diff --git a/esphome/components/climate/climate.cpp b/esphome/components/climate/climate.cpp index 51d91469c17..19a71959aac 100644 --- a/esphome/components/climate/climate.cpp +++ b/esphome/components/climate/climate.cpp @@ -485,10 +485,10 @@ void Climate::publish_state() { ClimateTraits Climate::get_traits() { auto traits = this->traits(); // Wire custom mode pointers from Climate-owned storage - if (!this->supported_custom_fan_modes_.empty()) - traits.set_supported_custom_fan_modes(&this->supported_custom_fan_modes_); - if (!this->supported_custom_presets_.empty()) - traits.set_supported_custom_presets(&this->supported_custom_presets_); + if (this->supported_custom_fan_modes_) + traits.set_supported_custom_fan_modes(this->supported_custom_fan_modes_); + if (this->supported_custom_presets_) + traits.set_supported_custom_presets(this->supported_custom_presets_); #ifdef USE_CLIMATE_VISUAL_OVERRIDES if (!std::isnan(this->visual_min_temperature_override_)) { traits.set_visual_min_temperature(this->visual_min_temperature_override_); @@ -706,7 +706,8 @@ const char *Climate::find_custom_fan_mode_(const char *custom_fan_mode) { } const char *Climate::find_custom_fan_mode_(const char *custom_fan_mode, size_t len) { - return vector_find(this->supported_custom_fan_modes_, custom_fan_mode, len); + return this->supported_custom_fan_modes_ ? vector_find(*this->supported_custom_fan_modes_, custom_fan_mode, len) + : nullptr; } const char *Climate::find_custom_preset_(const char *custom_preset) { @@ -714,7 +715,7 @@ const char *Climate::find_custom_preset_(const char *custom_preset) { } const char *Climate::find_custom_preset_(const char *custom_preset, size_t len) { - return vector_find(this->supported_custom_presets_, custom_preset, len); + return this->supported_custom_presets_ ? vector_find(*this->supported_custom_presets_, custom_preset, len) : nullptr; } void Climate::dump_traits_(const char *tag) { diff --git a/esphome/components/climate/climate.h b/esphome/components/climate/climate.h index 6214afcbe32..69ea192456e 100644 --- a/esphome/components/climate/climate.h +++ b/esphome/components/climate/climate.h @@ -236,24 +236,37 @@ class Climate : public EntityBase { /// Set the supported custom fan modes (stored on Climate, referenced by ClimateTraits). void set_supported_custom_fan_modes(std::initializer_list modes) { - this->supported_custom_fan_modes_ = modes; + if (!this->supported_custom_fan_modes_) + this->supported_custom_fan_modes_ = + new std::vector(); // NOLINT - intentional leak, entity lives forever + *this->supported_custom_fan_modes_ = modes; } void set_supported_custom_fan_modes(const std::vector &modes) { - this->supported_custom_fan_modes_ = modes; + if (!this->supported_custom_fan_modes_) + this->supported_custom_fan_modes_ = new std::vector(); // NOLINT + *this->supported_custom_fan_modes_ = modes; } template void set_supported_custom_fan_modes(const char *const (&modes)[N]) { - this->supported_custom_fan_modes_.assign(modes, modes + N); + if (!this->supported_custom_fan_modes_) + this->supported_custom_fan_modes_ = new std::vector(); // NOLINT + this->supported_custom_fan_modes_->assign(modes, modes + N); } /// Set the supported custom presets (stored on Climate, referenced by ClimateTraits). void set_supported_custom_presets(std::initializer_list presets) { - this->supported_custom_presets_ = presets; + if (!this->supported_custom_presets_) + this->supported_custom_presets_ = new std::vector(); // NOLINT + *this->supported_custom_presets_ = presets; } void set_supported_custom_presets(const std::vector &presets) { - this->supported_custom_presets_ = presets; + if (!this->supported_custom_presets_) + this->supported_custom_presets_ = new std::vector(); // NOLINT + *this->supported_custom_presets_ = presets; } template void set_supported_custom_presets(const char *const (&presets)[N]) { - this->supported_custom_presets_.assign(presets, presets + N); + if (!this->supported_custom_presets_) + this->supported_custom_presets_ = new std::vector(); // NOLINT + this->supported_custom_presets_->assign(presets, presets + N); } /// Check if a custom fan mode is currently active. @@ -366,11 +379,11 @@ class Climate : public EntityBase { LazyCallbackManager control_callback_{}; ESPPreferenceObject rtc_; - /** Custom mode storage - owned by Climate, referenced by ClimateTraits via pointer. + /** Custom mode storage — allocated on first use, never freed (entity lives forever). * Pointers in these vectors must point to string literals or static data. */ - std::vector supported_custom_fan_modes_; - std::vector supported_custom_presets_; + std::vector *supported_custom_fan_modes_{nullptr}; + std::vector *supported_custom_presets_{nullptr}; #ifdef USE_CLIMATE_VISUAL_OVERRIDES float visual_min_temperature_override_{NAN};