From 9ed3f18893a1d5003b7a69df5e725b6f54530eaa Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Thu, 30 Oct 2025 10:39:30 -0500 Subject: [PATCH] preen --- .../thermostat/thermostat_climate.cpp | 18 ++++++++++++++++-- .../components/thermostat/thermostat_climate.h | 6 ++++++ tests/integration/test_climate_custom_modes.py | 4 +++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 18efe3984e..9b55a807c3 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -321,9 +321,15 @@ climate::ClimateTraits ThermostatClimate::traits() { for (auto &it : this->preset_config_) { traits.add_supported_preset(it.first); } - for (auto &it : this->custom_preset_config_) { - traits.add_supported_custom_preset(it.first); + + // Custom presets and fan modes are set directly from Python (includes all non-standard preset names from map) + if (!this->additional_custom_presets_.empty()) { + traits.set_supported_custom_presets(this->additional_custom_presets_); } + if (!this->additional_custom_fan_modes_.empty()) { + traits.set_supported_custom_fan_modes(this->additional_custom_fan_modes_); + } + return traits; } @@ -1613,6 +1619,14 @@ void ThermostatClimate::dump_config() { } } +void ThermostatClimate::set_custom_fan_modes(std::initializer_list custom_fan_modes) { + this->additional_custom_fan_modes_ = custom_fan_modes; +} + +void ThermostatClimate::set_custom_presets(std::initializer_list custom_presets) { + this->additional_custom_presets_ = custom_presets; +} + ThermostatClimateTargetTempConfig::ThermostatClimateTargetTempConfig() = default; ThermostatClimateTargetTempConfig::ThermostatClimateTargetTempConfig(float default_temperature) diff --git a/esphome/components/thermostat/thermostat_climate.h b/esphome/components/thermostat/thermostat_climate.h index 42adab7751..a160c5e1a1 100644 --- a/esphome/components/thermostat/thermostat_climate.h +++ b/esphome/components/thermostat/thermostat_climate.h @@ -133,6 +133,8 @@ class ThermostatClimate : public climate::Climate, public Component { void set_preset_config(climate::ClimatePreset preset, const ThermostatClimateTargetTempConfig &config); void set_custom_preset_config(const std::string &name, const ThermostatClimateTargetTempConfig &config); + void set_custom_fan_modes(std::initializer_list custom_fan_modes); + void set_custom_presets(std::initializer_list custom_presets); Trigger<> *get_cool_action_trigger() const; Trigger<> *get_supplemental_cool_action_trigger() const; @@ -537,6 +539,10 @@ class ThermostatClimate : public climate::Climate, public Component { std::map preset_config_{}; /// The set of custom preset configurations this thermostat supports (eg. "My Custom Preset") std::map custom_preset_config_{}; + /// Custom fan mode names (from Python codegen) + std::vector additional_custom_fan_modes_{}; + /// Custom preset names (from Python codegen) + std::vector additional_custom_presets_{}; }; } // namespace thermostat diff --git a/tests/integration/test_climate_custom_modes.py b/tests/integration/test_climate_custom_modes.py index d88b682ccd..4e0e8522ca 100644 --- a/tests/integration/test_climate_custom_modes.py +++ b/tests/integration/test_climate_custom_modes.py @@ -45,7 +45,9 @@ async def test_climate_custom_fan_modes_and_presets( f"Expected 3 custom presets, got {len(custom_presets)}: {custom_presets}" ) assert "Eco Plus" in custom_presets, "Expected 'Eco Plus' in custom presets" - assert "Comfort" in custom_presets, "Expected 'Comfort' in custom presets" + assert "Super Saver" in custom_presets, ( + "Expected 'Super Saver' in custom presets" + ) assert "Vacation Mode" in custom_presets, ( "Expected 'Vacation Mode' in custom presets" )