From 29f8d70b35d16cb8296d1a0496e4b4ce0679008f Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:41:08 +0100 Subject: [PATCH 01/12] [thermostat] Avoid heap allocation for triggers (#13692) --- .../thermostat/thermostat_climate.cpp | 220 +++++++----------- .../thermostat/thermostat_climate.h | 212 +++++++---------- 2 files changed, 170 insertions(+), 262 deletions(-) diff --git a/esphome/components/thermostat/thermostat_climate.cpp b/esphome/components/thermostat/thermostat_climate.cpp index 44087969b5..02e01db549 100644 --- a/esphome/components/thermostat/thermostat_climate.cpp +++ b/esphome/components/thermostat/thermostat_climate.cpp @@ -499,7 +499,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } bool action_ready = false; - Trigger<> *trig = this->idle_action_trigger_, *trig_fan = nullptr; + Trigger<> *trig = &this->idle_action_trigger_, *trig_fan = nullptr; switch (action) { case climate::CLIMATE_ACTION_OFF: case climate::CLIMATE_ACTION_IDLE: @@ -529,10 +529,10 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME); if (this->supports_fan_with_cooling_) { this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); - trig_fan = this->fan_only_action_trigger_; + trig_fan = &this->fan_only_action_trigger_; } this->cooling_max_runtime_exceeded_ = false; - trig = this->cool_action_trigger_; + trig = &this->cool_action_trigger_; ESP_LOGVV(TAG, "Switching to COOLING action"); action_ready = true; } @@ -543,10 +543,10 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu this->start_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME); if (this->supports_fan_with_heating_) { this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); - trig_fan = this->fan_only_action_trigger_; + trig_fan = &this->fan_only_action_trigger_; } this->heating_max_runtime_exceeded_ = false; - trig = this->heat_action_trigger_; + trig = &this->heat_action_trigger_; ESP_LOGVV(TAG, "Switching to HEATING action"); action_ready = true; } @@ -558,7 +558,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu } else { this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); } - trig = this->fan_only_action_trigger_; + trig = &this->fan_only_action_trigger_; ESP_LOGVV(TAG, "Switching to FAN_ONLY action"); action_ready = true; } @@ -567,7 +567,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu if (this->drying_action_ready_()) { this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_ON); this->start_timer_(thermostat::THERMOSTAT_TIMER_FANNING_ON); - trig = this->dry_action_trigger_; + trig = &this->dry_action_trigger_; ESP_LOGVV(TAG, "Switching to DRYING action"); action_ready = true; } @@ -634,14 +634,14 @@ void ThermostatClimate::trigger_supplemental_action_() { if (!this->timer_active_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME)) { this->start_timer_(thermostat::THERMOSTAT_TIMER_COOLING_MAX_RUN_TIME); } - trig = this->supplemental_cool_action_trigger_; + trig = &this->supplemental_cool_action_trigger_; ESP_LOGVV(TAG, "Calling supplemental COOLING action"); break; case climate::CLIMATE_ACTION_HEATING: if (!this->timer_active_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME)) { this->start_timer_(thermostat::THERMOSTAT_TIMER_HEATING_MAX_RUN_TIME); } - trig = this->supplemental_heat_action_trigger_; + trig = &this->supplemental_heat_action_trigger_; ESP_LOGVV(TAG, "Calling supplemental HEATING action"); break; default: @@ -660,24 +660,24 @@ void ThermostatClimate::switch_to_humidity_control_action_(HumidificationAction return; } - Trigger<> *trig = this->humidity_control_off_action_trigger_; + Trigger<> *trig = &this->humidity_control_off_action_trigger_; switch (action) { case THERMOSTAT_HUMIDITY_CONTROL_ACTION_OFF: - // trig = this->humidity_control_off_action_trigger_; + // trig = &this->humidity_control_off_action_trigger_; ESP_LOGVV(TAG, "Switching to HUMIDIFICATION_OFF action"); break; case THERMOSTAT_HUMIDITY_CONTROL_ACTION_DEHUMIDIFY: - trig = this->humidity_control_dehumidify_action_trigger_; + trig = &this->humidity_control_dehumidify_action_trigger_; ESP_LOGVV(TAG, "Switching to DEHUMIDIFY action"); break; case THERMOSTAT_HUMIDITY_CONTROL_ACTION_HUMIDIFY: - trig = this->humidity_control_humidify_action_trigger_; + trig = &this->humidity_control_humidify_action_trigger_; ESP_LOGVV(TAG, "Switching to HUMIDIFY action"); break; case THERMOSTAT_HUMIDITY_CONTROL_ACTION_NONE: default: action = THERMOSTAT_HUMIDITY_CONTROL_ACTION_OFF; - // trig = this->humidity_control_off_action_trigger_; + // trig = &this->humidity_control_off_action_trigger_; } if (this->prev_humidity_control_trigger_ != nullptr) { @@ -703,53 +703,53 @@ void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bo this->publish_state(); if (this->fan_mode_ready_()) { - Trigger<> *trig = this->fan_mode_auto_trigger_; + Trigger<> *trig = &this->fan_mode_auto_trigger_; switch (fan_mode) { case climate::CLIMATE_FAN_ON: - trig = this->fan_mode_on_trigger_; + trig = &this->fan_mode_on_trigger_; ESP_LOGVV(TAG, "Switching to FAN_ON mode"); break; case climate::CLIMATE_FAN_OFF: - trig = this->fan_mode_off_trigger_; + trig = &this->fan_mode_off_trigger_; ESP_LOGVV(TAG, "Switching to FAN_OFF mode"); break; case climate::CLIMATE_FAN_AUTO: - // trig = this->fan_mode_auto_trigger_; + // trig = &this->fan_mode_auto_trigger_; ESP_LOGVV(TAG, "Switching to FAN_AUTO mode"); break; case climate::CLIMATE_FAN_LOW: - trig = this->fan_mode_low_trigger_; + trig = &this->fan_mode_low_trigger_; ESP_LOGVV(TAG, "Switching to FAN_LOW mode"); break; case climate::CLIMATE_FAN_MEDIUM: - trig = this->fan_mode_medium_trigger_; + trig = &this->fan_mode_medium_trigger_; ESP_LOGVV(TAG, "Switching to FAN_MEDIUM mode"); break; case climate::CLIMATE_FAN_HIGH: - trig = this->fan_mode_high_trigger_; + trig = &this->fan_mode_high_trigger_; ESP_LOGVV(TAG, "Switching to FAN_HIGH mode"); break; case climate::CLIMATE_FAN_MIDDLE: - trig = this->fan_mode_middle_trigger_; + trig = &this->fan_mode_middle_trigger_; ESP_LOGVV(TAG, "Switching to FAN_MIDDLE mode"); break; case climate::CLIMATE_FAN_FOCUS: - trig = this->fan_mode_focus_trigger_; + trig = &this->fan_mode_focus_trigger_; ESP_LOGVV(TAG, "Switching to FAN_FOCUS mode"); break; case climate::CLIMATE_FAN_DIFFUSE: - trig = this->fan_mode_diffuse_trigger_; + trig = &this->fan_mode_diffuse_trigger_; ESP_LOGVV(TAG, "Switching to FAN_DIFFUSE mode"); break; case climate::CLIMATE_FAN_QUIET: - trig = this->fan_mode_quiet_trigger_; + trig = &this->fan_mode_quiet_trigger_; ESP_LOGVV(TAG, "Switching to FAN_QUIET mode"); break; default: // we cannot report an invalid mode back to HA (even if it asked for one) // and must assume some valid value fan_mode = climate::CLIMATE_FAN_AUTO; - // trig = this->fan_mode_auto_trigger_; + // trig = &this->fan_mode_auto_trigger_; } if (this->prev_fan_mode_trigger_ != nullptr) { this->prev_fan_mode_trigger_->stop_action(); @@ -775,25 +775,25 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_ this->prev_mode_trigger_->stop_action(); this->prev_mode_trigger_ = nullptr; } - Trigger<> *trig = this->off_mode_trigger_; + Trigger<> *trig = &this->off_mode_trigger_; switch (mode) { case climate::CLIMATE_MODE_AUTO: - trig = this->auto_mode_trigger_; + trig = &this->auto_mode_trigger_; break; case climate::CLIMATE_MODE_HEAT_COOL: - trig = this->heat_cool_mode_trigger_; + trig = &this->heat_cool_mode_trigger_; break; case climate::CLIMATE_MODE_COOL: - trig = this->cool_mode_trigger_; + trig = &this->cool_mode_trigger_; break; case climate::CLIMATE_MODE_HEAT: - trig = this->heat_mode_trigger_; + trig = &this->heat_mode_trigger_; break; case climate::CLIMATE_MODE_FAN_ONLY: - trig = this->fan_only_mode_trigger_; + trig = &this->fan_only_mode_trigger_; break; case climate::CLIMATE_MODE_DRY: - trig = this->dry_mode_trigger_; + trig = &this->dry_mode_trigger_; break; case climate::CLIMATE_MODE_OFF: default: @@ -824,25 +824,25 @@ void ThermostatClimate::switch_to_swing_mode_(climate::ClimateSwingMode swing_mo this->prev_swing_mode_trigger_->stop_action(); this->prev_swing_mode_trigger_ = nullptr; } - Trigger<> *trig = this->swing_mode_off_trigger_; + Trigger<> *trig = &this->swing_mode_off_trigger_; switch (swing_mode) { case climate::CLIMATE_SWING_BOTH: - trig = this->swing_mode_both_trigger_; + trig = &this->swing_mode_both_trigger_; break; case climate::CLIMATE_SWING_HORIZONTAL: - trig = this->swing_mode_horizontal_trigger_; + trig = &this->swing_mode_horizontal_trigger_; break; case climate::CLIMATE_SWING_OFF: - // trig = this->swing_mode_off_trigger_; + // trig = &this->swing_mode_off_trigger_; break; case climate::CLIMATE_SWING_VERTICAL: - trig = this->swing_mode_vertical_trigger_; + trig = &this->swing_mode_vertical_trigger_; break; default: // we cannot report an invalid mode back to HA (even if it asked for one) // and must assume some valid value swing_mode = climate::CLIMATE_SWING_OFF; - // trig = this->swing_mode_off_trigger_; + // trig = &this->swing_mode_off_trigger_; } if (trig != nullptr) { trig->trigger(); @@ -1024,10 +1024,8 @@ void ThermostatClimate::check_humidity_change_trigger_() { this->prev_target_humidity_ = this->target_humidity; } // trigger the action - Trigger<> *trig = this->humidity_change_trigger_; - if (trig != nullptr) { - trig->trigger(); - } + Trigger<> *trig = &this->humidity_change_trigger_; + trig->trigger(); } void ThermostatClimate::check_temperature_change_trigger_() { @@ -1050,10 +1048,8 @@ void ThermostatClimate::check_temperature_change_trigger_() { } } // trigger the action - Trigger<> *trig = this->temperature_change_trigger_; - if (trig != nullptr) { - trig->trigger(); - } + Trigger<> *trig = &this->temperature_change_trigger_; + trig->trigger(); } bool ThermostatClimate::cooling_required_() { @@ -1202,12 +1198,10 @@ void ThermostatClimate::change_preset_(climate::ClimatePreset preset) { if (config != nullptr) { ESP_LOGV(TAG, "Preset %s requested", LOG_STR_ARG(climate::climate_preset_to_string(preset))); if (this->change_preset_internal_(*config) || (!this->preset.has_value()) || this->preset.value() != preset) { - // Fire any preset changed trigger if defined - Trigger<> *trig = this->preset_change_trigger_; + // Fire preset changed trigger + Trigger<> *trig = &this->preset_change_trigger_; this->set_preset_(preset); - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->refresh(); ESP_LOGI(TAG, "Preset %s applied", LOG_STR_ARG(climate::climate_preset_to_string(preset))); @@ -1234,13 +1228,11 @@ void ThermostatClimate::change_custom_preset_(const char *custom_preset, size_t ESP_LOGV(TAG, "Custom preset %s requested", custom_preset); if (this->change_preset_internal_(*config) || !this->has_custom_preset() || this->get_custom_preset() != custom_preset) { - // Fire any preset changed trigger if defined - Trigger<> *trig = this->preset_change_trigger_; + // Fire preset changed trigger + Trigger<> *trig = &this->preset_change_trigger_; // Use the base class method which handles pointer lookup and preset reset internally this->set_custom_preset_(custom_preset); - if (trig != nullptr) { - trig->trigger(); - } + trig->trigger(); this->refresh(); ESP_LOGI(TAG, "Custom preset %s applied", custom_preset); @@ -1305,41 +1297,7 @@ void ThermostatClimate::set_custom_preset_config(std::initializer_listcustom_preset_config_ = presets; } -ThermostatClimate::ThermostatClimate() - : cool_action_trigger_(new Trigger<>()), - supplemental_cool_action_trigger_(new Trigger<>()), - cool_mode_trigger_(new Trigger<>()), - dry_action_trigger_(new Trigger<>()), - dry_mode_trigger_(new Trigger<>()), - heat_action_trigger_(new Trigger<>()), - supplemental_heat_action_trigger_(new Trigger<>()), - heat_mode_trigger_(new Trigger<>()), - heat_cool_mode_trigger_(new Trigger<>()), - auto_mode_trigger_(new Trigger<>()), - idle_action_trigger_(new Trigger<>()), - off_mode_trigger_(new Trigger<>()), - fan_only_action_trigger_(new Trigger<>()), - fan_only_mode_trigger_(new Trigger<>()), - fan_mode_on_trigger_(new Trigger<>()), - fan_mode_off_trigger_(new Trigger<>()), - fan_mode_auto_trigger_(new Trigger<>()), - fan_mode_low_trigger_(new Trigger<>()), - fan_mode_medium_trigger_(new Trigger<>()), - fan_mode_high_trigger_(new Trigger<>()), - fan_mode_middle_trigger_(new Trigger<>()), - fan_mode_focus_trigger_(new Trigger<>()), - fan_mode_diffuse_trigger_(new Trigger<>()), - fan_mode_quiet_trigger_(new Trigger<>()), - swing_mode_both_trigger_(new Trigger<>()), - swing_mode_off_trigger_(new Trigger<>()), - swing_mode_horizontal_trigger_(new Trigger<>()), - swing_mode_vertical_trigger_(new Trigger<>()), - humidity_change_trigger_(new Trigger<>()), - temperature_change_trigger_(new Trigger<>()), - preset_change_trigger_(new Trigger<>()), - humidity_control_dehumidify_action_trigger_(new Trigger<>()), - humidity_control_humidify_action_trigger_(new Trigger<>()), - humidity_control_off_action_trigger_(new Trigger<>()) {} +ThermostatClimate::ThermostatClimate() = default; void ThermostatClimate::set_default_preset(const char *custom_preset) { // Find the preset in custom_preset_config_ and store pointer from there @@ -1513,49 +1471,49 @@ void ThermostatClimate::set_supports_humidification(bool supports_humidification } } -Trigger<> *ThermostatClimate::get_cool_action_trigger() const { return this->cool_action_trigger_; } -Trigger<> *ThermostatClimate::get_supplemental_cool_action_trigger() const { - return this->supplemental_cool_action_trigger_; +Trigger<> *ThermostatClimate::get_cool_action_trigger() { return &this->cool_action_trigger_; } +Trigger<> *ThermostatClimate::get_supplemental_cool_action_trigger() { + return &this->supplemental_cool_action_trigger_; } -Trigger<> *ThermostatClimate::get_dry_action_trigger() const { return this->dry_action_trigger_; } -Trigger<> *ThermostatClimate::get_fan_only_action_trigger() const { return this->fan_only_action_trigger_; } -Trigger<> *ThermostatClimate::get_heat_action_trigger() const { return this->heat_action_trigger_; } -Trigger<> *ThermostatClimate::get_supplemental_heat_action_trigger() const { - return this->supplemental_heat_action_trigger_; +Trigger<> *ThermostatClimate::get_dry_action_trigger() { return &this->dry_action_trigger_; } +Trigger<> *ThermostatClimate::get_fan_only_action_trigger() { return &this->fan_only_action_trigger_; } +Trigger<> *ThermostatClimate::get_heat_action_trigger() { return &this->heat_action_trigger_; } +Trigger<> *ThermostatClimate::get_supplemental_heat_action_trigger() { + return &this->supplemental_heat_action_trigger_; } -Trigger<> *ThermostatClimate::get_idle_action_trigger() const { return this->idle_action_trigger_; } -Trigger<> *ThermostatClimate::get_auto_mode_trigger() const { return this->auto_mode_trigger_; } -Trigger<> *ThermostatClimate::get_cool_mode_trigger() const { return this->cool_mode_trigger_; } -Trigger<> *ThermostatClimate::get_dry_mode_trigger() const { return this->dry_mode_trigger_; } -Trigger<> *ThermostatClimate::get_fan_only_mode_trigger() const { return this->fan_only_mode_trigger_; } -Trigger<> *ThermostatClimate::get_heat_mode_trigger() const { return this->heat_mode_trigger_; } -Trigger<> *ThermostatClimate::get_heat_cool_mode_trigger() const { return this->heat_cool_mode_trigger_; } -Trigger<> *ThermostatClimate::get_off_mode_trigger() const { return this->off_mode_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_on_trigger() const { return this->fan_mode_on_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_off_trigger() const { return this->fan_mode_off_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_auto_trigger() const { return this->fan_mode_auto_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_low_trigger() const { return this->fan_mode_low_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_medium_trigger() const { return this->fan_mode_medium_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_high_trigger() const { return this->fan_mode_high_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_middle_trigger() const { return this->fan_mode_middle_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_focus_trigger() const { return this->fan_mode_focus_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_diffuse_trigger() const { return this->fan_mode_diffuse_trigger_; } -Trigger<> *ThermostatClimate::get_fan_mode_quiet_trigger() const { return this->fan_mode_quiet_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_both_trigger() const { return this->swing_mode_both_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_off_trigger() const { return this->swing_mode_off_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_horizontal_trigger() const { return this->swing_mode_horizontal_trigger_; } -Trigger<> *ThermostatClimate::get_swing_mode_vertical_trigger() const { return this->swing_mode_vertical_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_change_trigger() const { return this->humidity_change_trigger_; } -Trigger<> *ThermostatClimate::get_temperature_change_trigger() const { return this->temperature_change_trigger_; } -Trigger<> *ThermostatClimate::get_preset_change_trigger() const { return this->preset_change_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_control_dehumidify_action_trigger() const { - return this->humidity_control_dehumidify_action_trigger_; +Trigger<> *ThermostatClimate::get_idle_action_trigger() { return &this->idle_action_trigger_; } +Trigger<> *ThermostatClimate::get_auto_mode_trigger() { return &this->auto_mode_trigger_; } +Trigger<> *ThermostatClimate::get_cool_mode_trigger() { return &this->cool_mode_trigger_; } +Trigger<> *ThermostatClimate::get_dry_mode_trigger() { return &this->dry_mode_trigger_; } +Trigger<> *ThermostatClimate::get_fan_only_mode_trigger() { return &this->fan_only_mode_trigger_; } +Trigger<> *ThermostatClimate::get_heat_mode_trigger() { return &this->heat_mode_trigger_; } +Trigger<> *ThermostatClimate::get_heat_cool_mode_trigger() { return &this->heat_cool_mode_trigger_; } +Trigger<> *ThermostatClimate::get_off_mode_trigger() { return &this->off_mode_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_on_trigger() { return &this->fan_mode_on_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_off_trigger() { return &this->fan_mode_off_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_auto_trigger() { return &this->fan_mode_auto_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_low_trigger() { return &this->fan_mode_low_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_medium_trigger() { return &this->fan_mode_medium_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_high_trigger() { return &this->fan_mode_high_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_middle_trigger() { return &this->fan_mode_middle_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_focus_trigger() { return &this->fan_mode_focus_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_diffuse_trigger() { return &this->fan_mode_diffuse_trigger_; } +Trigger<> *ThermostatClimate::get_fan_mode_quiet_trigger() { return &this->fan_mode_quiet_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_both_trigger() { return &this->swing_mode_both_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_off_trigger() { return &this->swing_mode_off_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_horizontal_trigger() { return &this->swing_mode_horizontal_trigger_; } +Trigger<> *ThermostatClimate::get_swing_mode_vertical_trigger() { return &this->swing_mode_vertical_trigger_; } +Trigger<> *ThermostatClimate::get_humidity_change_trigger() { return &this->humidity_change_trigger_; } +Trigger<> *ThermostatClimate::get_temperature_change_trigger() { return &this->temperature_change_trigger_; } +Trigger<> *ThermostatClimate::get_preset_change_trigger() { return &this->preset_change_trigger_; } +Trigger<> *ThermostatClimate::get_humidity_control_dehumidify_action_trigger() { + return &this->humidity_control_dehumidify_action_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_control_humidify_action_trigger() const { - return this->humidity_control_humidify_action_trigger_; +Trigger<> *ThermostatClimate::get_humidity_control_humidify_action_trigger() { + return &this->humidity_control_humidify_action_trigger_; } -Trigger<> *ThermostatClimate::get_humidity_control_off_action_trigger() const { - return this->humidity_control_off_action_trigger_; +Trigger<> *ThermostatClimate::get_humidity_control_off_action_trigger() { + return &this->humidity_control_off_action_trigger_; } void ThermostatClimate::dump_config() { diff --git a/esphome/components/thermostat/thermostat_climate.h b/esphome/components/thermostat/thermostat_climate.h index d37c9a68a6..4268d5c582 100644 --- a/esphome/components/thermostat/thermostat_climate.h +++ b/esphome/components/thermostat/thermostat_climate.h @@ -146,40 +146,40 @@ class ThermostatClimate : public climate::Climate, public Component { void set_preset_config(std::initializer_list presets); void set_custom_preset_config(std::initializer_list presets); - Trigger<> *get_cool_action_trigger() const; - Trigger<> *get_supplemental_cool_action_trigger() const; - Trigger<> *get_dry_action_trigger() const; - Trigger<> *get_fan_only_action_trigger() const; - Trigger<> *get_heat_action_trigger() const; - Trigger<> *get_supplemental_heat_action_trigger() const; - Trigger<> *get_idle_action_trigger() const; - Trigger<> *get_auto_mode_trigger() const; - Trigger<> *get_cool_mode_trigger() const; - Trigger<> *get_dry_mode_trigger() const; - Trigger<> *get_fan_only_mode_trigger() const; - Trigger<> *get_heat_mode_trigger() const; - Trigger<> *get_heat_cool_mode_trigger() const; - Trigger<> *get_off_mode_trigger() const; - Trigger<> *get_fan_mode_on_trigger() const; - Trigger<> *get_fan_mode_off_trigger() const; - Trigger<> *get_fan_mode_auto_trigger() const; - Trigger<> *get_fan_mode_low_trigger() const; - Trigger<> *get_fan_mode_medium_trigger() const; - Trigger<> *get_fan_mode_high_trigger() const; - Trigger<> *get_fan_mode_middle_trigger() const; - Trigger<> *get_fan_mode_focus_trigger() const; - Trigger<> *get_fan_mode_diffuse_trigger() const; - Trigger<> *get_fan_mode_quiet_trigger() const; - Trigger<> *get_swing_mode_both_trigger() const; - Trigger<> *get_swing_mode_horizontal_trigger() const; - Trigger<> *get_swing_mode_off_trigger() const; - Trigger<> *get_swing_mode_vertical_trigger() const; - Trigger<> *get_humidity_change_trigger() const; - Trigger<> *get_temperature_change_trigger() const; - Trigger<> *get_preset_change_trigger() const; - Trigger<> *get_humidity_control_dehumidify_action_trigger() const; - Trigger<> *get_humidity_control_humidify_action_trigger() const; - Trigger<> *get_humidity_control_off_action_trigger() const; + Trigger<> *get_cool_action_trigger(); + Trigger<> *get_supplemental_cool_action_trigger(); + Trigger<> *get_dry_action_trigger(); + Trigger<> *get_fan_only_action_trigger(); + Trigger<> *get_heat_action_trigger(); + Trigger<> *get_supplemental_heat_action_trigger(); + Trigger<> *get_idle_action_trigger(); + Trigger<> *get_auto_mode_trigger(); + Trigger<> *get_cool_mode_trigger(); + Trigger<> *get_dry_mode_trigger(); + Trigger<> *get_fan_only_mode_trigger(); + Trigger<> *get_heat_mode_trigger(); + Trigger<> *get_heat_cool_mode_trigger(); + Trigger<> *get_off_mode_trigger(); + Trigger<> *get_fan_mode_on_trigger(); + Trigger<> *get_fan_mode_off_trigger(); + Trigger<> *get_fan_mode_auto_trigger(); + Trigger<> *get_fan_mode_low_trigger(); + Trigger<> *get_fan_mode_medium_trigger(); + Trigger<> *get_fan_mode_high_trigger(); + Trigger<> *get_fan_mode_middle_trigger(); + Trigger<> *get_fan_mode_focus_trigger(); + Trigger<> *get_fan_mode_diffuse_trigger(); + Trigger<> *get_fan_mode_quiet_trigger(); + Trigger<> *get_swing_mode_both_trigger(); + Trigger<> *get_swing_mode_horizontal_trigger(); + Trigger<> *get_swing_mode_off_trigger(); + Trigger<> *get_swing_mode_vertical_trigger(); + Trigger<> *get_humidity_change_trigger(); + Trigger<> *get_temperature_change_trigger(); + Trigger<> *get_preset_change_trigger(); + Trigger<> *get_humidity_control_dehumidify_action_trigger(); + Trigger<> *get_humidity_control_humidify_action_trigger(); + Trigger<> *get_humidity_control_off_action_trigger(); /// Get current hysteresis values float cool_deadband(); float cool_overrun(); @@ -417,115 +417,65 @@ class ThermostatClimate : public climate::Climate, public Component { /// The sensor used for getting the current humidity sensor::Sensor *humidity_sensor_{nullptr}; - /// The trigger to call when the controller should switch to cooling action/mode. - /// - /// A null value for this attribute means that the controller has no cooling action - /// For example electric heat, where only heating (power on) and not-heating - /// (power off) is possible. - Trigger<> *cool_action_trigger_{nullptr}; - Trigger<> *supplemental_cool_action_trigger_{nullptr}; - Trigger<> *cool_mode_trigger_{nullptr}; + /// Trigger for cooling action/mode + Trigger<> cool_action_trigger_; + Trigger<> supplemental_cool_action_trigger_; + Trigger<> cool_mode_trigger_; - /// The trigger to call when the controller should switch to dry (dehumidification) mode. - /// - /// In dry mode, the controller is assumed to have both heating and cooling disabled, - /// although the system may use its cooling mechanism to achieve drying. - Trigger<> *dry_action_trigger_{nullptr}; - Trigger<> *dry_mode_trigger_{nullptr}; + /// Trigger for dry (dehumidification) mode + Trigger<> dry_action_trigger_; + Trigger<> dry_mode_trigger_; - /// The trigger to call when the controller should switch to heating action/mode. - /// - /// A null value for this attribute means that the controller has no heating action - /// For example window blinds, where only cooling (blinds closed) and not-cooling - /// (blinds open) is possible. - Trigger<> *heat_action_trigger_{nullptr}; - Trigger<> *supplemental_heat_action_trigger_{nullptr}; - Trigger<> *heat_mode_trigger_{nullptr}; + /// Trigger for heating action/mode + Trigger<> heat_action_trigger_; + Trigger<> supplemental_heat_action_trigger_; + Trigger<> heat_mode_trigger_; - /// The trigger to call when the controller should switch to heat/cool mode. - /// - /// In heat/cool mode, the controller will enable heating/cooling as necessary and switch - /// to idle when the temperature is within the thresholds/set points. - Trigger<> *heat_cool_mode_trigger_{nullptr}; + /// Trigger for heat/cool mode + Trigger<> heat_cool_mode_trigger_; - /// The trigger to call when the controller should switch to auto mode. - /// - /// In auto mode, the controller will enable heating/cooling as supported/necessary and switch - /// to idle when the temperature is within the thresholds/set points. - Trigger<> *auto_mode_trigger_{nullptr}; + /// Trigger for auto mode + Trigger<> auto_mode_trigger_; - /// The trigger to call when the controller should switch to idle action/off mode. - /// - /// In these actions/modes, the controller is assumed to have both heating and cooling disabled. - Trigger<> *idle_action_trigger_{nullptr}; - Trigger<> *off_mode_trigger_{nullptr}; + /// Trigger for idle action/off mode + Trigger<> idle_action_trigger_; + Trigger<> off_mode_trigger_; - /// The trigger to call when the controller should switch to fan-only action/mode. - /// - /// In fan-only mode, the controller is assumed to have both heating and cooling disabled. - /// The system should activate the fan only. - Trigger<> *fan_only_action_trigger_{nullptr}; - Trigger<> *fan_only_mode_trigger_{nullptr}; + /// Trigger for fan-only action/mode + Trigger<> fan_only_action_trigger_; + Trigger<> fan_only_mode_trigger_; - /// The trigger to call when the controller should switch on the fan. - Trigger<> *fan_mode_on_trigger_{nullptr}; + /// Fan mode triggers + Trigger<> fan_mode_on_trigger_; + Trigger<> fan_mode_off_trigger_; + Trigger<> fan_mode_auto_trigger_; + Trigger<> fan_mode_low_trigger_; + Trigger<> fan_mode_medium_trigger_; + Trigger<> fan_mode_high_trigger_; + Trigger<> fan_mode_middle_trigger_; + Trigger<> fan_mode_focus_trigger_; + Trigger<> fan_mode_diffuse_trigger_; + Trigger<> fan_mode_quiet_trigger_; - /// The trigger to call when the controller should switch off the fan. - Trigger<> *fan_mode_off_trigger_{nullptr}; + /// Swing mode triggers + Trigger<> swing_mode_both_trigger_; + Trigger<> swing_mode_off_trigger_; + Trigger<> swing_mode_horizontal_trigger_; + Trigger<> swing_mode_vertical_trigger_; - /// The trigger to call when the controller should switch the fan to "auto" mode. - Trigger<> *fan_mode_auto_trigger_{nullptr}; + /// Trigger for target humidity changes + Trigger<> humidity_change_trigger_; - /// The trigger to call when the controller should switch the fan to "low" speed. - Trigger<> *fan_mode_low_trigger_{nullptr}; + /// Trigger for target temperature changes + Trigger<> temperature_change_trigger_; - /// The trigger to call when the controller should switch the fan to "medium" speed. - Trigger<> *fan_mode_medium_trigger_{nullptr}; + /// Trigger for preset mode changes + Trigger<> preset_change_trigger_; - /// The trigger to call when the controller should switch the fan to "high" speed. - Trigger<> *fan_mode_high_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "middle" position. - Trigger<> *fan_mode_middle_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "focus" position. - Trigger<> *fan_mode_focus_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "diffuse" position. - Trigger<> *fan_mode_diffuse_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the fan to "quiet" position. - Trigger<> *fan_mode_quiet_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "both". - Trigger<> *swing_mode_both_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "off". - Trigger<> *swing_mode_off_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "horizontal". - Trigger<> *swing_mode_horizontal_trigger_{nullptr}; - - /// The trigger to call when the controller should switch the swing mode to "vertical". - Trigger<> *swing_mode_vertical_trigger_{nullptr}; - - /// The trigger to call when the target humidity changes. - Trigger<> *humidity_change_trigger_{nullptr}; - - /// The trigger to call when the target temperature(s) change(es). - Trigger<> *temperature_change_trigger_{nullptr}; - - /// The trigger to call when the preset mode changes - Trigger<> *preset_change_trigger_{nullptr}; - - /// The trigger to call when dehumidification is required - Trigger<> *humidity_control_dehumidify_action_trigger_{nullptr}; - - /// The trigger to call when humidification is required - Trigger<> *humidity_control_humidify_action_trigger_{nullptr}; - - /// The trigger to call when (de)humidification should stop - Trigger<> *humidity_control_off_action_trigger_{nullptr}; + /// Humidity control triggers + Trigger<> humidity_control_dehumidify_action_trigger_; + Trigger<> humidity_control_humidify_action_trigger_; + Trigger<> humidity_control_off_action_trigger_; /// A reference to the trigger that was previously active. /// From bfeb4471784983af79c076d953ed6382df870176 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:43:16 +0100 Subject: [PATCH 02/12] [sx127x] Avoid heap allocation for packet trigger (#13698) --- esphome/components/sx127x/sx127x.cpp | 2 +- esphome/components/sx127x/sx127x.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/sx127x/sx127x.cpp b/esphome/components/sx127x/sx127x.cpp index 3185574b1a..caf68b6d51 100644 --- a/esphome/components/sx127x/sx127x.cpp +++ b/esphome/components/sx127x/sx127x.cpp @@ -300,7 +300,7 @@ void SX127x::call_listeners_(const std::vector &packet, float rssi, flo for (auto &listener : this->listeners_) { listener->on_packet(packet, rssi, snr); } - this->packet_trigger_->trigger(packet, rssi, snr); + this->packet_trigger_.trigger(packet, rssi, snr); } void SX127x::loop() { diff --git a/esphome/components/sx127x/sx127x.h b/esphome/components/sx127x/sx127x.h index 0600b51201..be7b6d8d9f 100644 --- a/esphome/components/sx127x/sx127x.h +++ b/esphome/components/sx127x/sx127x.h @@ -83,7 +83,7 @@ class SX127x : public Component, void configure(); SX127xError transmit_packet(const std::vector &packet); void register_listener(SX127xListener *listener) { this->listeners_.push_back(listener); } - Trigger, float, float> *get_packet_trigger() const { return this->packet_trigger_; }; + Trigger, float, float> *get_packet_trigger() { return &this->packet_trigger_; } protected: void configure_fsk_ook_(); @@ -94,7 +94,7 @@ class SX127x : public Component, void write_register_(uint8_t reg, uint8_t value); void call_listeners_(const std::vector &packet, float rssi, float snr); uint8_t read_register_(uint8_t reg); - Trigger, float, float> *packet_trigger_{new Trigger, float, float>()}; + Trigger, float, float> packet_trigger_; std::vector listeners_; std::vector packet_; std::vector sync_value_; From 75ee9a718ac7dd02b445648847229bfcbffe6642 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:43:30 +0100 Subject: [PATCH 03/12] [sx126x] Avoid heap allocation for packet trigger (#13699) --- esphome/components/sx126x/sx126x.cpp | 2 +- esphome/components/sx126x/sx126x.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/sx126x/sx126x.cpp b/esphome/components/sx126x/sx126x.cpp index 707d6f1fbf..64cd24b171 100644 --- a/esphome/components/sx126x/sx126x.cpp +++ b/esphome/components/sx126x/sx126x.cpp @@ -343,7 +343,7 @@ void SX126x::call_listeners_(const std::vector &packet, float rssi, flo for (auto &listener : this->listeners_) { listener->on_packet(packet, rssi, snr); } - this->packet_trigger_->trigger(packet, rssi, snr); + this->packet_trigger_.trigger(packet, rssi, snr); } void SX126x::loop() { diff --git a/esphome/components/sx126x/sx126x.h b/esphome/components/sx126x/sx126x.h index 850d7d4c77..a758d63795 100644 --- a/esphome/components/sx126x/sx126x.h +++ b/esphome/components/sx126x/sx126x.h @@ -97,7 +97,7 @@ class SX126x : public Component, void configure(); SX126xError transmit_packet(const std::vector &packet); void register_listener(SX126xListener *listener) { this->listeners_.push_back(listener); } - Trigger, float, float> *get_packet_trigger() const { return this->packet_trigger_; }; + Trigger, float, float> *get_packet_trigger() { return &this->packet_trigger_; } protected: void configure_fsk_ook_(); @@ -111,7 +111,7 @@ class SX126x : public Component, void read_register_(uint16_t reg, uint8_t *data, uint8_t size); void call_listeners_(const std::vector &packet, float rssi, float snr); void wait_busy_(); - Trigger, float, float> *packet_trigger_{new Trigger, float, float>()}; + Trigger, float, float> packet_trigger_; std::vector listeners_; std::vector packet_; std::vector sync_value_; From 78ed898f0bf521a2bea95461640c167aa6ac5715 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:43:52 +0100 Subject: [PATCH 04/12] [current_based] Avoid heap allocation for cover triggers (#13700) --- .../current_based/current_based_cover.cpp | 10 +++++----- .../current_based/current_based_cover.h | 16 ++++++++-------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/esphome/components/current_based/current_based_cover.cpp b/esphome/components/current_based/current_based_cover.cpp index cb3f65c9cd..402cf9fee7 100644 --- a/esphome/components/current_based/current_based_cover.cpp +++ b/esphome/components/current_based/current_based_cover.cpp @@ -66,7 +66,7 @@ void CurrentBasedCover::loop() { if (this->current_operation == COVER_OPERATION_OPENING) { if (this->malfunction_detection_ && this->is_closing_()) { // Malfunction this->direction_idle_(); - this->malfunction_trigger_->trigger(); + this->malfunction_trigger_.trigger(); ESP_LOGI(TAG, "'%s' - Malfunction detected during opening. Current flow detected in close circuit", this->name_.c_str()); } else if (this->is_opening_blocked_()) { // Blocked @@ -87,7 +87,7 @@ void CurrentBasedCover::loop() { } else if (this->current_operation == COVER_OPERATION_CLOSING) { if (this->malfunction_detection_ && this->is_opening_()) { // Malfunction this->direction_idle_(); - this->malfunction_trigger_->trigger(); + this->malfunction_trigger_.trigger(); ESP_LOGI(TAG, "'%s' - Malfunction detected during closing. Current flow detected in open circuit", this->name_.c_str()); } else if (this->is_closing_blocked_()) { // Blocked @@ -221,15 +221,15 @@ void CurrentBasedCover::start_direction_(CoverOperation dir) { Trigger<> *trig; switch (dir) { case COVER_OPERATION_IDLE: - trig = this->stop_trigger_; + trig = &this->stop_trigger_; break; case COVER_OPERATION_OPENING: this->last_operation_ = dir; - trig = this->open_trigger_; + trig = &this->open_trigger_; break; case COVER_OPERATION_CLOSING: this->last_operation_ = dir; - trig = this->close_trigger_; + trig = &this->close_trigger_; break; default: return; diff --git a/esphome/components/current_based/current_based_cover.h b/esphome/components/current_based/current_based_cover.h index b172e762b0..f7993f1550 100644 --- a/esphome/components/current_based/current_based_cover.h +++ b/esphome/components/current_based/current_based_cover.h @@ -16,9 +16,9 @@ class CurrentBasedCover : public cover::Cover, public Component { void dump_config() override; float get_setup_priority() const override; - Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } + Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } - Trigger<> *get_open_trigger() const { return this->open_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } void set_open_sensor(sensor::Sensor *open_sensor) { this->open_sensor_ = open_sensor; } void set_open_moving_current_threshold(float open_moving_current_threshold) { this->open_moving_current_threshold_ = open_moving_current_threshold; @@ -28,7 +28,7 @@ class CurrentBasedCover : public cover::Cover, public Component { } void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } - Trigger<> *get_close_trigger() const { return this->close_trigger_; } + Trigger<> *get_close_trigger() { return &this->close_trigger_; } void set_close_sensor(sensor::Sensor *close_sensor) { this->close_sensor_ = close_sensor; } void set_close_moving_current_threshold(float close_moving_current_threshold) { this->close_moving_current_threshold_ = close_moving_current_threshold; @@ -44,7 +44,7 @@ class CurrentBasedCover : public cover::Cover, public Component { void set_malfunction_detection(bool malfunction_detection) { this->malfunction_detection_ = malfunction_detection; } void set_start_sensing_delay(uint32_t start_sensing_delay) { this->start_sensing_delay_ = start_sensing_delay; } - Trigger<> *get_malfunction_trigger() const { return this->malfunction_trigger_; } + Trigger<> *get_malfunction_trigger() { return &this->malfunction_trigger_; } cover::CoverTraits get_traits() override; @@ -64,23 +64,23 @@ class CurrentBasedCover : public cover::Cover, public Component { void recompute_position_(); - Trigger<> *stop_trigger_{new Trigger<>()}; + Trigger<> stop_trigger_; sensor::Sensor *open_sensor_{nullptr}; - Trigger<> *open_trigger_{new Trigger<>()}; + Trigger<> open_trigger_; float open_moving_current_threshold_; float open_obstacle_current_threshold_{FLT_MAX}; uint32_t open_duration_; sensor::Sensor *close_sensor_{nullptr}; - Trigger<> *close_trigger_{new Trigger<>()}; + Trigger<> close_trigger_; float close_moving_current_threshold_; float close_obstacle_current_threshold_{FLT_MAX}; uint32_t close_duration_; uint32_t max_duration_{UINT32_MAX}; bool malfunction_detection_{true}; - Trigger<> *malfunction_trigger_{new Trigger<>()}; + Trigger<> malfunction_trigger_; uint32_t start_sensing_delay_; float obstacle_rollback_; From 01ffeba2c2930e633c6faf14d993cb040db97e85 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:44:08 +0100 Subject: [PATCH 05/12] [api] Avoid heap allocation for homeassistant action triggers (#13695) --- .../components/api/homeassistant_service.h | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/esphome/components/api/homeassistant_service.h b/esphome/components/api/homeassistant_service.h index 9bffe18764..8ee23c75fe 100644 --- a/esphome/components/api/homeassistant_service.h +++ b/esphome/components/api/homeassistant_service.h @@ -136,12 +136,10 @@ template class HomeAssistantServiceCallAction : public Actionflags_.wants_response = true; } #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - Trigger *get_success_trigger_with_response() const { - return this->success_trigger_with_response_; - } + Trigger *get_success_trigger_with_response() { return &this->success_trigger_with_response_; } #endif - Trigger *get_success_trigger() const { return this->success_trigger_; } - Trigger *get_error_trigger() const { return this->error_trigger_; } + Trigger *get_success_trigger() { return &this->success_trigger_; } + Trigger *get_error_trigger() { return &this->error_trigger_; } #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES void play(const Ts &...x) override { @@ -187,14 +185,14 @@ template class HomeAssistantServiceCallAction : public Actionflags_.wants_response) { - this->success_trigger_with_response_->trigger(response.get_json(), args...); + this->success_trigger_with_response_.trigger(response.get_json(), args...); } else #endif { - this->success_trigger_->trigger(args...); + this->success_trigger_.trigger(args...); } } else { - this->error_trigger_->trigger(response.get_error_message(), args...); + this->error_trigger_.trigger(response.get_error_message(), args...); } }, captured_args); @@ -251,10 +249,10 @@ template class HomeAssistantServiceCallAction : public Action response_template_{""}; - Trigger *success_trigger_with_response_ = new Trigger(); + Trigger success_trigger_with_response_; #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - Trigger *success_trigger_ = new Trigger(); - Trigger *error_trigger_ = new Trigger(); + Trigger success_trigger_; + Trigger error_trigger_; #endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES struct Flags { From 8a8c1290dbfc87639bc4c297b94377857aa2d077 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:45:01 +0100 Subject: [PATCH 06/12] [endstop] Avoid heap allocation for cover triggers (#13702) --- esphome/components/endstop/endstop_cover.cpp | 6 +++--- esphome/components/endstop/endstop_cover.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/endstop/endstop_cover.cpp b/esphome/components/endstop/endstop_cover.cpp index 2c281ea2e6..e28f024136 100644 --- a/esphome/components/endstop/endstop_cover.cpp +++ b/esphome/components/endstop/endstop_cover.cpp @@ -141,15 +141,15 @@ void EndstopCover::start_direction_(CoverOperation dir) { Trigger<> *trig; switch (dir) { case COVER_OPERATION_IDLE: - trig = this->stop_trigger_; + trig = &this->stop_trigger_; break; case COVER_OPERATION_OPENING: this->last_operation_ = dir; - trig = this->open_trigger_; + trig = &this->open_trigger_; break; case COVER_OPERATION_CLOSING: this->last_operation_ = dir; - trig = this->close_trigger_; + trig = &this->close_trigger_; break; default: return; diff --git a/esphome/components/endstop/endstop_cover.h b/esphome/components/endstop/endstop_cover.h index 6ae15de8c1..6f72b2b805 100644 --- a/esphome/components/endstop/endstop_cover.h +++ b/esphome/components/endstop/endstop_cover.h @@ -15,9 +15,9 @@ class EndstopCover : public cover::Cover, public Component { void dump_config() override; float get_setup_priority() const override; - Trigger<> *get_open_trigger() const { return this->open_trigger_; } - Trigger<> *get_close_trigger() const { return this->close_trigger_; } - Trigger<> *get_stop_trigger() const { return this->stop_trigger_; } + Trigger<> *get_open_trigger() { return &this->open_trigger_; } + Trigger<> *get_close_trigger() { return &this->close_trigger_; } + Trigger<> *get_stop_trigger() { return &this->stop_trigger_; } void set_open_endstop(binary_sensor::BinarySensor *open_endstop) { this->open_endstop_ = open_endstop; } void set_close_endstop(binary_sensor::BinarySensor *close_endstop) { this->close_endstop_ = close_endstop; } void set_open_duration(uint32_t open_duration) { this->open_duration_ = open_duration; } @@ -39,11 +39,11 @@ class EndstopCover : public cover::Cover, public Component { binary_sensor::BinarySensor *open_endstop_; binary_sensor::BinarySensor *close_endstop_; - Trigger<> *open_trigger_{new Trigger<>()}; + Trigger<> open_trigger_; uint32_t open_duration_; - Trigger<> *close_trigger_{new Trigger<>()}; + Trigger<> close_trigger_; uint32_t close_duration_; - Trigger<> *stop_trigger_{new Trigger<>()}; + Trigger<> stop_trigger_; uint32_t max_duration_{UINT32_MAX}; Trigger<> *prev_command_trigger_{nullptr}; From d49d8095dfdb24c8e54a3e7f12e1a7e6ffe0f8b2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:46:41 +0100 Subject: [PATCH 07/12] [template] Avoid heap allocation for valve triggers (#13697) --- .../template/valve/template_valve.cpp | 35 ++++++++----------- .../template/valve/template_valve.h | 20 +++++------ 2 files changed, 25 insertions(+), 30 deletions(-) diff --git a/esphome/components/template/valve/template_valve.cpp b/esphome/components/template/valve/template_valve.cpp index 4e772f9253..2817e1a132 100644 --- a/esphome/components/template/valve/template_valve.cpp +++ b/esphome/components/template/valve/template_valve.cpp @@ -7,12 +7,7 @@ using namespace esphome::valve; static const char *const TAG = "template.valve"; -TemplateValve::TemplateValve() - : open_trigger_(new Trigger<>()), - close_trigger_(new Trigger<>), - stop_trigger_(new Trigger<>()), - toggle_trigger_(new Trigger<>()), - position_trigger_(new Trigger()) {} +TemplateValve::TemplateValve() = default; void TemplateValve::setup() { switch (this->restore_mode_) { @@ -56,10 +51,10 @@ void TemplateValve::set_optimistic(bool optimistic) { this->optimistic_ = optimi void TemplateValve::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; } float TemplateValve::get_setup_priority() const { return setup_priority::HARDWARE; } -Trigger<> *TemplateValve::get_open_trigger() const { return this->open_trigger_; } -Trigger<> *TemplateValve::get_close_trigger() const { return this->close_trigger_; } -Trigger<> *TemplateValve::get_stop_trigger() const { return this->stop_trigger_; } -Trigger<> *TemplateValve::get_toggle_trigger() const { return this->toggle_trigger_; } +Trigger<> *TemplateValve::get_open_trigger() { return &this->open_trigger_; } +Trigger<> *TemplateValve::get_close_trigger() { return &this->close_trigger_; } +Trigger<> *TemplateValve::get_stop_trigger() { return &this->stop_trigger_; } +Trigger<> *TemplateValve::get_toggle_trigger() { return &this->toggle_trigger_; } void TemplateValve::dump_config() { LOG_VALVE("", "Template Valve", this); @@ -72,14 +67,14 @@ void TemplateValve::dump_config() { void TemplateValve::control(const ValveCall &call) { if (call.get_stop()) { this->stop_prev_trigger_(); - this->stop_trigger_->trigger(); - this->prev_command_trigger_ = this->stop_trigger_; + this->stop_trigger_.trigger(); + this->prev_command_trigger_ = &this->stop_trigger_; this->publish_state(); } if (call.get_toggle().has_value()) { this->stop_prev_trigger_(); - this->toggle_trigger_->trigger(); - this->prev_command_trigger_ = this->toggle_trigger_; + this->toggle_trigger_.trigger(); + this->prev_command_trigger_ = &this->toggle_trigger_; this->publish_state(); } if (call.get_position().has_value()) { @@ -87,13 +82,13 @@ void TemplateValve::control(const ValveCall &call) { this->stop_prev_trigger_(); if (pos == VALVE_OPEN) { - this->open_trigger_->trigger(); - this->prev_command_trigger_ = this->open_trigger_; + this->open_trigger_.trigger(); + this->prev_command_trigger_ = &this->open_trigger_; } else if (pos == VALVE_CLOSED) { - this->close_trigger_->trigger(); - this->prev_command_trigger_ = this->close_trigger_; + this->close_trigger_.trigger(); + this->prev_command_trigger_ = &this->close_trigger_; } else { - this->position_trigger_->trigger(pos); + this->position_trigger_.trigger(pos); } if (this->optimistic_) { @@ -113,7 +108,7 @@ ValveTraits TemplateValve::get_traits() { return traits; } -Trigger *TemplateValve::get_position_trigger() const { return this->position_trigger_; } +Trigger *TemplateValve::get_position_trigger() { return &this->position_trigger_; } void TemplateValve::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; } void TemplateValve::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; } diff --git a/esphome/components/template/valve/template_valve.h b/esphome/components/template/valve/template_valve.h index 4205682a2a..76c4630aa0 100644 --- a/esphome/components/template/valve/template_valve.h +++ b/esphome/components/template/valve/template_valve.h @@ -18,11 +18,11 @@ class TemplateValve final : public valve::Valve, public Component { TemplateValve(); template void set_state_lambda(F &&f) { this->state_f_.set(std::forward(f)); } - Trigger<> *get_open_trigger() const; - Trigger<> *get_close_trigger() const; - Trigger<> *get_stop_trigger() const; - Trigger<> *get_toggle_trigger() const; - Trigger *get_position_trigger() const; + Trigger<> *get_open_trigger(); + Trigger<> *get_close_trigger(); + Trigger<> *get_stop_trigger(); + Trigger<> *get_toggle_trigger(); + Trigger *get_position_trigger(); void set_optimistic(bool optimistic); void set_assumed_state(bool assumed_state); void set_has_stop(bool has_stop); @@ -45,14 +45,14 @@ class TemplateValve final : public valve::Valve, public Component { TemplateLambda state_f_; bool assumed_state_{false}; bool optimistic_{false}; - Trigger<> *open_trigger_; - Trigger<> *close_trigger_; + Trigger<> open_trigger_; + Trigger<> close_trigger_; bool has_stop_{false}; bool has_toggle_{false}; - Trigger<> *stop_trigger_; - Trigger<> *toggle_trigger_; + Trigger<> stop_trigger_; + Trigger<> toggle_trigger_; Trigger<> *prev_command_trigger_{nullptr}; - Trigger *position_trigger_; + Trigger position_trigger_; bool has_position_{false}; }; From 2f0abd5c3f5e9b1ae8bffe62a8ad320b7ad32a2c Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:46:55 +0100 Subject: [PATCH 08/12] [template] Avoid heap allocation for cover triggers (#13696) --- .../template/cover/template_cover.cpp | 40 ++++++++----------- .../template/cover/template_cover.h | 24 +++++------ 2 files changed, 29 insertions(+), 35 deletions(-) diff --git a/esphome/components/template/cover/template_cover.cpp b/esphome/components/template/cover/template_cover.cpp index 9c8a8fc9bc..7f5d68623f 100644 --- a/esphome/components/template/cover/template_cover.cpp +++ b/esphome/components/template/cover/template_cover.cpp @@ -7,13 +7,7 @@ using namespace esphome::cover; static const char *const TAG = "template.cover"; -TemplateCover::TemplateCover() - : open_trigger_(new Trigger<>()), - close_trigger_(new Trigger<>), - stop_trigger_(new Trigger<>()), - toggle_trigger_(new Trigger<>()), - position_trigger_(new Trigger()), - tilt_trigger_(new Trigger()) {} +TemplateCover::TemplateCover() = default; void TemplateCover::setup() { switch (this->restore_mode_) { case COVER_NO_RESTORE: @@ -62,22 +56,22 @@ void TemplateCover::loop() { void TemplateCover::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } void TemplateCover::set_assumed_state(bool assumed_state) { this->assumed_state_ = assumed_state; } float TemplateCover::get_setup_priority() const { return setup_priority::HARDWARE; } -Trigger<> *TemplateCover::get_open_trigger() const { return this->open_trigger_; } -Trigger<> *TemplateCover::get_close_trigger() const { return this->close_trigger_; } -Trigger<> *TemplateCover::get_stop_trigger() const { return this->stop_trigger_; } -Trigger<> *TemplateCover::get_toggle_trigger() const { return this->toggle_trigger_; } +Trigger<> *TemplateCover::get_open_trigger() { return &this->open_trigger_; } +Trigger<> *TemplateCover::get_close_trigger() { return &this->close_trigger_; } +Trigger<> *TemplateCover::get_stop_trigger() { return &this->stop_trigger_; } +Trigger<> *TemplateCover::get_toggle_trigger() { return &this->toggle_trigger_; } void TemplateCover::dump_config() { LOG_COVER("", "Template Cover", this); } void TemplateCover::control(const CoverCall &call) { if (call.get_stop()) { this->stop_prev_trigger_(); - this->stop_trigger_->trigger(); - this->prev_command_trigger_ = this->stop_trigger_; + this->stop_trigger_.trigger(); + this->prev_command_trigger_ = &this->stop_trigger_; this->publish_state(); } if (call.get_toggle().has_value()) { this->stop_prev_trigger_(); - this->toggle_trigger_->trigger(); - this->prev_command_trigger_ = this->toggle_trigger_; + this->toggle_trigger_.trigger(); + this->prev_command_trigger_ = &this->toggle_trigger_; this->publish_state(); } if (call.get_position().has_value()) { @@ -85,13 +79,13 @@ void TemplateCover::control(const CoverCall &call) { this->stop_prev_trigger_(); if (pos == COVER_OPEN) { - this->open_trigger_->trigger(); - this->prev_command_trigger_ = this->open_trigger_; + this->open_trigger_.trigger(); + this->prev_command_trigger_ = &this->open_trigger_; } else if (pos == COVER_CLOSED) { - this->close_trigger_->trigger(); - this->prev_command_trigger_ = this->close_trigger_; + this->close_trigger_.trigger(); + this->prev_command_trigger_ = &this->close_trigger_; } else { - this->position_trigger_->trigger(pos); + this->position_trigger_.trigger(pos); } if (this->optimistic_) { @@ -101,7 +95,7 @@ void TemplateCover::control(const CoverCall &call) { if (call.get_tilt().has_value()) { auto tilt = *call.get_tilt(); - this->tilt_trigger_->trigger(tilt); + this->tilt_trigger_.trigger(tilt); if (this->optimistic_) { this->tilt = tilt; @@ -119,8 +113,8 @@ CoverTraits TemplateCover::get_traits() { traits.set_supports_tilt(this->has_tilt_); return traits; } -Trigger *TemplateCover::get_position_trigger() const { return this->position_trigger_; } -Trigger *TemplateCover::get_tilt_trigger() const { return this->tilt_trigger_; } +Trigger *TemplateCover::get_position_trigger() { return &this->position_trigger_; } +Trigger *TemplateCover::get_tilt_trigger() { return &this->tilt_trigger_; } void TemplateCover::set_has_stop(bool has_stop) { this->has_stop_ = has_stop; } void TemplateCover::set_has_toggle(bool has_toggle) { this->has_toggle_ = has_toggle; } void TemplateCover::set_has_position(bool has_position) { this->has_position_ = has_position; } diff --git a/esphome/components/template/cover/template_cover.h b/esphome/components/template/cover/template_cover.h index 9c4a787283..20c092cda7 100644 --- a/esphome/components/template/cover/template_cover.h +++ b/esphome/components/template/cover/template_cover.h @@ -19,12 +19,12 @@ class TemplateCover final : public cover::Cover, public Component { template void set_state_lambda(F &&f) { this->state_f_.set(std::forward(f)); } template void set_tilt_lambda(F &&f) { this->tilt_f_.set(std::forward(f)); } - Trigger<> *get_open_trigger() const; - Trigger<> *get_close_trigger() const; - Trigger<> *get_stop_trigger() const; - Trigger<> *get_toggle_trigger() const; - Trigger *get_position_trigger() const; - Trigger *get_tilt_trigger() const; + Trigger<> *get_open_trigger(); + Trigger<> *get_close_trigger(); + Trigger<> *get_stop_trigger(); + Trigger<> *get_toggle_trigger(); + Trigger *get_position_trigger(); + Trigger *get_tilt_trigger(); void set_optimistic(bool optimistic); void set_assumed_state(bool assumed_state); void set_has_stop(bool has_stop); @@ -49,16 +49,16 @@ class TemplateCover final : public cover::Cover, public Component { TemplateLambda tilt_f_; bool assumed_state_{false}; bool optimistic_{false}; - Trigger<> *open_trigger_; - Trigger<> *close_trigger_; + Trigger<> open_trigger_; + Trigger<> close_trigger_; bool has_stop_{false}; bool has_toggle_{false}; - Trigger<> *stop_trigger_; - Trigger<> *toggle_trigger_; + Trigger<> stop_trigger_; + Trigger<> toggle_trigger_; Trigger<> *prev_command_trigger_{nullptr}; - Trigger *position_trigger_; + Trigger position_trigger_; bool has_position_{false}; - Trigger *tilt_trigger_; + Trigger tilt_trigger_; bool has_tilt_{false}; }; From 7d717a78dc0f68cfd6d47135dfa896ec65021e86 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:47:21 +0100 Subject: [PATCH 09/12] [template] Avoid heap allocation for number set trigger (#13694) --- esphome/components/template/number/template_number.cpp | 2 +- esphome/components/template/number/template_number.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/template/number/template_number.cpp b/esphome/components/template/number/template_number.cpp index 885265cf5d..64c2deb281 100644 --- a/esphome/components/template/number/template_number.cpp +++ b/esphome/components/template/number/template_number.cpp @@ -36,7 +36,7 @@ void TemplateNumber::update() { } void TemplateNumber::control(float value) { - this->set_trigger_->trigger(value); + this->set_trigger_.trigger(value); if (this->optimistic_) this->publish_state(value); diff --git a/esphome/components/template/number/template_number.h b/esphome/components/template/number/template_number.h index 42c27fc3ca..e51e858ccf 100644 --- a/esphome/components/template/number/template_number.h +++ b/esphome/components/template/number/template_number.h @@ -17,7 +17,7 @@ class TemplateNumber final : public number::Number, public PollingComponent { void dump_config() override; float get_setup_priority() const override { return setup_priority::HARDWARE; } - Trigger *get_set_trigger() const { return set_trigger_; } + Trigger *get_set_trigger() { return &this->set_trigger_; } void set_optimistic(bool optimistic) { optimistic_ = optimistic; } void set_initial_value(float initial_value) { initial_value_ = initial_value; } void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; } @@ -27,7 +27,7 @@ class TemplateNumber final : public number::Number, public PollingComponent { bool optimistic_{false}; float initial_value_{NAN}; bool restore_value_{false}; - Trigger *set_trigger_ = new Trigger(); + Trigger set_trigger_; TemplateLambda f_; ESPPreferenceObject pref_; From e420964b939b78edd7475d7ad89eaeef37f22020 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:47:34 +0100 Subject: [PATCH 10/12] [template.switch] Avoid heap allocation for triggers (#13691) --- .../components/template/switch/template_switch.cpp | 14 +++++++------- .../components/template/switch/template_switch.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/esphome/components/template/switch/template_switch.cpp b/esphome/components/template/switch/template_switch.cpp index cfa8798e75..05288b2d4e 100644 --- a/esphome/components/template/switch/template_switch.cpp +++ b/esphome/components/template/switch/template_switch.cpp @@ -5,7 +5,7 @@ namespace esphome::template_ { static const char *const TAG = "template.switch"; -TemplateSwitch::TemplateSwitch() : turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {} +TemplateSwitch::TemplateSwitch() = default; void TemplateSwitch::loop() { auto s = this->f_(); @@ -19,11 +19,11 @@ void TemplateSwitch::write_state(bool state) { } if (state) { - this->prev_trigger_ = this->turn_on_trigger_; - this->turn_on_trigger_->trigger(); + this->prev_trigger_ = &this->turn_on_trigger_; + this->turn_on_trigger_.trigger(); } else { - this->prev_trigger_ = this->turn_off_trigger_; - this->turn_off_trigger_->trigger(); + this->prev_trigger_ = &this->turn_off_trigger_; + this->turn_off_trigger_.trigger(); } if (this->optimistic_) @@ -32,8 +32,8 @@ void TemplateSwitch::write_state(bool state) { void TemplateSwitch::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; } bool TemplateSwitch::assumed_state() { return this->assumed_state_; } float TemplateSwitch::get_setup_priority() const { return setup_priority::HARDWARE - 2.0f; } -Trigger<> *TemplateSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; } -Trigger<> *TemplateSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; } +Trigger<> *TemplateSwitch::get_turn_on_trigger() { return &this->turn_on_trigger_; } +Trigger<> *TemplateSwitch::get_turn_off_trigger() { return &this->turn_off_trigger_; } void TemplateSwitch::setup() { if (!this->f_.has_value()) this->disable_loop(); diff --git a/esphome/components/template/switch/template_switch.h b/esphome/components/template/switch/template_switch.h index 91b7b396f6..1714b4f72b 100644 --- a/esphome/components/template/switch/template_switch.h +++ b/esphome/components/template/switch/template_switch.h @@ -15,8 +15,8 @@ class TemplateSwitch final : public switch_::Switch, public Component { void dump_config() override; template void set_state_lambda(F &&f) { this->f_.set(std::forward(f)); } - Trigger<> *get_turn_on_trigger() const; - Trigger<> *get_turn_off_trigger() const; + Trigger<> *get_turn_on_trigger(); + Trigger<> *get_turn_off_trigger(); void set_optimistic(bool optimistic); void set_assumed_state(bool assumed_state); void loop() override; @@ -31,9 +31,9 @@ class TemplateSwitch final : public switch_::Switch, public Component { TemplateLambda f_; bool optimistic_{false}; bool assumed_state_{false}; - Trigger<> *turn_on_trigger_; - Trigger<> *turn_off_trigger_; - Trigger<> *prev_trigger_{nullptr}; + Trigger<> turn_on_trigger_; + Trigger<> turn_off_trigger_; + Trigger<> *prev_trigger_{nullptr}; // Points to one of the above }; } // namespace esphome::template_ From 4ab552d7504fb2070b3b7eb58ae9eafe7e8c32ec Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:47:49 +0100 Subject: [PATCH 11/12] [http_request] Avoid heap allocation for triggers (#13690) --- .../components/http_request/http_request.h | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/esphome/components/http_request/http_request.h b/esphome/components/http_request/http_request.h index fb39ca504c..79098a6b72 100644 --- a/esphome/components/http_request/http_request.h +++ b/esphome/components/http_request/http_request.h @@ -332,13 +332,13 @@ template class HttpRequestSendAction : public Action { void set_json(std::function json_func) { this->json_func_ = json_func; } #ifdef USE_HTTP_REQUEST_RESPONSE - Trigger, std::string &, Ts...> *get_success_trigger_with_response() const { - return this->success_trigger_with_response_; + Trigger, std::string &, Ts...> *get_success_trigger_with_response() { + return &this->success_trigger_with_response_; } #endif - Trigger, Ts...> *get_success_trigger() const { return this->success_trigger_; } + Trigger, Ts...> *get_success_trigger() { return &this->success_trigger_; } - Trigger *get_error_trigger() const { return this->error_trigger_; } + Trigger *get_error_trigger() { return &this->error_trigger_; } void set_max_response_buffer_size(size_t max_response_buffer_size) { this->max_response_buffer_size_ = max_response_buffer_size; @@ -372,7 +372,7 @@ template class HttpRequestSendAction : public Action { auto captured_args = std::make_tuple(x...); if (container == nullptr) { - std::apply([this](Ts... captured_args_inner) { this->error_trigger_->trigger(captured_args_inner...); }, + std::apply([this](Ts... captured_args_inner) { this->error_trigger_.trigger(captured_args_inner...); }, captured_args); return; } @@ -406,14 +406,14 @@ template class HttpRequestSendAction : public Action { } std::apply( [this, &container, &response_body](Ts... captured_args_inner) { - this->success_trigger_with_response_->trigger(container, response_body, captured_args_inner...); + this->success_trigger_with_response_.trigger(container, response_body, captured_args_inner...); }, captured_args); } else #endif { std::apply([this, &container]( - Ts... captured_args_inner) { this->success_trigger_->trigger(container, captured_args_inner...); }, + Ts... captured_args_inner) { this->success_trigger_.trigger(container, captured_args_inner...); }, captured_args); } container->end(); @@ -433,12 +433,10 @@ template class HttpRequestSendAction : public Action { std::map> json_{}; std::function json_func_{nullptr}; #ifdef USE_HTTP_REQUEST_RESPONSE - Trigger, std::string &, Ts...> *success_trigger_with_response_ = - new Trigger, std::string &, Ts...>(); + Trigger, std::string &, Ts...> success_trigger_with_response_; #endif - Trigger, Ts...> *success_trigger_ = - new Trigger, Ts...>(); - Trigger *error_trigger_ = new Trigger(); + Trigger, Ts...> success_trigger_; + Trigger error_trigger_; size_t max_response_buffer_size_{SIZE_MAX}; }; From 7fcbb06a9e00502692453a06c8c2d07921376266 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 2 Feb 2026 04:50:22 +0100 Subject: [PATCH 12/12] [speaker.media_player] Avoid heap allocation for triggers --- .../speaker/media_player/speaker_media_player.cpp | 6 +++--- .../speaker/media_player/speaker_media_player.h | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 172bc980a8..94f555c26e 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -519,9 +519,9 @@ void SpeakerMediaPlayer::set_mute_state_(bool mute_state) { if (old_mute_state != mute_state) { if (mute_state) { - this->defer([this]() { this->mute_trigger_->trigger(); }); + this->defer([this]() { this->mute_trigger_.trigger(); }); } else { - this->defer([this]() { this->unmute_trigger_->trigger(); }); + this->defer([this]() { this->unmute_trigger_.trigger(); }); } } } @@ -550,7 +550,7 @@ void SpeakerMediaPlayer::set_volume_(float volume, bool publish) { this->set_mute_state_(false); } - this->defer([this, volume]() { this->volume_trigger_->trigger(volume); }); + this->defer([this, volume]() { this->volume_trigger_.trigger(volume); }); } } // namespace speaker diff --git a/esphome/components/speaker/media_player/speaker_media_player.h b/esphome/components/speaker/media_player/speaker_media_player.h index 065926d0cf..722f98ceea 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.h +++ b/esphome/components/speaker/media_player/speaker_media_player.h @@ -84,9 +84,9 @@ class SpeakerMediaPlayer : public Component, this->media_format_ = media_format; } - Trigger<> *get_mute_trigger() const { return this->mute_trigger_; } - Trigger<> *get_unmute_trigger() const { return this->unmute_trigger_; } - Trigger *get_volume_trigger() const { return this->volume_trigger_; } + Trigger<> *get_mute_trigger() { return &this->mute_trigger_; } + Trigger<> *get_unmute_trigger() { return &this->unmute_trigger_; } + Trigger *get_volume_trigger() { return &this->volume_trigger_; } void play_file(audio::AudioFile *media_file, bool announcement, bool enqueue); @@ -154,9 +154,9 @@ class SpeakerMediaPlayer : public Component, // Used to save volume/mute state for restoration on reboot ESPPreferenceObject pref_; - Trigger<> *mute_trigger_ = new Trigger<>(); - Trigger<> *unmute_trigger_ = new Trigger<>(); - Trigger *volume_trigger_ = new Trigger(); + Trigger<> mute_trigger_; + Trigger<> unmute_trigger_; + Trigger volume_trigger_; }; } // namespace speaker