ESPHome 2025.12.0-dev
Loading...
Searching...
No Matches
select_call.cpp
Go to the documentation of this file.
1#include "select_call.h"
2#include "select.h"
3#include "esphome/core/log.h"
4
5namespace esphome {
6namespace select {
7
8static const char *const TAG = "select";
9
10SelectCall &SelectCall::set_option(const std::string &option) { return this->with_option(option); }
11
12SelectCall &SelectCall::set_option(const char *option) { return this->with_option(option); }
13
14SelectCall &SelectCall::set_index(size_t index) { return this->with_index(index); }
15
17
21
23
25
27 this->operation_ = operation;
28 return *this;
29}
30
32 this->cycle_ = cycle;
33 return *this;
34}
35
36SelectCall &SelectCall::with_option(const std::string &option) { return this->with_option(option.c_str()); }
37
38SelectCall &SelectCall::with_option(const char *option) {
40 // Find the option index - this validates the option exists
41 this->index_ = this->parent_->index_of(option);
42 return *this;
43}
44
47 if (index >= this->parent_->size()) {
48 ESP_LOGW(TAG, "'%s' - Index value %zu out of bounds", this->parent_->get_name().c_str(), index);
49 this->index_ = {}; // Store nullopt for invalid index
50 } else {
51 this->index_ = index;
52 }
53 return *this;
54}
55
56optional<size_t> SelectCall::calculate_target_index_(const char *name) {
57 const auto &options = this->parent_->traits.get_options();
58 if (options.empty()) {
59 ESP_LOGW(TAG, "'%s' - Select has no options", name);
60 return {};
61 }
62
63 if (this->operation_ == SELECT_OP_FIRST) {
64 return 0;
65 }
66
67 if (this->operation_ == SELECT_OP_LAST) {
68 return options.size() - 1;
69 }
70
71 if (this->operation_ == SELECT_OP_SET) {
72 ESP_LOGD(TAG, "'%s' - Setting", name);
73 if (!this->index_.has_value()) {
74 ESP_LOGW(TAG, "'%s' - No option set", name);
75 return {};
76 }
77 return this->index_.value();
78 }
79
80 // SELECT_OP_NEXT or SELECT_OP_PREVIOUS
81 ESP_LOGD(TAG, "'%s' - Selecting %s, with%s cycling", name,
82 this->operation_ == SELECT_OP_NEXT ? LOG_STR_LITERAL("next") : LOG_STR_LITERAL("previous"),
83 this->cycle_ ? LOG_STR_LITERAL("") : LOG_STR_LITERAL("out"));
84
85 const auto size = options.size();
86 if (!this->parent_->has_state()) {
87 return this->operation_ == SELECT_OP_NEXT ? 0 : size - 1;
88 }
89
90 // Use cached active_index_ instead of index_of() lookup
91 const auto active_index = this->parent_->active_index_;
92 if (this->cycle_) {
93 return (size + active_index + (this->operation_ == SELECT_OP_NEXT ? +1 : -1)) % size;
94 }
95
96 if (this->operation_ == SELECT_OP_PREVIOUS && active_index > 0) {
97 return active_index - 1;
98 }
99
100 if (this->operation_ == SELECT_OP_NEXT && active_index < size - 1) {
101 return active_index + 1;
102 }
103
104 return {}; // Can't navigate further without cycling
105}
106
108 auto *parent = this->parent_;
109 const auto *name = parent->get_name().c_str();
110
111 if (this->operation_ == SELECT_OP_NONE) {
112 ESP_LOGW(TAG, "'%s' - SelectCall performed without selecting an operation", name);
113 return;
114 }
115
116 // Calculate target index (with_index() and with_option() already validate bounds/existence)
117 auto target_index = this->calculate_target_index_(name);
118 if (!target_index.has_value()) {
119 return;
120 }
121
122 auto idx = target_index.value();
123 // All operations use indices, call control() by index to avoid string conversion
124 ESP_LOGD(TAG, "'%s' - Set selected option to: %s", name, parent->option_at(idx));
125 parent->control(idx);
126}
127
128} // namespace select
129} // namespace esphome
const StringRef & get_name() const
bool has_state() const
Definition entity_base.h:90
constexpr const char * c_str() const
Definition string_ref.h:69
bool has_value() const
Definition optional.h:92
value_type const & value() const
Definition optional.h:94
SelectCall & select_next(bool cycle)
SelectCall & with_index(size_t index)
optional< size_t > index_
Definition select_call.h:43
SelectCall & with_cycle(bool cycle)
SelectCall & select_previous(bool cycle)
SelectOperation operation_
Definition select_call.h:44
SelectCall & with_operation(SelectOperation operation)
SelectCall & set_index(size_t index)
SelectCall & set_option(const std::string &option)
SelectCall & with_option(const std::string &option)
size_t size() const
Return the number of options in this select component.
Definition select.cpp:55
optional< size_t > index_of(const std::string &option) const
Find the (optional) index offset of the provided option value.
Definition select.cpp:60
SelectTraits traits
Definition select.h:33
const FixedVector< const char * > & get_options() const
uint8_t options
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7