Compare commits

..

30 Commits

Author SHA1 Message Date
J. Nick Koston
6d1e100491 wip 2026-02-02 14:45:33 +01:00
J. Nick Koston
15eb28ab77 [core] Add missing uint32_t ID overloads for defer() and cancel_defer() 2026-02-02 14:40:27 +01:00
J. Nick Koston
62f34bea83 [template.output] Avoid heap allocation for triggers (#13709) 2026-02-02 07:36:27 +01:00
J. Nick Koston
6114005952 [template.water_heater] Avoid heap allocation for trigger (#13712) 2026-02-02 07:36:08 +01:00
J. Nick Koston
c0e5ae4298 [template.text] Avoid heap allocation for trigger (#13711) 2026-02-02 07:35:21 +01:00
J. Nick Koston
420de987bc [micro_wake_word] Avoid heap allocation for trigger (#13714) 2026-02-02 07:35:03 +01:00
J. Nick Koston
61e33217cd [cc1101] Avoid heap allocation for trigger (#13715) 2026-02-02 07:34:50 +01:00
J. Nick Koston
b5b9a89561 [light] Avoid heap allocation for AutomationLightEffect trigger (#13713) 2026-02-02 07:34:34 +01:00
J. Nick Koston
bc9fc66225 [template.datetime] Avoid heap allocation for triggers (#13710) 2026-02-02 04:30:46 +00:00
J. Nick Koston
6727fe9040 [remote_transmitter] Avoid heap allocation for triggers (#13708) 2026-02-02 04:18:17 +00:00
J. Nick Koston
56110d4495 [time_based] Avoid heap allocation for cover triggers (#13703) 2026-02-02 05:15:50 +01:00
J. Nick Koston
1362ff6cba [speaker.media_player] Avoid heap allocation for triggers (#13707) 2026-02-02 05:15:33 +01:00
J. Nick Koston
dbd7401721 [feedback] Avoid heap allocation for cover triggers (#13693) 2026-02-02 05:15:13 +01:00
J. Nick Koston
f0801ecac0 [template.lock] Avoid heap allocation for triggers (#13704) 2026-02-02 05:14:11 +01:00
J. Nick Koston
379652f631 [thermostat] Remove dead null checks for triggers (#13706) 2026-02-02 04:10:08 +00:00
J. Nick Koston
18c152723c [sprinkler] Avoid heap allocation for triggers (#13705) 2026-02-02 04:53:46 +01:00
J. Nick Koston
09b76d5e4a [voice_assistant] Avoid heap allocation for triggers (#13689) 2026-02-02 04:50:16 +01:00
J. Nick Koston
8791c24072 [api] Avoid heap allocation for client connected/disconnected triggers (#13688) 2026-02-02 04:50:01 +01:00
J. Nick Koston
652c02b9ab [bang_bang] Avoid heap allocation for climate triggers (#13701) 2026-02-02 04:49:46 +01:00
J. Nick Koston
4ab552d750 [http_request] Avoid heap allocation for triggers (#13690) 2026-02-02 04:47:49 +01:00
J. Nick Koston
e420964b93 [template.switch] Avoid heap allocation for triggers (#13691) 2026-02-02 04:47:34 +01:00
J. Nick Koston
7d717a78dc [template] Avoid heap allocation for number set trigger (#13694) 2026-02-02 04:47:21 +01:00
J. Nick Koston
2f0abd5c3f [template] Avoid heap allocation for cover triggers (#13696) 2026-02-02 04:46:55 +01:00
J. Nick Koston
d49d8095df [template] Avoid heap allocation for valve triggers (#13697) 2026-02-02 04:46:41 +01:00
J. Nick Koston
8a8c1290db [endstop] Avoid heap allocation for cover triggers (#13702) 2026-02-02 04:45:01 +01:00
J. Nick Koston
01ffeba2c2 [api] Avoid heap allocation for homeassistant action triggers (#13695) 2026-02-02 04:44:08 +01:00
J. Nick Koston
78ed898f0b [current_based] Avoid heap allocation for cover triggers (#13700) 2026-02-02 04:43:52 +01:00
J. Nick Koston
75ee9a718a [sx126x] Avoid heap allocation for packet trigger (#13699) 2026-02-02 04:43:30 +01:00
J. Nick Koston
bfeb447178 [sx127x] Avoid heap allocation for packet trigger (#13698) 2026-02-02 04:43:16 +01:00
J. Nick Koston
29f8d70b35 [thermostat] Avoid heap allocation for triggers (#13692) 2026-02-02 04:41:08 +01:00
66 changed files with 581 additions and 682 deletions

View File

@@ -211,7 +211,7 @@ void APIServer::loop() {
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
// Fire trigger after client is removed so api.connected reflects the true state
this->client_disconnected_trigger_->trigger(client_name, client_peername);
this->client_disconnected_trigger_.trigger(client_name, client_peername);
#endif
// Don't increment client_index since we need to process the swapped element
}

View File

@@ -227,12 +227,10 @@ class APIServer : public Component,
#endif
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
Trigger<std::string, std::string> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
Trigger<std::string, std::string> *get_client_connected_trigger() { return &this->client_connected_trigger_; }
#endif
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
Trigger<std::string, std::string> *get_client_disconnected_trigger() const {
return this->client_disconnected_trigger_;
}
Trigger<std::string, std::string> *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; }
#endif
protected:
@@ -253,10 +251,10 @@ class APIServer : public Component,
// Pointers and pointer-like types first (4 bytes each)
std::unique_ptr<socket::Socket> socket_ = nullptr;
#ifdef USE_API_CLIENT_CONNECTED_TRIGGER
Trigger<std::string, std::string> *client_connected_trigger_ = new Trigger<std::string, std::string>();
Trigger<std::string, std::string> client_connected_trigger_;
#endif
#ifdef USE_API_CLIENT_DISCONNECTED_TRIGGER
Trigger<std::string, std::string> *client_disconnected_trigger_ = new Trigger<std::string, std::string>();
Trigger<std::string, std::string> client_disconnected_trigger_;
#endif
// 4-byte aligned types

View File

@@ -136,12 +136,10 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
void set_wants_response() { this->flags_.wants_response = true; }
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
Trigger<JsonObjectConst, Ts...> *get_success_trigger_with_response() const {
return this->success_trigger_with_response_;
}
Trigger<JsonObjectConst, Ts...> *get_success_trigger_with_response() { return &this->success_trigger_with_response_; }
#endif
Trigger<Ts...> *get_success_trigger() const { return this->success_trigger_; }
Trigger<std::string, Ts...> *get_error_trigger() const { return this->error_trigger_; }
Trigger<Ts...> *get_success_trigger() { return &this->success_trigger_; }
Trigger<std::string, Ts...> *get_error_trigger() { return &this->error_trigger_; }
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
void play(const Ts &...x) override {
@@ -187,14 +185,14 @@ template<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
if (response.is_success()) {
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
if (this->flags_.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<typename... Ts> class HomeAssistantServiceCallAction : public Action<Ts
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES
#ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
TemplatableStringValue<Ts...> response_template_{""};
Trigger<JsonObjectConst, Ts...> *success_trigger_with_response_ = new Trigger<JsonObjectConst, Ts...>();
Trigger<JsonObjectConst, Ts...> success_trigger_with_response_;
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON
Trigger<Ts...> *success_trigger_ = new Trigger<Ts...>();
Trigger<std::string, Ts...> *error_trigger_ = new Trigger<std::string, Ts...>();
Trigger<Ts...> success_trigger_;
Trigger<std::string, Ts...> error_trigger_;
#endif // USE_API_HOMEASSISTANT_ACTION_RESPONSES
struct Flags {

View File

@@ -6,8 +6,7 @@ namespace bang_bang {
static const char *const TAG = "bang_bang.climate";
BangBangClimate::BangBangClimate()
: idle_trigger_(new Trigger<>()), cool_trigger_(new Trigger<>()), heat_trigger_(new Trigger<>()) {}
BangBangClimate::BangBangClimate() = default;
void BangBangClimate::setup() {
this->sensor_->add_on_state_callback([this](float state) {
@@ -160,13 +159,13 @@ void BangBangClimate::switch_to_action_(climate::ClimateAction action) {
switch (action) {
case climate::CLIMATE_ACTION_OFF:
case climate::CLIMATE_ACTION_IDLE:
trig = this->idle_trigger_;
trig = &this->idle_trigger_;
break;
case climate::CLIMATE_ACTION_COOLING:
trig = this->cool_trigger_;
trig = &this->cool_trigger_;
break;
case climate::CLIMATE_ACTION_HEATING:
trig = this->heat_trigger_;
trig = &this->heat_trigger_;
break;
default:
trig = nullptr;
@@ -204,9 +203,9 @@ void BangBangClimate::set_away_config(const BangBangClimateTargetTempConfig &awa
void BangBangClimate::set_sensor(sensor::Sensor *sensor) { this->sensor_ = sensor; }
void BangBangClimate::set_humidity_sensor(sensor::Sensor *humidity_sensor) { this->humidity_sensor_ = humidity_sensor; }
Trigger<> *BangBangClimate::get_idle_trigger() const { return this->idle_trigger_; }
Trigger<> *BangBangClimate::get_cool_trigger() const { return this->cool_trigger_; }
Trigger<> *BangBangClimate::get_heat_trigger() const { return this->heat_trigger_; }
Trigger<> *BangBangClimate::get_idle_trigger() { return &this->idle_trigger_; }
Trigger<> *BangBangClimate::get_cool_trigger() { return &this->cool_trigger_; }
Trigger<> *BangBangClimate::get_heat_trigger() { return &this->heat_trigger_; }
void BangBangClimate::set_supports_cool(bool supports_cool) { this->supports_cool_ = supports_cool; }
void BangBangClimate::set_supports_heat(bool supports_heat) { this->supports_heat_ = supports_heat; }

View File

@@ -30,9 +30,9 @@ class BangBangClimate : public climate::Climate, public Component {
void set_normal_config(const BangBangClimateTargetTempConfig &normal_config);
void set_away_config(const BangBangClimateTargetTempConfig &away_config);
Trigger<> *get_idle_trigger() const;
Trigger<> *get_cool_trigger() const;
Trigger<> *get_heat_trigger() const;
Trigger<> *get_idle_trigger();
Trigger<> *get_cool_trigger();
Trigger<> *get_heat_trigger();
protected:
/// Override control to change settings of the climate device.
@@ -57,17 +57,13 @@ class BangBangClimate : public climate::Climate, public Component {
*
* In idle mode, the controller is assumed to have both heating and cooling disabled.
*/
Trigger<> *idle_trigger_{nullptr};
Trigger<> idle_trigger_;
/** The trigger to call when the controller should switch to cooling mode.
*/
Trigger<> *cool_trigger_{nullptr};
Trigger<> cool_trigger_;
/** The trigger to call when the controller should switch to heating 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_trigger_{nullptr};
Trigger<> heat_trigger_;
/** A reference to the trigger that was previously active.
*
* This is so that the previous trigger can be stopped before enabling a new one.

View File

@@ -156,7 +156,7 @@ void CC1101Component::call_listeners_(const std::vector<uint8_t> &packet, float
for (auto &listener : this->listeners_) {
listener->on_packet(packet, freq_offset, rssi, lqi);
}
this->packet_trigger_->trigger(packet, freq_offset, rssi, lqi);
this->packet_trigger_.trigger(packet, freq_offset, rssi, lqi);
}
void CC1101Component::loop() {

View File

@@ -79,7 +79,7 @@ class CC1101Component : public Component,
// Packet mode operations
CC1101Error transmit_packet(const std::vector<uint8_t> &packet);
void register_listener(CC1101Listener *listener) { this->listeners_.push_back(listener); }
Trigger<std::vector<uint8_t>, float, float, uint8_t> *get_packet_trigger() const { return this->packet_trigger_; }
Trigger<std::vector<uint8_t>, float, float, uint8_t> *get_packet_trigger() { return &this->packet_trigger_; }
protected:
uint16_t chip_id_{0};
@@ -96,8 +96,7 @@ class CC1101Component : public Component,
// Packet handling
void call_listeners_(const std::vector<uint8_t> &packet, float freq_offset, float rssi, uint8_t lqi);
Trigger<std::vector<uint8_t>, float, float, uint8_t> *packet_trigger_{
new Trigger<std::vector<uint8_t>, float, float, uint8_t>()};
Trigger<std::vector<uint8_t>, float, float, uint8_t> packet_trigger_;
std::vector<uint8_t> packet_;
std::vector<CC1101Listener *> listeners_;

View File

@@ -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;

View File

@@ -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_;

View File

@@ -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;

View File

@@ -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};

View File

@@ -335,18 +335,18 @@ void FeedbackCover::start_direction_(CoverOperation dir) {
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_;
#ifdef USE_BINARY_SENSOR
obstacle = this->open_obstacle_;
#endif
break;
case COVER_OPERATION_CLOSING:
this->last_operation_ = dir;
trig = this->close_trigger_;
trig = &this->close_trigger_;
#ifdef USE_BINARY_SENSOR
obstacle = this->close_obstacle_;
#endif

View File

@@ -17,9 +17,9 @@ class FeedbackCover : public cover::Cover, public Component {
void loop() override;
void dump_config() 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_; }
#ifdef USE_BINARY_SENSOR
void set_open_endstop(binary_sensor::BinarySensor *open_endstop);
@@ -61,9 +61,9 @@ class FeedbackCover : public cover::Cover, public Component {
binary_sensor::BinarySensor *close_obstacle_{nullptr};
#endif
Trigger<> *open_trigger_{new Trigger<>()};
Trigger<> *close_trigger_{new Trigger<>()};
Trigger<> *stop_trigger_{new Trigger<>()};
Trigger<> open_trigger_;
Trigger<> close_trigger_;
Trigger<> stop_trigger_;
uint32_t open_duration_{0};
uint32_t close_duration_{0};

View File

@@ -332,13 +332,13 @@ template<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
void set_json(std::function<void(Ts..., JsonObject)> json_func) { this->json_func_ = json_func; }
#ifdef USE_HTTP_REQUEST_RESPONSE
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> *get_success_trigger_with_response() const {
return this->success_trigger_with_response_;
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> *get_success_trigger_with_response() {
return &this->success_trigger_with_response_;
}
#endif
Trigger<std::shared_ptr<HttpContainer>, Ts...> *get_success_trigger() const { return this->success_trigger_; }
Trigger<std::shared_ptr<HttpContainer>, Ts...> *get_success_trigger() { return &this->success_trigger_; }
Trigger<Ts...> *get_error_trigger() const { return this->error_trigger_; }
Trigger<Ts...> *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<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
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<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
}
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<typename... Ts> class HttpRequestSendAction : public Action<Ts...> {
std::map<const char *, TemplatableValue<std::string, Ts...>> json_{};
std::function<void(Ts..., JsonObject)> json_func_{nullptr};
#ifdef USE_HTTP_REQUEST_RESPONSE
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> *success_trigger_with_response_ =
new Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...>();
Trigger<std::shared_ptr<HttpContainer>, std::string &, Ts...> success_trigger_with_response_;
#endif
Trigger<std::shared_ptr<HttpContainer>, Ts...> *success_trigger_ =
new Trigger<std::shared_ptr<HttpContainer>, Ts...>();
Trigger<Ts...> *error_trigger_ = new Trigger<Ts...>();
Trigger<std::shared_ptr<HttpContainer>, Ts...> success_trigger_;
Trigger<Ts...> error_trigger_;
size_t max_response_buffer_size_{SIZE_MAX};
};

View File

@@ -138,20 +138,20 @@ class LambdaLightEffect : public LightEffect {
class AutomationLightEffect : public LightEffect {
public:
AutomationLightEffect(const char *name) : LightEffect(name) {}
void stop() override { this->trig_->stop_action(); }
void stop() override { this->trig_.stop_action(); }
void apply() override {
if (!this->trig_->is_action_running()) {
this->trig_->trigger();
if (!this->trig_.is_action_running()) {
this->trig_.trigger();
}
}
Trigger<> *get_trig() const { return trig_; }
Trigger<> *get_trig() { return &this->trig_; }
/// Get the current effect index for use in automations.
/// Useful for automations that need to know which effect is running.
uint32_t get_current_index() const { return this->get_index(); }
protected:
Trigger<> *trig_{new Trigger<>};
Trigger<> trig_;
};
struct StrobeLightEffectColor {

View File

@@ -325,7 +325,7 @@ void MicroWakeWord::loop() {
ESP_LOGD(TAG, "Detected '%s' with sliding average probability is %.2f and max probability is %.2f",
detection_event.wake_word->c_str(), (detection_event.average_probability / uint8_to_float_divisor),
(detection_event.max_probability / uint8_to_float_divisor));
this->wake_word_detected_trigger_->trigger(*detection_event.wake_word);
this->wake_word_detected_trigger_.trigger(*detection_event.wake_word);
if (this->stop_after_detection_) {
this->stop();
}

View File

@@ -60,7 +60,7 @@ class MicroWakeWord : public Component
void set_stop_after_detection(bool stop_after_detection) { this->stop_after_detection_ = stop_after_detection; }
Trigger<std::string> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; }
Trigger<std::string> *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; }
void add_wake_word_model(WakeWordModel *model);
@@ -78,7 +78,7 @@ class MicroWakeWord : public Component
protected:
microphone::MicrophoneSource *microphone_source_{nullptr};
Trigger<std::string> *wake_word_detected_trigger_ = new Trigger<std::string>();
Trigger<std::string> wake_word_detected_trigger_;
State state_{State::STOPPED};
std::weak_ptr<RingBuffer> ring_buffer_;

View File

@@ -1,5 +1,6 @@
#pragma once
#include "esphome/core/automation.h"
#include "mixer_speaker.h"
#ifdef USE_ESP32

View File

@@ -83,7 +83,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
uint32_t on_time, off_time;
this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time);
this->target_time_ = 0;
this->transmit_trigger_->trigger();
this->transmit_trigger_.trigger();
for (uint32_t i = 0; i < send_times; i++) {
InterruptLock lock;
for (int32_t item : this->temp_.get_data()) {
@@ -102,7 +102,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
if (i + 1 < send_times)
this->target_time_ += send_wait;
}
this->complete_trigger_->trigger();
this->complete_trigger_.trigger();
}
} // namespace remote_transmitter

View File

@@ -57,8 +57,8 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
void set_non_blocking(bool non_blocking) { this->non_blocking_ = non_blocking; }
#endif
Trigger<> *get_transmit_trigger() const { return this->transmit_trigger_; };
Trigger<> *get_complete_trigger() const { return this->complete_trigger_; };
Trigger<> *get_transmit_trigger() { return &this->transmit_trigger_; }
Trigger<> *get_complete_trigger() { return &this->complete_trigger_; }
protected:
void send_internal(uint32_t send_times, uint32_t send_wait) override;
@@ -96,8 +96,8 @@ class RemoteTransmitterComponent : public remote_base::RemoteTransmitterBase,
#endif
uint8_t carrier_duty_percent_;
Trigger<> *transmit_trigger_{new Trigger<>()};
Trigger<> *complete_trigger_{new Trigger<>()};
Trigger<> transmit_trigger_;
Trigger<> complete_trigger_;
};
} // namespace remote_transmitter

View File

@@ -203,7 +203,7 @@ void RemoteTransmitterComponent::wait_for_rmt_() {
this->status_set_warning();
}
this->complete_trigger_->trigger();
this->complete_trigger_.trigger();
}
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 5, 1)
@@ -264,7 +264,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
return;
}
this->transmit_trigger_->trigger();
this->transmit_trigger_.trigger();
rmt_transmit_config_t config;
memset(&config, 0, sizeof(config));
@@ -333,7 +333,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
ESP_LOGE(TAG, "Empty data");
return;
}
this->transmit_trigger_->trigger();
this->transmit_trigger_.trigger();
for (uint32_t i = 0; i < send_times; i++) {
rmt_transmit_config_t config;
memset(&config, 0, sizeof(config));
@@ -354,7 +354,7 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
if (i + 1 < send_times)
delayMicroseconds(send_wait);
}
this->complete_trigger_->trigger();
this->complete_trigger_.trigger();
}
#endif

View File

@@ -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

View File

@@ -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<float> *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<float> *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<float> *volume_trigger_ = new Trigger<float>();
Trigger<> mute_trigger_;
Trigger<> unmute_trigger_;
Trigger<float> volume_trigger_;
};
} // namespace speaker

View File

@@ -29,7 +29,7 @@ void SprinklerControllerNumber::setup() {
}
void SprinklerControllerNumber::control(float value) {
this->set_trigger_->trigger(value);
this->set_trigger_.trigger(value);
this->publish_state(value);
@@ -39,8 +39,7 @@ void SprinklerControllerNumber::control(float value) {
void SprinklerControllerNumber::dump_config() { LOG_NUMBER("", "Sprinkler Controller Number", this); }
SprinklerControllerSwitch::SprinklerControllerSwitch()
: turn_on_trigger_(new Trigger<>()), turn_off_trigger_(new Trigger<>()) {}
SprinklerControllerSwitch::SprinklerControllerSwitch() = default;
void SprinklerControllerSwitch::loop() {
// Loop is only enabled when f_ has a value (see setup())
@@ -56,11 +55,11 @@ void SprinklerControllerSwitch::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();
}
this->publish_state(state);
@@ -69,9 +68,6 @@ void SprinklerControllerSwitch::write_state(bool state) {
void SprinklerControllerSwitch::set_state_lambda(std::function<optional<bool>()> &&f) { this->f_ = f; }
float SprinklerControllerSwitch::get_setup_priority() const { return setup_priority::HARDWARE; }
Trigger<> *SprinklerControllerSwitch::get_turn_on_trigger() const { return this->turn_on_trigger_; }
Trigger<> *SprinklerControllerSwitch::get_turn_off_trigger() const { return this->turn_off_trigger_; }
void SprinklerControllerSwitch::setup() {
this->state = this->get_initial_state_with_restore_mode().value_or(false);
// Disable loop if no state lambda is set - nothing to poll

View File

@@ -76,7 +76,7 @@ class SprinklerControllerNumber : public number::Number, public Component {
void dump_config() override;
float get_setup_priority() const override { return setup_priority::PROCESSOR; }
Trigger<float> *get_set_trigger() const { return set_trigger_; }
Trigger<float> *get_set_trigger() { return &this->set_trigger_; }
void set_initial_value(float initial_value) { initial_value_ = initial_value; }
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
@@ -84,7 +84,7 @@ class SprinklerControllerNumber : public number::Number, public Component {
void control(float value) override;
float initial_value_{NAN};
bool restore_value_{true};
Trigger<float> *set_trigger_ = new Trigger<float>();
Trigger<float> set_trigger_;
ESPPreferenceObject pref_;
};
@@ -97,8 +97,8 @@ class SprinklerControllerSwitch : public switch_::Switch, public Component {
void dump_config() override;
void set_state_lambda(std::function<optional<bool>()> &&f);
Trigger<> *get_turn_on_trigger() const;
Trigger<> *get_turn_off_trigger() const;
Trigger<> *get_turn_on_trigger() { return &this->turn_on_trigger_; }
Trigger<> *get_turn_off_trigger() { return &this->turn_off_trigger_; }
void loop() override;
float get_setup_priority() const override;
@@ -107,8 +107,8 @@ class SprinklerControllerSwitch : public switch_::Switch, public Component {
void write_state(bool state) override;
optional<std::function<optional<bool>()>> f_;
Trigger<> *turn_on_trigger_;
Trigger<> *turn_off_trigger_;
Trigger<> turn_on_trigger_;
Trigger<> turn_off_trigger_;
Trigger<> *prev_trigger_{nullptr};
};

View File

@@ -343,7 +343,7 @@ void SX126x::call_listeners_(const std::vector<uint8_t> &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() {

View File

@@ -97,7 +97,7 @@ class SX126x : public Component,
void configure();
SX126xError transmit_packet(const std::vector<uint8_t> &packet);
void register_listener(SX126xListener *listener) { this->listeners_.push_back(listener); }
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() const { return this->packet_trigger_; };
Trigger<std::vector<uint8_t>, 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<uint8_t> &packet, float rssi, float snr);
void wait_busy_();
Trigger<std::vector<uint8_t>, float, float> *packet_trigger_{new Trigger<std::vector<uint8_t>, float, float>()};
Trigger<std::vector<uint8_t>, float, float> packet_trigger_;
std::vector<SX126xListener *> listeners_;
std::vector<uint8_t> packet_;
std::vector<uint8_t> sync_value_;

View File

@@ -300,7 +300,7 @@ void SX127x::call_listeners_(const std::vector<uint8_t> &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() {

View File

@@ -83,7 +83,7 @@ class SX127x : public Component,
void configure();
SX127xError transmit_packet(const std::vector<uint8_t> &packet);
void register_listener(SX127xListener *listener) { this->listeners_.push_back(listener); }
Trigger<std::vector<uint8_t>, float, float> *get_packet_trigger() const { return this->packet_trigger_; };
Trigger<std::vector<uint8_t>, 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<uint8_t> &packet, float rssi, float snr);
uint8_t read_register_(uint8_t reg);
Trigger<std::vector<uint8_t>, float, float> *packet_trigger_{new Trigger<std::vector<uint8_t>, float, float>()};
Trigger<std::vector<uint8_t>, float, float> packet_trigger_;
std::vector<SX127xListener *> listeners_;
std::vector<uint8_t> packet_;
std::vector<uint8_t> sync_value_;

View File

@@ -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<float>()),
tilt_trigger_(new Trigger<float>()) {}
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<float> *TemplateCover::get_position_trigger() const { return this->position_trigger_; }
Trigger<float> *TemplateCover::get_tilt_trigger() const { return this->tilt_trigger_; }
Trigger<float> *TemplateCover::get_position_trigger() { return &this->position_trigger_; }
Trigger<float> *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; }

View File

@@ -19,12 +19,12 @@ class TemplateCover final : public cover::Cover, public Component {
template<typename F> void set_state_lambda(F &&f) { this->state_f_.set(std::forward<F>(f)); }
template<typename F> void set_tilt_lambda(F &&f) { this->tilt_f_.set(std::forward<F>(f)); }
Trigger<> *get_open_trigger() const;
Trigger<> *get_close_trigger() const;
Trigger<> *get_stop_trigger() const;
Trigger<> *get_toggle_trigger() const;
Trigger<float> *get_position_trigger() const;
Trigger<float> *get_tilt_trigger() const;
Trigger<> *get_open_trigger();
Trigger<> *get_close_trigger();
Trigger<> *get_stop_trigger();
Trigger<> *get_toggle_trigger();
Trigger<float> *get_position_trigger();
Trigger<float> *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<float> 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<float> *position_trigger_;
Trigger<float> position_trigger_;
bool has_position_{false};
Trigger<float> *tilt_trigger_;
Trigger<float> tilt_trigger_;
bool has_tilt_{false};
};

View File

@@ -62,7 +62,7 @@ void TemplateDate::control(const datetime::DateCall &call) {
if (has_day)
value.day_of_month = *call.get_day();
this->set_trigger_->trigger(value);
this->set_trigger_.trigger(value);
if (this->optimistic_) {
if (has_year)

View File

@@ -22,7 +22,7 @@ class TemplateDate final : public datetime::DateEntity, public PollingComponent
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
Trigger<ESPTime> *get_set_trigger() { return &this->set_trigger_; }
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
@@ -34,7 +34,7 @@ class TemplateDate final : public datetime::DateEntity, public PollingComponent
bool optimistic_{false};
ESPTime initial_value_{};
bool restore_value_{false};
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
Trigger<ESPTime> set_trigger_;
TemplateLambda<ESPTime> f_;
ESPPreferenceObject pref_;

View File

@@ -80,7 +80,7 @@ void TemplateDateTime::control(const datetime::DateTimeCall &call) {
if (has_second)
value.second = *call.get_second();
this->set_trigger_->trigger(value);
this->set_trigger_.trigger(value);
if (this->optimistic_) {
if (has_year)

View File

@@ -22,7 +22,7 @@ class TemplateDateTime final : public datetime::DateTimeEntity, public PollingCo
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
Trigger<ESPTime> *get_set_trigger() { return &this->set_trigger_; }
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
@@ -34,7 +34,7 @@ class TemplateDateTime final : public datetime::DateTimeEntity, public PollingCo
bool optimistic_{false};
ESPTime initial_value_{};
bool restore_value_{false};
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
Trigger<ESPTime> set_trigger_;
TemplateLambda<ESPTime> f_;
ESPPreferenceObject pref_;

View File

@@ -62,7 +62,7 @@ void TemplateTime::control(const datetime::TimeCall &call) {
if (has_second)
value.second = *call.get_second();
this->set_trigger_->trigger(value);
this->set_trigger_.trigger(value);
if (this->optimistic_) {
if (has_hour)

View File

@@ -22,7 +22,7 @@ class TemplateTime final : public datetime::TimeEntity, public PollingComponent
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
Trigger<ESPTime> *get_set_trigger() const { return this->set_trigger_; }
Trigger<ESPTime> *get_set_trigger() { return &this->set_trigger_; }
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
void set_initial_value(ESPTime initial_value) { this->initial_value_ = initial_value; }
@@ -34,7 +34,7 @@ class TemplateTime final : public datetime::TimeEntity, public PollingComponent
bool optimistic_{false};
ESPTime initial_value_{};
bool restore_value_{false};
Trigger<ESPTime> *set_trigger_ = new Trigger<ESPTime>();
Trigger<ESPTime> set_trigger_;
TemplateLambda<ESPTime> f_;
ESPPreferenceObject pref_;

View File

@@ -7,8 +7,7 @@ using namespace esphome::lock;
static const char *const TAG = "template.lock";
TemplateLock::TemplateLock()
: lock_trigger_(new Trigger<>()), unlock_trigger_(new Trigger<>()), open_trigger_(new Trigger<>()) {}
TemplateLock::TemplateLock() = default;
void TemplateLock::setup() {
if (!this->f_.has_value())
@@ -28,11 +27,11 @@ void TemplateLock::control(const lock::LockCall &call) {
auto state = *call.get_state();
if (state == LOCK_STATE_LOCKED) {
this->prev_trigger_ = this->lock_trigger_;
this->lock_trigger_->trigger();
this->prev_trigger_ = &this->lock_trigger_;
this->lock_trigger_.trigger();
} else if (state == LOCK_STATE_UNLOCKED) {
this->prev_trigger_ = this->unlock_trigger_;
this->unlock_trigger_->trigger();
this->prev_trigger_ = &this->unlock_trigger_;
this->unlock_trigger_.trigger();
}
if (this->optimistic_)
@@ -42,14 +41,11 @@ void TemplateLock::open_latch() {
if (this->prev_trigger_ != nullptr) {
this->prev_trigger_->stop_action();
}
this->prev_trigger_ = this->open_trigger_;
this->open_trigger_->trigger();
this->prev_trigger_ = &this->open_trigger_;
this->open_trigger_.trigger();
}
void TemplateLock::set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
float TemplateLock::get_setup_priority() const { return setup_priority::HARDWARE; }
Trigger<> *TemplateLock::get_lock_trigger() const { return this->lock_trigger_; }
Trigger<> *TemplateLock::get_unlock_trigger() const { return this->unlock_trigger_; }
Trigger<> *TemplateLock::get_open_trigger() const { return this->open_trigger_; }
void TemplateLock::dump_config() {
LOG_LOCK("", "Template Lock", this);
ESP_LOGCONFIG(TAG, " Optimistic: %s", YESNO(this->optimistic_));

View File

@@ -15,9 +15,9 @@ class TemplateLock final : public lock::Lock, public Component {
void dump_config() override;
template<typename F> void set_state_lambda(F &&f) { this->f_.set(std::forward<F>(f)); }
Trigger<> *get_lock_trigger() const;
Trigger<> *get_unlock_trigger() const;
Trigger<> *get_open_trigger() const;
Trigger<> *get_lock_trigger() { return &this->lock_trigger_; }
Trigger<> *get_unlock_trigger() { return &this->unlock_trigger_; }
Trigger<> *get_open_trigger() { return &this->open_trigger_; }
void set_optimistic(bool optimistic);
void loop() override;
@@ -29,9 +29,9 @@ class TemplateLock final : public lock::Lock, public Component {
TemplateLambda<lock::LockState> f_;
bool optimistic_{false};
Trigger<> *lock_trigger_;
Trigger<> *unlock_trigger_;
Trigger<> *open_trigger_;
Trigger<> lock_trigger_;
Trigger<> unlock_trigger_;
Trigger<> open_trigger_;
Trigger<> *prev_trigger_{nullptr};
};

View File

@@ -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);

View File

@@ -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<float> *get_set_trigger() const { return set_trigger_; }
Trigger<float> *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<float> *set_trigger_ = new Trigger<float>();
Trigger<float> set_trigger_;
TemplateLambda<float> f_;
ESPPreferenceObject pref_;

View File

@@ -8,22 +8,22 @@ namespace esphome::template_ {
class TemplateBinaryOutput final : public output::BinaryOutput {
public:
Trigger<bool> *get_trigger() const { return trigger_; }
Trigger<bool> *get_trigger() { return &this->trigger_; }
protected:
void write_state(bool state) override { this->trigger_->trigger(state); }
void write_state(bool state) override { this->trigger_.trigger(state); }
Trigger<bool> *trigger_ = new Trigger<bool>();
Trigger<bool> trigger_;
};
class TemplateFloatOutput final : public output::FloatOutput {
public:
Trigger<float> *get_trigger() const { return trigger_; }
Trigger<float> *get_trigger() { return &this->trigger_; }
protected:
void write_state(float state) override { this->trigger_->trigger(state); }
void write_state(float state) override { this->trigger_.trigger(state); }
Trigger<float> *trigger_ = new Trigger<float>();
Trigger<float> trigger_;
};
} // namespace esphome::template_

View File

@@ -17,9 +17,6 @@ from .. import template_ns
TemplateSelect = template_ns.class_(
"TemplateSelect", select.Select, cg.PollingComponent
)
TemplateSelectWithSetAction = template_ns.class_(
"TemplateSelectWithSetAction", TemplateSelect
)
def validate(config):
@@ -42,11 +39,6 @@ def validate(config):
raise cv.Invalid(
"Either optimistic mode must be enabled, or set_action must be set, to handle the option being set."
)
# Use subclass with trigger only when set_action is configured
if CONF_SET_ACTION in config:
config[CONF_ID].type = TemplateSelectWithSetAction
return config

View File

@@ -41,6 +41,8 @@ void TemplateSelect::update() {
}
void TemplateSelect::control(size_t index) {
this->set_trigger_->trigger(StringRef(this->option_at(index)));
if (this->optimistic_)
this->publish_state(index);
@@ -48,11 +50,6 @@ void TemplateSelect::control(size_t index) {
this->pref_.save(&index);
}
void TemplateSelectWithSetAction::control(size_t index) {
this->set_trigger_.trigger(StringRef(this->option_at(index)));
TemplateSelect::control(index);
}
void TemplateSelect::dump_config() {
LOG_SELECT("", "Template Select", this);
LOG_UPDATE_INTERVAL(this);

View File

@@ -9,8 +9,7 @@
namespace esphome::template_ {
/// Base template select class - used when no set_action is configured
class TemplateSelect : public select::Select, public PollingComponent {
class TemplateSelect final : public select::Select, public PollingComponent {
public:
template<typename F> void set_template(F &&f) { this->f_.set(std::forward<F>(f)); }
@@ -19,6 +18,7 @@ class TemplateSelect : public select::Select, public PollingComponent {
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
Trigger<StringRef> *get_set_trigger() const { return this->set_trigger_; }
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
void set_initial_option_index(size_t initial_option_index) { this->initial_option_index_ = initial_option_index; }
void set_restore_value(bool restore_value) { this->restore_value_ = restore_value; }
@@ -28,19 +28,10 @@ class TemplateSelect : public select::Select, public PollingComponent {
bool optimistic_ = false;
size_t initial_option_index_{0};
bool restore_value_ = false;
Trigger<StringRef> *set_trigger_ = new Trigger<StringRef>();
TemplateLambda<std::string> f_;
ESPPreferenceObject pref_;
};
/// Template select with set_action trigger - only instantiated when set_action is configured
class TemplateSelectWithSetAction final : public TemplateSelect {
public:
Trigger<StringRef> *get_set_trigger() { return &this->set_trigger_; }
protected:
void control(size_t index) override;
Trigger<StringRef> set_trigger_;
};
} // namespace esphome::template_

View File

@@ -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();

View File

@@ -15,8 +15,8 @@ class TemplateSwitch final : public switch_::Switch, public Component {
void dump_config() override;
template<typename F> void set_state_lambda(F &&f) { this->f_.set(std::forward<F>(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<bool> 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_

View File

@@ -47,7 +47,7 @@ void TemplateText::update() {
}
void TemplateText::control(const std::string &value) {
this->set_trigger_->trigger(value);
this->set_trigger_.trigger(value);
if (this->optimistic_)
this->publish_state(value);

View File

@@ -68,7 +68,7 @@ class TemplateText final : public text::Text, public PollingComponent {
void dump_config() override;
float get_setup_priority() const override { return setup_priority::HARDWARE; }
Trigger<std::string> *get_set_trigger() const { return this->set_trigger_; }
Trigger<std::string> *get_set_trigger() { return &this->set_trigger_; }
void set_optimistic(bool optimistic) { this->optimistic_ = optimistic; }
void set_initial_value(const char *initial_value) { this->initial_value_ = initial_value; }
/// Prevent accidental use of std::string which would dangle
@@ -79,7 +79,7 @@ class TemplateText final : public text::Text, public PollingComponent {
void control(const std::string &value) override;
bool optimistic_ = false;
const char *initial_value_{nullptr};
Trigger<std::string> *set_trigger_ = new Trigger<std::string>();
Trigger<std::string> set_trigger_;
TemplateLambda<std::string> f_{};
TemplateTextSaverBase *pref_ = nullptr;

View File

@@ -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<float>()) {}
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<float> *TemplateValve::get_position_trigger() const { return this->position_trigger_; }
Trigger<float> *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; }

View File

@@ -18,11 +18,11 @@ class TemplateValve final : public valve::Valve, public Component {
TemplateValve();
template<typename F> void set_state_lambda(F &&f) { this->state_f_.set(std::forward<F>(f)); }
Trigger<> *get_open_trigger() const;
Trigger<> *get_close_trigger() const;
Trigger<> *get_stop_trigger() const;
Trigger<> *get_toggle_trigger() const;
Trigger<float> *get_position_trigger() const;
Trigger<> *get_open_trigger();
Trigger<> *get_close_trigger();
Trigger<> *get_stop_trigger();
Trigger<> *get_toggle_trigger();
Trigger<float> *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<float> 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<float> *position_trigger_;
Trigger<float> position_trigger_;
bool has_position_{false};
};

View File

@@ -5,7 +5,7 @@ namespace esphome::template_ {
static const char *const TAG = "template.water_heater";
TemplateWaterHeater::TemplateWaterHeater() : set_trigger_(new Trigger<>()) {}
TemplateWaterHeater::TemplateWaterHeater() = default;
void TemplateWaterHeater::setup() {
if (this->restore_mode_ == TemplateWaterHeaterRestoreMode::WATER_HEATER_RESTORE ||
@@ -78,7 +78,7 @@ void TemplateWaterHeater::control(const water_heater::WaterHeaterCall &call) {
}
}
this->set_trigger_->trigger();
this->set_trigger_.trigger();
if (this->optimistic_) {
this->publish_state();

View File

@@ -28,7 +28,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater {
this->supported_modes_ = modes;
}
Trigger<> *get_set_trigger() const { return this->set_trigger_; }
Trigger<> *get_set_trigger() { return &this->set_trigger_; }
void setup() override;
void loop() override;
@@ -42,7 +42,7 @@ class TemplateWaterHeater : public Component, public water_heater::WaterHeater {
water_heater::WaterHeaterTraits traits() override;
// Ordered to minimize padding on 32-bit: 4-byte members first, then smaller
Trigger<> *set_trigger_;
Trigger<> set_trigger_;
TemplateLambda<float> current_temperature_f_;
TemplateLambda<water_heater::WaterHeaterMode> mode_f_;
TemplateWaterHeaterRestoreMode restore_mode_{WATER_HEATER_NO_RESTORE};

View File

@@ -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;
}
@@ -586,9 +586,7 @@ void ThermostatClimate::switch_to_action_(climate::ClimateAction action, bool pu
}
this->action = action;
this->prev_action_trigger_ = trig;
if (trig != nullptr) {
trig->trigger();
}
trig->trigger();
// if enabled, call the fan_only action with cooling/heating actions
if (trig_fan != nullptr) {
ESP_LOGVV(TAG, "Calling FAN_ONLY action with HEATING/COOLING action");
@@ -634,14 +632,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 +658,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) {
@@ -686,9 +684,7 @@ void ThermostatClimate::switch_to_humidity_control_action_(HumidificationAction
}
this->humidification_action = action;
this->prev_humidity_control_trigger_ = trig;
if (trig != nullptr) {
trig->trigger();
}
trig->trigger();
}
void ThermostatClimate::switch_to_fan_mode_(climate::ClimateFanMode fan_mode, bool publish_state) {
@@ -703,62 +699,60 @@ 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();
this->prev_fan_mode_trigger_ = nullptr;
}
this->start_timer_(thermostat::THERMOSTAT_TIMER_FAN_MODE);
if (trig != nullptr) {
trig->trigger();
}
trig->trigger();
this->prev_fan_mode_ = fan_mode;
this->prev_fan_mode_trigger_ = trig;
}
@@ -775,25 +769,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:
@@ -802,9 +796,7 @@ void ThermostatClimate::switch_to_mode_(climate::ClimateMode mode, bool publish_
mode = climate::CLIMATE_MODE_OFF;
// trig = this->off_mode_trigger_;
}
if (trig != nullptr) {
trig->trigger();
}
trig->trigger();
this->mode = mode;
this->prev_mode_ = mode;
this->prev_mode_trigger_ = trig;
@@ -824,29 +816,27 @@ 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_;
}
if (trig != nullptr) {
trig->trigger();
// trig = &this->swing_mode_off_trigger_;
}
trig->trigger();
this->swing_mode = swing_mode;
this->prev_swing_mode_ = swing_mode;
this->prev_swing_mode_trigger_ = trig;
@@ -1024,10 +1014,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 +1038,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 +1188,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 +1218,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 +1287,7 @@ void ThermostatClimate::set_custom_preset_config(std::initializer_list<CustomPre
this->custom_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 +1461,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() {

View File

@@ -146,40 +146,40 @@ class ThermostatClimate : public climate::Climate, public Component {
void set_preset_config(std::initializer_list<PresetEntry> presets);
void set_custom_preset_config(std::initializer_list<CustomPresetEntry> 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.
///

View File

@@ -132,15 +132,15 @@ void TimeBasedCover::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;

View File

@@ -14,9 +14,9 @@ class TimeBasedCover : 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_duration(uint32_t open_duration) { this->open_duration_ = open_duration; }
void set_close_duration(uint32_t close_duration) { this->close_duration_ = close_duration; }
cover::CoverTraits get_traits() override;
@@ -34,11 +34,11 @@ class TimeBasedCover : public cover::Cover, public Component {
void recompute_position_();
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_;
Trigger<> *prev_command_trigger_{nullptr};
uint32_t last_recompute_time_{0};

View File

@@ -197,7 +197,7 @@ void VoiceAssistant::loop() {
switch (this->state_) {
case State::IDLE: {
if (this->continuous_ && this->desired_state_ == State::IDLE) {
this->idle_trigger_->trigger();
this->idle_trigger_.trigger();
this->set_state_(State::START_MICROPHONE, State::START_PIPELINE);
} else {
this->deallocate_buffers_();
@@ -254,7 +254,7 @@ void VoiceAssistant::loop() {
if (this->api_client_ == nullptr ||
!this->api_client_->send_message(msg, api::VoiceAssistantRequest::MESSAGE_TYPE)) {
ESP_LOGW(TAG, "Could not request start");
this->error_trigger_->trigger("not-connected", "Could not request start");
this->error_trigger_.trigger("not-connected", "Could not request start");
this->continuous_ = false;
this->set_state_(State::IDLE, State::IDLE);
break;
@@ -384,7 +384,7 @@ void VoiceAssistant::loop() {
this->wait_for_stream_end_ = false;
this->stream_ended_ = false;
this->tts_stream_end_trigger_->trigger();
this->tts_stream_end_trigger_.trigger();
}
#endif
if (this->continue_conversation_) {
@@ -425,7 +425,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
return;
}
this->api_client_ = nullptr;
this->client_disconnected_trigger_->trigger();
this->client_disconnected_trigger_.trigger();
return;
}
@@ -440,7 +440,7 @@ void VoiceAssistant::client_subscription(api::APIConnection *client, bool subscr
}
this->api_client_ = client;
this->client_connected_trigger_->trigger();
this->client_connected_trigger_.trigger();
}
static const LogString *voice_assistant_state_to_string(State state) {
@@ -491,7 +491,7 @@ void VoiceAssistant::set_state_(State state, State desired_state) {
void VoiceAssistant::failed_to_start() {
ESP_LOGE(TAG, "Failed to start server. See Home Assistant logs for more details.");
this->error_trigger_->trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details.");
this->error_trigger_.trigger("failed-to-start", "Failed to start server. See Home Assistant logs for more details.");
this->set_state_(State::STOP_MICROPHONE, State::IDLE);
}
@@ -637,18 +637,18 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
#endif
this->defer([this]() { this->start_trigger_->trigger(); });
this->defer([this]() { this->start_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_WAKE_WORD_START:
break;
case api::enums::VOICE_ASSISTANT_WAKE_WORD_END: {
ESP_LOGD(TAG, "Wake word detected");
this->defer([this]() { this->wake_word_detected_trigger_->trigger(); });
this->defer([this]() { this->wake_word_detected_trigger_.trigger(); });
break;
}
case api::enums::VOICE_ASSISTANT_STT_START:
ESP_LOGD(TAG, "STT started");
this->defer([this]() { this->listening_trigger_->trigger(); });
this->defer([this]() { this->listening_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_STT_END: {
std::string text;
@@ -665,12 +665,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
text += "...";
}
ESP_LOGD(TAG, "Speech recognised as: \"%s\"", text.c_str());
this->defer([this, text]() { this->stt_end_trigger_->trigger(text); });
this->defer([this, text]() { this->stt_end_trigger_.trigger(text); });
break;
}
case api::enums::VOICE_ASSISTANT_INTENT_START:
ESP_LOGD(TAG, "Intent started");
this->defer([this]() { this->intent_start_trigger_->trigger(); });
this->defer([this]() { this->intent_start_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_INTENT_PROGRESS: {
ESP_LOGD(TAG, "Intent progress");
@@ -693,7 +693,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
}
#endif
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_->trigger(tts_url_for_trigger); });
this->defer([this, tts_url_for_trigger]() { this->intent_progress_trigger_.trigger(tts_url_for_trigger); });
break;
}
case api::enums::VOICE_ASSISTANT_INTENT_END: {
@@ -704,7 +704,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
this->continue_conversation_ = (arg.value == "1");
}
}
this->defer([this]() { this->intent_end_trigger_->trigger(); });
this->defer([this]() { this->intent_end_trigger_.trigger(); });
break;
}
case api::enums::VOICE_ASSISTANT_TTS_START: {
@@ -724,7 +724,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
ESP_LOGD(TAG, "Response: \"%s\"", text.c_str());
this->defer([this, text]() {
this->tts_start_trigger_->trigger(text);
this->tts_start_trigger_.trigger(text);
#ifdef USE_SPEAKER
if (this->speaker_ != nullptr) {
this->speaker_->start();
@@ -756,7 +756,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
this->started_streaming_tts_ = false; // Helps indicate reaching the TTS_END stage
#endif
this->tts_end_trigger_->trigger(url);
this->tts_end_trigger_.trigger(url);
});
State new_state = this->local_output_ ? State::STREAMING_RESPONSE : State::IDLE;
if (new_state != this->state_) {
@@ -776,7 +776,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
// No TTS start event ("nevermind")
this->set_state_(State::IDLE, State::IDLE);
}
this->defer([this]() { this->end_trigger_->trigger(); });
this->defer([this]() { this->end_trigger_.trigger(); });
break;
}
case api::enums::VOICE_ASSISTANT_ERROR: {
@@ -796,7 +796,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
// Wake word is not set up or not ready on Home Assistant so stop and do not retry until user starts again.
this->defer([this, code, message]() {
this->request_stop();
this->error_trigger_->trigger(code, message);
this->error_trigger_.trigger(code, message);
});
return;
}
@@ -805,7 +805,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
this->signal_stop_();
this->set_state_(State::STOP_MICROPHONE, State::IDLE);
}
this->defer([this, code, message]() { this->error_trigger_->trigger(code, message); });
this->defer([this, code, message]() { this->error_trigger_.trigger(code, message); });
break;
}
case api::enums::VOICE_ASSISTANT_TTS_STREAM_START: {
@@ -813,7 +813,7 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
if (this->speaker_ != nullptr) {
this->wait_for_stream_end_ = true;
ESP_LOGD(TAG, "TTS stream start");
this->defer([this] { this->tts_stream_start_trigger_->trigger(); });
this->defer([this] { this->tts_stream_start_trigger_.trigger(); });
}
#endif
break;
@@ -829,12 +829,12 @@ void VoiceAssistant::on_event(const api::VoiceAssistantEventResponse &msg) {
}
case api::enums::VOICE_ASSISTANT_STT_VAD_START:
ESP_LOGD(TAG, "Starting STT by VAD");
this->defer([this]() { this->stt_vad_start_trigger_->trigger(); });
this->defer([this]() { this->stt_vad_start_trigger_.trigger(); });
break;
case api::enums::VOICE_ASSISTANT_STT_VAD_END:
ESP_LOGD(TAG, "STT by VAD end");
this->set_state_(State::STOP_MICROPHONE, State::AWAITING_RESPONSE);
this->defer([this]() { this->stt_vad_end_trigger_->trigger(); });
this->defer([this]() { this->stt_vad_end_trigger_.trigger(); });
break;
default:
ESP_LOGD(TAG, "Unhandled event type: %" PRId32, msg.event_type);
@@ -876,17 +876,17 @@ void VoiceAssistant::on_timer_event(const api::VoiceAssistantTimerEventResponse
switch (msg.event_type) {
case api::enums::VOICE_ASSISTANT_TIMER_STARTED:
this->timer_started_trigger_->trigger(timer);
this->timer_started_trigger_.trigger(timer);
break;
case api::enums::VOICE_ASSISTANT_TIMER_UPDATED:
this->timer_updated_trigger_->trigger(timer);
this->timer_updated_trigger_.trigger(timer);
break;
case api::enums::VOICE_ASSISTANT_TIMER_CANCELLED:
this->timer_cancelled_trigger_->trigger(timer);
this->timer_cancelled_trigger_.trigger(timer);
this->timers_.erase(timer.id);
break;
case api::enums::VOICE_ASSISTANT_TIMER_FINISHED:
this->timer_finished_trigger_->trigger(timer);
this->timer_finished_trigger_.trigger(timer);
this->timers_.erase(timer.id);
break;
}
@@ -910,13 +910,13 @@ void VoiceAssistant::timer_tick_() {
}
res.push_back(timer);
}
this->timer_tick_trigger_->trigger(res);
this->timer_tick_trigger_.trigger(res);
}
void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg) {
#ifdef USE_MEDIA_PLAYER
if (this->media_player_ != nullptr) {
this->tts_start_trigger_->trigger(msg.text);
this->tts_start_trigger_.trigger(msg.text);
this->media_player_response_state_ = MediaPlayerResponseState::URL_SENT;
@@ -939,8 +939,8 @@ void VoiceAssistant::on_announce(const api::VoiceAssistantAnnounceRequest &msg)
this->set_state_(State::STREAMING_RESPONSE, State::STREAMING_RESPONSE);
}
this->tts_end_trigger_->trigger(msg.media_id);
this->end_trigger_->trigger();
this->tts_end_trigger_.trigger(msg.media_id);
this->end_trigger_.trigger();
}
#endif
}

View File

@@ -195,38 +195,38 @@ class VoiceAssistant : public Component {
void set_conversation_timeout(uint32_t conversation_timeout) { this->conversation_timeout_ = conversation_timeout; }
void reset_conversation_id();
Trigger<> *get_intent_end_trigger() const { return this->intent_end_trigger_; }
Trigger<> *get_intent_start_trigger() const { return this->intent_start_trigger_; }
Trigger<std::string> *get_intent_progress_trigger() const { return this->intent_progress_trigger_; }
Trigger<> *get_listening_trigger() const { return this->listening_trigger_; }
Trigger<> *get_end_trigger() const { return this->end_trigger_; }
Trigger<> *get_start_trigger() const { return this->start_trigger_; }
Trigger<> *get_stt_vad_end_trigger() const { return this->stt_vad_end_trigger_; }
Trigger<> *get_stt_vad_start_trigger() const { return this->stt_vad_start_trigger_; }
Trigger<> *get_intent_end_trigger() { return &this->intent_end_trigger_; }
Trigger<> *get_intent_start_trigger() { return &this->intent_start_trigger_; }
Trigger<std::string> *get_intent_progress_trigger() { return &this->intent_progress_trigger_; }
Trigger<> *get_listening_trigger() { return &this->listening_trigger_; }
Trigger<> *get_end_trigger() { return &this->end_trigger_; }
Trigger<> *get_start_trigger() { return &this->start_trigger_; }
Trigger<> *get_stt_vad_end_trigger() { return &this->stt_vad_end_trigger_; }
Trigger<> *get_stt_vad_start_trigger() { return &this->stt_vad_start_trigger_; }
#ifdef USE_SPEAKER
Trigger<> *get_tts_stream_start_trigger() const { return this->tts_stream_start_trigger_; }
Trigger<> *get_tts_stream_end_trigger() const { return this->tts_stream_end_trigger_; }
Trigger<> *get_tts_stream_start_trigger() { return &this->tts_stream_start_trigger_; }
Trigger<> *get_tts_stream_end_trigger() { return &this->tts_stream_end_trigger_; }
#endif
Trigger<> *get_wake_word_detected_trigger() const { return this->wake_word_detected_trigger_; }
Trigger<std::string> *get_stt_end_trigger() const { return this->stt_end_trigger_; }
Trigger<std::string> *get_tts_end_trigger() const { return this->tts_end_trigger_; }
Trigger<std::string> *get_tts_start_trigger() const { return this->tts_start_trigger_; }
Trigger<std::string, std::string> *get_error_trigger() const { return this->error_trigger_; }
Trigger<> *get_idle_trigger() const { return this->idle_trigger_; }
Trigger<> *get_wake_word_detected_trigger() { return &this->wake_word_detected_trigger_; }
Trigger<std::string> *get_stt_end_trigger() { return &this->stt_end_trigger_; }
Trigger<std::string> *get_tts_end_trigger() { return &this->tts_end_trigger_; }
Trigger<std::string> *get_tts_start_trigger() { return &this->tts_start_trigger_; }
Trigger<std::string, std::string> *get_error_trigger() { return &this->error_trigger_; }
Trigger<> *get_idle_trigger() { return &this->idle_trigger_; }
Trigger<> *get_client_connected_trigger() const { return this->client_connected_trigger_; }
Trigger<> *get_client_disconnected_trigger() const { return this->client_disconnected_trigger_; }
Trigger<> *get_client_connected_trigger() { return &this->client_connected_trigger_; }
Trigger<> *get_client_disconnected_trigger() { return &this->client_disconnected_trigger_; }
void client_subscription(api::APIConnection *client, bool subscribe);
api::APIConnection *get_api_connection() const { return this->api_client_; }
void set_wake_word(const std::string &wake_word) { this->wake_word_ = wake_word; }
Trigger<Timer> *get_timer_started_trigger() const { return this->timer_started_trigger_; }
Trigger<Timer> *get_timer_updated_trigger() const { return this->timer_updated_trigger_; }
Trigger<Timer> *get_timer_cancelled_trigger() const { return this->timer_cancelled_trigger_; }
Trigger<Timer> *get_timer_finished_trigger() const { return this->timer_finished_trigger_; }
Trigger<std::vector<Timer>> *get_timer_tick_trigger() const { return this->timer_tick_trigger_; }
Trigger<Timer> *get_timer_started_trigger() { return &this->timer_started_trigger_; }
Trigger<Timer> *get_timer_updated_trigger() { return &this->timer_updated_trigger_; }
Trigger<Timer> *get_timer_cancelled_trigger() { return &this->timer_cancelled_trigger_; }
Trigger<Timer> *get_timer_finished_trigger() { return &this->timer_finished_trigger_; }
Trigger<std::vector<Timer>> *get_timer_tick_trigger() { return &this->timer_tick_trigger_; }
void set_has_timers(bool has_timers) { this->has_timers_ = has_timers; }
const std::unordered_map<std::string, Timer> &get_timers() const { return this->timers_; }
@@ -243,37 +243,37 @@ class VoiceAssistant : public Component {
std::unique_ptr<socket::Socket> socket_ = nullptr;
struct sockaddr_storage dest_addr_;
Trigger<> *intent_end_trigger_ = new Trigger<>();
Trigger<> *intent_start_trigger_ = new Trigger<>();
Trigger<> *listening_trigger_ = new Trigger<>();
Trigger<> *end_trigger_ = new Trigger<>();
Trigger<> *start_trigger_ = new Trigger<>();
Trigger<> *stt_vad_start_trigger_ = new Trigger<>();
Trigger<> *stt_vad_end_trigger_ = new Trigger<>();
Trigger<> intent_end_trigger_;
Trigger<> intent_start_trigger_;
Trigger<> listening_trigger_;
Trigger<> end_trigger_;
Trigger<> start_trigger_;
Trigger<> stt_vad_start_trigger_;
Trigger<> stt_vad_end_trigger_;
#ifdef USE_SPEAKER
Trigger<> *tts_stream_start_trigger_ = new Trigger<>();
Trigger<> *tts_stream_end_trigger_ = new Trigger<>();
Trigger<> tts_stream_start_trigger_;
Trigger<> tts_stream_end_trigger_;
#endif
Trigger<std::string> *intent_progress_trigger_ = new Trigger<std::string>();
Trigger<> *wake_word_detected_trigger_ = new Trigger<>();
Trigger<std::string> *stt_end_trigger_ = new Trigger<std::string>();
Trigger<std::string> *tts_end_trigger_ = new Trigger<std::string>();
Trigger<std::string> *tts_start_trigger_ = new Trigger<std::string>();
Trigger<std::string, std::string> *error_trigger_ = new Trigger<std::string, std::string>();
Trigger<> *idle_trigger_ = new Trigger<>();
Trigger<std::string> intent_progress_trigger_;
Trigger<> wake_word_detected_trigger_;
Trigger<std::string> stt_end_trigger_;
Trigger<std::string> tts_end_trigger_;
Trigger<std::string> tts_start_trigger_;
Trigger<std::string, std::string> error_trigger_;
Trigger<> idle_trigger_;
Trigger<> *client_connected_trigger_ = new Trigger<>();
Trigger<> *client_disconnected_trigger_ = new Trigger<>();
Trigger<> client_connected_trigger_;
Trigger<> client_disconnected_trigger_;
api::APIConnection *api_client_{nullptr};
std::unordered_map<std::string, Timer> timers_;
void timer_tick_();
Trigger<Timer> *timer_started_trigger_ = new Trigger<Timer>();
Trigger<Timer> *timer_finished_trigger_ = new Trigger<Timer>();
Trigger<Timer> *timer_updated_trigger_ = new Trigger<Timer>();
Trigger<Timer> *timer_cancelled_trigger_ = new Trigger<Timer>();
Trigger<std::vector<Timer>> *timer_tick_trigger_ = new Trigger<std::vector<Timer>>();
Trigger<Timer> timer_started_trigger_;
Trigger<Timer> timer_finished_trigger_;
Trigger<Timer> timer_updated_trigger_;
Trigger<Timer> timer_cancelled_trigger_;
Trigger<std::vector<Timer>> timer_tick_trigger_;
bool has_timers_{false};
bool timer_tick_running_{false};

View File

@@ -359,6 +359,10 @@ void Component::defer(const std::string &name, std::function<void()> &&f) { //
void Component::defer(const char *name, std::function<void()> &&f) { // NOLINT
App.scheduler.set_timeout(this, name, 0, std::move(f));
}
void Component::defer(uint32_t id, std::function<void()> &&f) { // NOLINT
App.scheduler.set_timeout(this, id, 0, std::move(f));
}
bool Component::cancel_defer(uint32_t id) { return App.scheduler.cancel_timeout(this, id); }
void Component::set_timeout(uint32_t timeout, std::function<void()> &&f) { // NOLINT
App.scheduler.set_timeout(this, static_cast<const char *>(nullptr), timeout, std::move(f));
}

View File

@@ -494,11 +494,15 @@ class Component {
/// Defer a callback to the next loop() call.
void defer(std::function<void()> &&f); // NOLINT
/// Defer a callback with a numeric ID (zero heap allocation)
void defer(uint32_t id, std::function<void()> &&f); // NOLINT
/// Cancel a defer callback using the specified name, name must not be empty.
// Remove before 2026.7.0
ESPDEPRECATED("Use const char* overload instead. Removed in 2026.7.0", "2026.1.0")
bool cancel_defer(const std::string &name); // NOLINT
bool cancel_defer(const char *name); // NOLINT
bool cancel_defer(uint32_t id); // NOLINT
// Ordered for optimal packing on 32-bit systems
const LogString *component_source_{nullptr};

View File

@@ -296,16 +296,6 @@ select:
// Migration guide: Store in std::string
std::string stored_option(id(template_select).current_option());
ESP_LOGI("test", "Stored: %s", stored_option.c_str());
- platform: template
id: template_select_with_action
name: "Template select with action"
options:
- option_a
- option_b
set_action:
- logger.log:
format: "Selected: %s"
args: ["x.c_str()"]
lock:
- platform: template

View File

@@ -20,6 +20,9 @@ globals:
- id: retry_counter
type: int
initial_value: '0'
- id: defer_counter
type: int
initial_value: '0'
- id: tests_done
type: bool
initial_value: 'false'
@@ -136,11 +139,49 @@ script:
App.scheduler.cancel_retry(component1, 6002U);
ESP_LOGI("test", "Cancelled numeric retry 6002");
// Test 12: defer with numeric ID (Component method)
class TestDeferComponent : public Component {
public:
void test_defer_methods() {
// Test defer with uint32_t ID - should execute on next loop
this->defer(7001U, []() {
ESP_LOGI("test", "Component numeric defer 7001 fired");
id(defer_counter) += 1;
});
// Test another defer with numeric ID
this->defer(7002U, []() {
ESP_LOGI("test", "Component numeric defer 7002 fired");
id(defer_counter) += 1;
});
}
};
static TestDeferComponent test_defer_component;
test_defer_component.test_defer_methods();
// Test 13: cancel_defer with numeric ID (Component method)
class TestCancelDeferComponent : public Component {
public:
void test_cancel_defer() {
// Set a defer that should be cancelled
this->defer(8001U, []() {
ESP_LOGE("test", "ERROR: Numeric defer 8001 should have been cancelled");
});
// Cancel it immediately
bool cancelled = this->cancel_defer(8001U);
ESP_LOGI("test", "Cancelled numeric defer 8001: %s", cancelled ? "true" : "false");
}
};
static TestCancelDeferComponent test_cancel_defer_component;
test_cancel_defer_component.test_cancel_defer();
- id: report_results
then:
- lambda: |-
ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d",
id(timeout_counter), id(interval_counter), id(retry_counter));
ESP_LOGI("test", "Final results - Timeouts: %d, Intervals: %d, Retries: %d, Defers: %d",
id(timeout_counter), id(interval_counter), id(retry_counter), id(defer_counter));
sensor:
- platform: template

View File

@@ -56,21 +56,7 @@ select:
std::string prefix = x.substr(0, 6);
ESP_LOGI("test", "Substr prefix: %s", prefix.c_str());
# Second select with set_action trigger (uses TemplateSelectWithSetAction subclass)
- platform: template
name: "Action Select"
id: action_select
options:
- "Action A"
- "Action B"
set_action:
then:
# Test: set_action trigger receives StringRef
- logger.log:
format: "set_action triggered: %s"
args: ['x.c_str()']
# Third select with numeric options to test ADL functions
# Second select with numeric options to test ADL functions
- platform: template
name: "Baud Rate"
id: baud_select

View File

@@ -19,6 +19,7 @@ async def test_scheduler_numeric_id_test(
timeout_count = 0
interval_count = 0
retry_count = 0
defer_count = 0
# Events for each test completion
numeric_timeout_1001_fired = asyncio.Event()
@@ -33,6 +34,9 @@ async def test_scheduler_numeric_id_test(
max_id_timeout_fired = asyncio.Event()
numeric_retry_done = asyncio.Event()
numeric_retry_cancelled = asyncio.Event()
numeric_defer_7001_fired = asyncio.Event()
numeric_defer_7002_fired = asyncio.Event()
numeric_defer_cancelled = asyncio.Event()
final_results_logged = asyncio.Event()
# Track interval counts
@@ -40,7 +44,7 @@ async def test_scheduler_numeric_id_test(
numeric_retry_count = 0
def on_log_line(line: str) -> None:
nonlocal timeout_count, interval_count, retry_count
nonlocal timeout_count, interval_count, retry_count, defer_count
nonlocal numeric_interval_count, numeric_retry_count
# Strip ANSI color codes
@@ -105,15 +109,27 @@ async def test_scheduler_numeric_id_test(
elif "Cancelled numeric retry 6002" in clean_line:
numeric_retry_cancelled.set()
# Check for numeric defer tests
elif "Component numeric defer 7001 fired" in clean_line:
numeric_defer_7001_fired.set()
elif "Component numeric defer 7002 fired" in clean_line:
numeric_defer_7002_fired.set()
elif "Cancelled numeric defer 8001: true" in clean_line:
numeric_defer_cancelled.set()
# Check for final results
elif "Final results" in clean_line:
match = re.search(
r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+)", clean_line
r"Timeouts: (\d+), Intervals: (\d+), Retries: (\d+), Defers: (\d+)",
clean_line,
)
if match:
timeout_count = int(match.group(1))
interval_count = int(match.group(2))
retry_count = int(match.group(3))
defer_count = int(match.group(4))
final_results_logged.set()
async with (
@@ -201,6 +217,23 @@ async def test_scheduler_numeric_id_test(
"Numeric retry 6002 should have been cancelled"
)
# Wait for numeric defer tests
try:
await asyncio.wait_for(numeric_defer_7001_fired.wait(), timeout=0.5)
except TimeoutError:
pytest.fail("Numeric defer 7001 did not fire within 0.5 seconds")
try:
await asyncio.wait_for(numeric_defer_7002_fired.wait(), timeout=0.5)
except TimeoutError:
pytest.fail("Numeric defer 7002 did not fire within 0.5 seconds")
# Verify numeric defer was cancelled
try:
await asyncio.wait_for(numeric_defer_cancelled.wait(), timeout=0.5)
except TimeoutError:
pytest.fail("Numeric defer 8001 cancel confirmation not received")
# Wait for final results
try:
await asyncio.wait_for(final_results_logged.wait(), timeout=3.0)
@@ -215,3 +248,4 @@ async def test_scheduler_numeric_id_test(
assert retry_count >= 2, (
f"Expected at least 2 retry attempts, got {retry_count}"
)
assert defer_count >= 2, f"Expected at least 2 defer fires, got {defer_count}"

View File

@@ -28,8 +28,6 @@ async def test_select_stringref_trigger(
find_substr_future = loop.create_future()
find_char_future = loop.create_future()
substr_future = loop.create_future()
# set_action trigger (TemplateSelectWithSetAction subclass)
set_action_future = loop.create_future()
# ADL functions
stoi_future = loop.create_future()
stol_future = loop.create_future()
@@ -45,8 +43,6 @@ async def test_select_stringref_trigger(
find_substr_pattern = re.compile(r"Found 'Option' in value")
find_char_pattern = re.compile(r"Space at position: 6") # space at index 6
substr_pattern = re.compile(r"Substr prefix: Option")
# set_action trigger pattern (TemplateSelectWithSetAction subclass)
set_action_pattern = re.compile(r"set_action triggered: Action B")
# ADL function patterns (115200 from baud rate select)
stoi_pattern = re.compile(r"stoi result: 115200")
stol_pattern = re.compile(r"stol result: 115200")
@@ -71,9 +67,6 @@ async def test_select_stringref_trigger(
find_char_future.set_result(True)
if not substr_future.done() and substr_pattern.search(line):
substr_future.set_result(True)
# set_action trigger
if not set_action_future.done() and set_action_pattern.search(line):
set_action_future.set_result(True)
# ADL functions
if not stoi_future.done() and stoi_pattern.search(line):
stoi_future.set_result(True)
@@ -96,21 +89,22 @@ async def test_select_stringref_trigger(
# List entities to find our select
entities, _ = await client.list_entities_services()
select_entity = next((e for e in entities if e.name == "Test Select"), None)
select_entity = next(
(e for e in entities if hasattr(e, "options") and e.name == "Test Select"),
None,
)
assert select_entity is not None, "Test Select entity not found"
baud_entity = next((e for e in entities if e.name == "Baud Rate"), None)
baud_entity = next(
(e for e in entities if hasattr(e, "options") and e.name == "Baud Rate"),
None,
)
assert baud_entity is not None, "Baud Rate entity not found"
action_entity = next((e for e in entities if e.name == "Action Select"), None)
assert action_entity is not None, "Action Select entity not found"
# Change select to Option B - this should trigger on_value with StringRef
client.select_command(select_entity.key, "Option B")
# Change baud to 115200 - this tests ADL functions (stoi, stol, stof, stod)
client.select_command(baud_entity.key, "115200")
# Change action select - tests set_action trigger (TemplateSelectWithSetAction)
client.select_command(action_entity.key, "Action B")
# Wait for all log messages confirming StringRef operations work
try:
@@ -124,7 +118,6 @@ async def test_select_stringref_trigger(
find_substr_future,
find_char_future,
substr_future,
set_action_future,
stoi_future,
stol_future,
stof_future,
@@ -142,7 +135,6 @@ async def test_select_stringref_trigger(
"find_substr": find_substr_future.done(),
"find_char": find_char_future.done(),
"substr": substr_future.done(),
"set_action": set_action_future.done(),
"stoi": stoi_future.done(),
"stol": stol_future.done(),
"stof": stof_future.done(),