From ad5752f68e4c543ae57e509ffec67c0c964bbca1 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 30 Oct 2025 13:25:31 -0500 Subject: [PATCH] give people time to migrate since we can --- esphome/components/select/select.cpp | 1 + esphome/components/select/select.h | 19 +++++++++++++++---- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/esphome/components/select/select.cpp b/esphome/components/select/select.cpp index 0c05a7b3bf..e495ab4a44 100644 --- a/esphome/components/select/select.cpp +++ b/esphome/components/select/select.cpp @@ -26,6 +26,7 @@ void Select::publish_state(size_t index) { const char *option = this->option_at(index); this->set_has_state(true); this->active_index_ = index; + this->state = option; // Update deprecated member for backward compatibility ESP_LOGD(TAG, "'%s': Sending state %s (index %zu)", this->get_name().c_str(), option, index); // Callback signature requires std::string, create temporary for compatibility this->state_callback_.call(std::string(option), index); diff --git a/esphome/components/select/select.h b/esphome/components/select/select.h index 801074a4d5..26e5c6dbde 100644 --- a/esphome/components/select/select.h +++ b/esphome/components/select/select.h @@ -32,6 +32,9 @@ class Select : public EntityBase { public: SelectTraits traits; + /// @deprecated Use current_option() instead. This member will be removed in a future release. + __attribute__((deprecated("Use current_option() instead of .state"))) std::string state{}; + void publish_state(const std::string &state); void publish_state(const char *state); void publish_state(size_t index); @@ -82,11 +85,14 @@ class Select : public EntityBase { size_t active_index_{0}; - /** Set the value of the select, this is a virtual method that each select integration must implement. + /** Set the value of the select, this is a virtual method that each select integration can implement. * * This method is called by control(size_t) when not overridden, or directly by external code. - * All existing integrations implement this method. New integrations can optionally override - * control(size_t) instead to work with indices directly and avoid string conversions. + * Integrations can either: + * 1. Override this method to handle string-based control (traditional approach) + * 2. Override control(size_t) instead to work with indices directly (recommended) + * + * Default implementation converts to index and calls control(size_t). * * Delegation chain: * - SelectCall::perform() → control(size_t) → [if not overridden] → control(string) @@ -94,7 +100,12 @@ class Select : public EntityBase { * * @param value The value as validated by the SelectCall. */ - virtual void control(const std::string &value) = 0; + virtual void control(const std::string &value) { + auto index = this->index_of(value); + if (index.has_value()) { + this->control(index.value()); + } + } CallbackManager state_callback_; };