[core] Store parent pointers as members to enable inline Callback storage (#14923)

This commit is contained in:
J. Nick Koston
2026-03-20 15:25:40 -10:00
committed by GitHub
parent 21e384cafd
commit f3cddcee21
10 changed files with 134 additions and 76 deletions
+10 -8
View File
@@ -105,17 +105,18 @@ template<typename... Ts> using CoverIsClosedCondition = CoverPositionCondition<f
template<bool OPEN> class CoverPositionTrigger : public Trigger<> {
public:
CoverPositionTrigger(Cover *a_cover) {
a_cover->add_on_state_callback([this, a_cover]() {
if (a_cover->position != this->last_position_) {
this->last_position_ = a_cover->position;
if (a_cover->position == (OPEN ? COVER_OPEN : COVER_CLOSED))
CoverPositionTrigger(Cover *a_cover) : cover_(a_cover) {
a_cover->add_on_state_callback([this]() {
if (this->cover_->position != this->last_position_) {
this->last_position_ = this->cover_->position;
if (this->cover_->position == (OPEN ? COVER_OPEN : COVER_CLOSED))
this->trigger();
}
});
}
protected:
Cover *cover_;
float last_position_{NAN};
};
@@ -124,9 +125,9 @@ using CoverClosedTrigger = CoverPositionTrigger<false>;
template<CoverOperation OP> class CoverTrigger : public Trigger<> {
public:
CoverTrigger(Cover *a_cover) {
a_cover->add_on_state_callback([this, a_cover]() {
auto current_op = a_cover->current_operation;
CoverTrigger(Cover *a_cover) : cover_(a_cover) {
a_cover->add_on_state_callback([this]() {
auto current_op = this->cover_->current_operation;
if (current_op == OP) {
if (!this->last_operation_.has_value() || this->last_operation_.value() != OP) {
this->trigger();
@@ -137,6 +138,7 @@ template<CoverOperation OP> class CoverTrigger : public Trigger<> {
}
protected:
Cover *cover_;
optional<CoverOperation> last_operation_{};
};
} // namespace esphome::cover
+5 -2
View File
@@ -33,9 +33,12 @@ class DateTimeBase : public EntityBase {
class DateTimeStateTrigger : public Trigger<ESPTime> {
public:
explicit DateTimeStateTrigger(DateTimeBase *parent) {
parent->add_on_state_callback([this, parent]() { this->trigger(parent->state_as_esptime()); });
explicit DateTimeStateTrigger(DateTimeBase *parent) : parent_(parent) {
parent->add_on_state_callback([this]() { this->trigger(this->parent_->state_as_esptime()); });
}
protected:
DateTimeBase *parent_;
};
} // namespace esphome::datetime
@@ -96,37 +96,52 @@ template<typename... Ts> class IsActiveCondition : public Condition<Ts...> {
class DisplayMenuOnEnterTrigger : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnEnterTrigger(MenuItem *parent) {
parent->add_on_enter_callback([this, parent]() { this->trigger(parent); });
explicit DisplayMenuOnEnterTrigger(MenuItem *parent) : parent_(parent) {
parent->add_on_enter_callback([this]() { this->trigger(this->parent_); });
}
protected:
MenuItem *parent_;
};
class DisplayMenuOnLeaveTrigger : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnLeaveTrigger(MenuItem *parent) {
parent->add_on_leave_callback([this, parent]() { this->trigger(parent); });
explicit DisplayMenuOnLeaveTrigger(MenuItem *parent) : parent_(parent) {
parent->add_on_leave_callback([this]() { this->trigger(this->parent_); });
}
protected:
MenuItem *parent_;
};
class DisplayMenuOnValueTrigger : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnValueTrigger(MenuItem *parent) {
parent->add_on_value_callback([this, parent]() { this->trigger(parent); });
explicit DisplayMenuOnValueTrigger(MenuItem *parent) : parent_(parent) {
parent->add_on_value_callback([this]() { this->trigger(this->parent_); });
}
protected:
MenuItem *parent_;
};
class DisplayMenuOnNextTrigger : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnNextTrigger(MenuItemCustom *parent) {
parent->add_on_next_callback([this, parent]() { this->trigger(parent); });
explicit DisplayMenuOnNextTrigger(MenuItemCustom *parent) : parent_(parent) {
parent->add_on_next_callback([this]() { this->trigger(this->parent_); });
}
protected:
MenuItemCustom *parent_;
};
class DisplayMenuOnPrevTrigger : public Trigger<const MenuItem *> {
public:
explicit DisplayMenuOnPrevTrigger(MenuItemCustom *parent) {
parent->add_on_prev_callback([this, parent]() { this->trigger(parent); });
explicit DisplayMenuOnPrevTrigger(MenuItemCustom *parent) : parent_(parent) {
parent->add_on_prev_callback([this]() { this->trigger(this->parent_); });
}
protected:
MenuItemCustom *parent_;
};
} // namespace display_menu_base
+35 -20
View File
@@ -12,58 +12,73 @@ namespace esp32_improv {
class ESP32ImprovProvisionedTrigger : public Trigger<> {
public:
explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) {
parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
if (state == improv::STATE_PROVISIONED && !parent->is_failed()) {
trigger();
explicit ESP32ImprovProvisionedTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
if (state == improv::STATE_PROVISIONED && !this->parent_->is_failed()) {
this->trigger();
}
});
}
protected:
ESP32ImprovComponent *parent_;
};
class ESP32ImprovProvisioningTrigger : public Trigger<> {
public:
explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) {
parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
if (state == improv::STATE_PROVISIONING && !parent->is_failed()) {
trigger();
explicit ESP32ImprovProvisioningTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
if (state == improv::STATE_PROVISIONING && !this->parent_->is_failed()) {
this->trigger();
}
});
}
protected:
ESP32ImprovComponent *parent_;
};
class ESP32ImprovStartTrigger : public Trigger<> {
public:
explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) {
parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
explicit ESP32ImprovStartTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
if ((state == improv::STATE_AUTHORIZED || state == improv::STATE_AWAITING_AUTHORIZATION) &&
!parent->is_failed()) {
trigger();
!this->parent_->is_failed()) {
this->trigger();
}
});
}
protected:
ESP32ImprovComponent *parent_;
};
class ESP32ImprovStateTrigger : public Trigger<improv::State, improv::Error> {
public:
explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) {
parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
if (!parent->is_failed()) {
trigger(state, error);
explicit ESP32ImprovStateTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
if (!this->parent_->is_failed()) {
this->trigger(state, error);
}
});
}
protected:
ESP32ImprovComponent *parent_;
};
class ESP32ImprovStoppedTrigger : public Trigger<> {
public:
explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) {
parent->add_on_state_callback([this, parent](improv::State state, improv::Error error) {
if (state == improv::STATE_STOPPED && !parent->is_failed()) {
trigger();
explicit ESP32ImprovStoppedTrigger(ESP32ImprovComponent *parent) : parent_(parent) {
parent->add_on_state_callback([this](improv::State state, improv::Error error) {
if (state == improv::STATE_STOPPED && !this->parent_->is_failed()) {
this->trigger();
}
});
}
protected:
ESP32ImprovComponent *parent_;
};
} // namespace esp32_improv
+29 -20
View File
@@ -113,16 +113,19 @@ template<typename... Ts> class FanIsOffCondition : public Condition<Ts...> {
class FanStateTrigger : public Trigger<Fan *> {
public:
FanStateTrigger(Fan *state) {
state->add_on_state_callback([this, state]() { this->trigger(state); });
FanStateTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() { this->trigger(this->fan_); });
}
protected:
Fan *fan_;
};
class FanTurnOnTrigger : public Trigger<> {
public:
FanTurnOnTrigger(Fan *state) {
state->add_on_state_callback([this, state]() {
auto is_on = state->state;
FanTurnOnTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() {
auto is_on = this->fan_->state;
auto should_trigger = is_on && !this->last_on_;
this->last_on_ = is_on;
if (should_trigger) {
@@ -133,14 +136,15 @@ class FanTurnOnTrigger : public Trigger<> {
}
protected:
Fan *fan_;
bool last_on_;
};
class FanTurnOffTrigger : public Trigger<> {
public:
FanTurnOffTrigger(Fan *state) {
state->add_on_state_callback([this, state]() {
auto is_on = state->state;
FanTurnOffTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() {
auto is_on = this->fan_->state;
auto should_trigger = !is_on && this->last_on_;
this->last_on_ = is_on;
if (should_trigger) {
@@ -151,14 +155,15 @@ class FanTurnOffTrigger : public Trigger<> {
}
protected:
Fan *fan_;
bool last_on_;
};
class FanDirectionSetTrigger : public Trigger<FanDirection> {
public:
FanDirectionSetTrigger(Fan *state) {
state->add_on_state_callback([this, state]() {
auto direction = state->direction;
FanDirectionSetTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() {
auto direction = this->fan_->direction;
auto should_trigger = direction != this->last_direction_;
this->last_direction_ = direction;
if (should_trigger) {
@@ -169,14 +174,15 @@ class FanDirectionSetTrigger : public Trigger<FanDirection> {
}
protected:
Fan *fan_;
FanDirection last_direction_;
};
class FanOscillatingSetTrigger : public Trigger<bool> {
public:
FanOscillatingSetTrigger(Fan *state) {
state->add_on_state_callback([this, state]() {
auto oscillating = state->oscillating;
FanOscillatingSetTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() {
auto oscillating = this->fan_->oscillating;
auto should_trigger = oscillating != this->last_oscillating_;
this->last_oscillating_ = oscillating;
if (should_trigger) {
@@ -187,14 +193,15 @@ class FanOscillatingSetTrigger : public Trigger<bool> {
}
protected:
Fan *fan_;
bool last_oscillating_;
};
class FanSpeedSetTrigger : public Trigger<int> {
public:
FanSpeedSetTrigger(Fan *state) {
state->add_on_state_callback([this, state]() {
auto speed = state->speed;
FanSpeedSetTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() {
auto speed = this->fan_->speed;
auto should_trigger = speed != this->last_speed_;
this->last_speed_ = speed;
if (should_trigger) {
@@ -205,14 +212,15 @@ class FanSpeedSetTrigger : public Trigger<int> {
}
protected:
Fan *fan_;
int last_speed_;
};
class FanPresetSetTrigger : public Trigger<StringRef> {
public:
FanPresetSetTrigger(Fan *state) {
state->add_on_state_callback([this, state]() {
auto preset_mode = state->get_preset_mode();
FanPresetSetTrigger(Fan *state) : fan_(state) {
state->add_on_state_callback([this]() {
auto preset_mode = this->fan_->get_preset_mode();
auto should_trigger = preset_mode != this->last_preset_mode_;
this->last_preset_mode_ = preset_mode;
if (should_trigger) {
@@ -223,6 +231,7 @@ class FanPresetSetTrigger : public Trigger<StringRef> {
}
protected:
Fan *fan_;
StringRef last_preset_mode_{};
};
@@ -75,9 +75,12 @@ class GraphicalDisplayMenu : public display_menu_base::DisplayMenuComponent {
class GraphicalDisplayMenuOnRedrawTrigger : public Trigger<const GraphicalDisplayMenu *> {
public:
explicit GraphicalDisplayMenuOnRedrawTrigger(GraphicalDisplayMenu *parent) {
parent->add_on_redraw_callback([this, parent]() { this->trigger(parent); });
explicit GraphicalDisplayMenuOnRedrawTrigger(GraphicalDisplayMenu *parent) : parent_(parent) {
parent->add_on_redraw_callback([this]() { this->trigger(this->parent_); });
}
protected:
GraphicalDisplayMenu *parent_;
};
} // namespace graphical_display_menu
+6 -3
View File
@@ -51,13 +51,16 @@ template<typename... Ts> class LockCondition : public Condition<Ts...> {
template<LockState State> class LockStateTrigger : public Trigger<> {
public:
explicit LockStateTrigger(Lock *a_lock) {
a_lock->add_on_state_callback([this, a_lock]() {
if (a_lock->state == State) {
explicit LockStateTrigger(Lock *a_lock) : lock_(a_lock) {
a_lock->add_on_state_callback([this]() {
if (this->lock_->state == State) {
this->trigger();
}
});
}
protected:
Lock *lock_;
};
using LockLockTrigger = LockStateTrigger<LockState::LOCK_STATE_LOCKED>;
+6 -3
View File
@@ -80,12 +80,15 @@ class StateTrigger : public Trigger<> {
template<MediaPlayerState State> class MediaPlayerStateTrigger : public Trigger<> {
public:
explicit MediaPlayerStateTrigger(MediaPlayer *player) {
player->add_on_state_callback([this, player]() {
if (player->state == State)
explicit MediaPlayerStateTrigger(MediaPlayer *player) : player_(player) {
player->add_on_state_callback([this]() {
if (this->player_->state == State)
this->trigger();
});
}
protected:
MediaPlayer *player_;
};
using IdleTrigger = MediaPlayerStateTrigger<MediaPlayerState::MEDIA_PLAYER_STATE_IDLE>;
+1 -2
View File
@@ -121,8 +121,7 @@ void MQTTFanComponent::setup() {
});
}
auto f = std::bind(&MQTTFanComponent::publish_state, this);
this->state_->add_on_state_callback([this, f]() { this->defer("send", f); });
this->state_->add_on_state_callback([this]() { this->defer("send", [this]() { this->publish_state(); }); });
}
void MQTTFanComponent::dump_config() {
+12 -6
View File
@@ -87,24 +87,30 @@ template<typename... Ts> class ValveIsClosedCondition : public Condition<Ts...>
class ValveOpenTrigger : public Trigger<> {
public:
ValveOpenTrigger(Valve *a_valve) {
a_valve->add_on_state_callback([this, a_valve]() {
if (a_valve->is_fully_open()) {
ValveOpenTrigger(Valve *a_valve) : valve_(a_valve) {
a_valve->add_on_state_callback([this]() {
if (this->valve_->is_fully_open()) {
this->trigger();
}
});
}
protected:
Valve *valve_;
};
class ValveClosedTrigger : public Trigger<> {
public:
ValveClosedTrigger(Valve *a_valve) {
a_valve->add_on_state_callback([this, a_valve]() {
if (a_valve->is_fully_closed()) {
ValveClosedTrigger(Valve *a_valve) : valve_(a_valve) {
a_valve->add_on_state_callback([this]() {
if (this->valve_->is_fully_closed()) {
this->trigger();
}
});
}
protected:
Valve *valve_;
};
} // namespace valve