diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 54e9f1687c..61e279d4a6 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -974,9 +974,19 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { auto config = this->preset_config_.find(preset); if (config != this->preset_config_.end()) { - ESP_LOGI(TAG, "Switching to preset %s", LOG_STR_ARG(climate::climate_preset_to_string(preset))); - this->change_preset_internal_(config->second); + ESP_LOGI(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset))); + if (this->change_preset_internal_(config->second) || (!this->preset.has_value()) || + this->preset.value() != preset) { + // Fire any preset changed trigger if defined + Trigger<> *trig = this->preset_change_trigger_; + assert(trig != nullptr); + trig->trigger(); + this->refresh(); + ESP_LOGI(TAG, "Preset %s applied", LOG_STR_ARG(climate::climate_preset_to_string(preset))); + } else { + ESP_LOGI(TAG, "No changes required to apply preset %s", LOG_STR_ARG(climate::climate_preset_to_string(preset))); + } this->custom_preset.reset(); this->preset = preset; } else { @@ -988,9 +998,19 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) auto config = this->custom_preset_config_.find(custom_preset); if (config != this->custom_preset_config_.end()) { - ESP_LOGI(TAG, "Switching to custom preset %s", custom_preset.c_str()); - this->change_preset_internal_(config->second); + ESP_LOGI(TAG, "Custom preset %s requested", custom_preset.c_str()); + if (this->change_preset_internal_(config->second) || (!this->custom_preset.has_value()) || + this->custom_preset.value() != custom_preset) { + // Fire any preset changed trigger if defined + Trigger<> *trig = this->preset_change_trigger_; + assert(trig != nullptr); + trig->trigger(); + this->refresh(); + ESP_LOGI(TAG, "Custom preset %s applied", custom_preset.c_str()); + } else { + ESP_LOGI(TAG, "No changes required to apply custom preset %s", custom_preset.c_str()); + } this->preset.reset(); this->custom_preset = custom_preset; } else { @@ -998,39 +1018,46 @@ void ThermostatClimate::change_custom_preset_(const std::string &custom_preset) } } -void ThermostatClimate::change_preset_internal_(const ThermostatClimateTargetTempConfig &config) { +bool ThermostatClimate::change_preset_internal_(const ThermostatClimateTargetTempConfig &config) { + bool something_changed = false; + if (this->supports_two_points_) { - this->target_temperature_low = config.default_temperature_low; - this->target_temperature_high = config.default_temperature_high; + if (this->target_temperature_low != config.default_temperature_low) { + this->target_temperature_low = config.default_temperature_low; + something_changed = true; + } + if (this->target_temperature_high != config.default_temperature_high) { + this->target_temperature_high = config.default_temperature_high; + something_changed = true; + } } else { - this->target_temperature = config.default_temperature; + if (this->target_temperature != config.default_temperature) { + this->target_temperature = config.default_temperature; + something_changed = true; + } } - // Note: The mode, fan_mode, and swing_mode can all be defined on the preset but if the climate.control call - // also specifies them then the control's version will override these for that call - if (config.mode_.has_value()) { - this->mode = *config.mode_; + // Note: The mode, fan_mode and swing_mode can all be defined in the preset but if the climate.control call + // also specifies them then the climate.control call's values will override the preset's values for that call + if (config.mode_.has_value() && (this->mode != config.mode_.value())) { ESP_LOGV(TAG, "Setting mode to %s", LOG_STR_ARG(climate::climate_mode_to_string(*config.mode_))); + this->mode = *config.mode_; + something_changed = true; } - if (config.fan_mode_.has_value()) { - this->fan_mode = *config.fan_mode_; + if (config.fan_mode_.has_value() && (this->fan_mode != config.fan_mode_.value())) { ESP_LOGV(TAG, "Setting fan mode to %s", LOG_STR_ARG(climate::climate_fan_mode_to_string(*config.fan_mode_))); + this->fan_mode = *config.fan_mode_; + something_changed = true; } - if (config.swing_mode_.has_value()) { + if (config.swing_mode_.has_value() && (this->swing_mode != config.swing_mode_.value())) { ESP_LOGV(TAG, "Setting swing mode to %s", LOG_STR_ARG(climate::climate_swing_mode_to_string(*config.swing_mode_))); this->swing_mode = *config.swing_mode_; + something_changed = true; } - // Fire any preset changed trigger if defined - if (this->preset != preset) { - Trigger<> *trig = this->preset_change_trigger_; - assert(trig != nullptr); - trig->trigger(); - } - - this->refresh(); + return something_changed; } void ThermostatClimate::set_preset_config(climate::ClimatePreset preset, diff --git a/esphome/components/thermostat/thermostat_climate.h b/esphome/components/thermostat/thermostat_climate.h index a738ba4986..68cbb17e34 100644 --- a/esphome/components/thermostat/thermostat_climate.h +++ b/esphome/components/thermostat/thermostat_climate.h @@ -168,7 +168,8 @@ class ThermostatClimate : public climate::Climate, public Component { /// Applies the temperature, mode, fan, and swing modes of the provided config. /// This is agnostic of custom vs built in preset - void change_preset_internal_(const ThermostatClimateTargetTempConfig &config); + /// Returns true if something was changed + bool change_preset_internal_(const ThermostatClimateTargetTempConfig &config); /// Return the traits of this controller. climate::ClimateTraits traits() override;