This commit is contained in:
J. Nick Koston
2025-11-28 16:23:31 -06:00
parent e8bc19a07d
commit 3c1c19da1c
4 changed files with 50 additions and 76 deletions

View File

@@ -36,7 +36,7 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state)));
this->current_state_ = state;
for (auto *listener : this->listeners_) {
for (auto *listener : this->state_listeners_) {
listener->on_state(state, prev_state);
}
@@ -52,12 +52,12 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
}
void AlarmControlPanel::notify_chime() {
for (auto *listener : this->listeners_)
for (auto *listener : this->event_listeners_)
listener->on_chime();
}
void AlarmControlPanel::notify_ready() {
for (auto *listener : this->listeners_)
for (auto *listener : this->event_listeners_)
listener->on_ready();
}

View File

@@ -14,16 +14,21 @@
namespace esphome {
namespace alarm_control_panel {
/// Listener interface for alarm control panel events.
/// Implement this interface and register with add_listener() to receive notifications.
class AlarmControlPanelListener {
/// Listener interface for alarm control panel state changes.
class AlarmControlPanelStateListener {
public:
virtual ~AlarmControlPanelListener() = default;
/// Called when state changes. Check new_state to filter specific states.
virtual void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) {}
virtual ~AlarmControlPanelStateListener() = default;
/// Called when state changes. Check new_state/prev_state to filter specific states.
virtual void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) = 0;
};
/// Listener interface for alarm events (chime, ready, etc).
class AlarmControlPanelEventListener {
public:
virtual ~AlarmControlPanelEventListener() = default;
/// Called when a chime zone opens while disarmed.
virtual void on_chime() {}
/// Called when ready state changes.
/// Called when zones ready state changes.
virtual void on_ready() {}
};
@@ -50,11 +55,17 @@ class AlarmControlPanel : public EntityBase {
*/
void publish_state(AlarmControlPanelState state);
/** Register a listener for alarm control panel events.
/** Register a listener for state changes.
*
* @param listener The listener to add (must remain valid for lifetime of panel)
*/
void add_listener(AlarmControlPanelListener *listener) { this->listeners_.push_back(listener); }
void add_listener(AlarmControlPanelStateListener *listener) { this->state_listeners_.push_back(listener); }
/** Register a listener for alarm events (chime/ready/etc).
*
* @param listener The listener to add (must remain valid for lifetime of panel)
*/
void add_listener(AlarmControlPanelEventListener *listener) { this->event_listeners_.push_back(listener); }
/** Notify listeners of a chime event (zone opened while disarmed).
*/
@@ -135,8 +146,10 @@ class AlarmControlPanel : public EntityBase {
uint32_t last_update_;
// the call control function
virtual void control(const AlarmControlPanelCall &call) = 0;
// registered listeners
std::vector<AlarmControlPanelListener *> listeners_;
// registered state listeners
std::vector<AlarmControlPanelStateListener *> state_listeners_;
// registered event listeners (chime/ready/etc)
std::vector<AlarmControlPanelEventListener *> event_listeners_;
};
} // namespace alarm_control_panel

View File

@@ -6,76 +6,35 @@
namespace esphome {
namespace alarm_control_panel {
class StateTrigger final : public Trigger<>, public AlarmControlPanelListener {
/// Trigger on any state change
class StateTrigger final : public Trigger<>, public AlarmControlPanelStateListener {
public:
explicit StateTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override { this->trigger(); }
};
class TriggeredTrigger final : public Trigger<>, public AlarmControlPanelListener {
/// Template trigger that fires when entering a specific state
template<AlarmControlPanelState State>
class StateEnterTrigger final : public Trigger<>, public AlarmControlPanelStateListener {
public:
explicit TriggeredTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
explicit StateEnterTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_TRIGGERED)
if (new_state == State)
this->trigger();
}
};
class ArmingTrigger final : public Trigger<>, public AlarmControlPanelListener {
public:
explicit ArmingTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_ARMING)
this->trigger();
}
};
// Type aliases for state-specific triggers
using TriggeredTrigger = StateEnterTrigger<ACP_STATE_TRIGGERED>;
using ArmingTrigger = StateEnterTrigger<ACP_STATE_ARMING>;
using PendingTrigger = StateEnterTrigger<ACP_STATE_PENDING>;
using ArmedHomeTrigger = StateEnterTrigger<ACP_STATE_ARMED_HOME>;
using ArmedNightTrigger = StateEnterTrigger<ACP_STATE_ARMED_NIGHT>;
using ArmedAwayTrigger = StateEnterTrigger<ACP_STATE_ARMED_AWAY>;
using DisarmedTrigger = StateEnterTrigger<ACP_STATE_DISARMED>;
class PendingTrigger final : public Trigger<>, public AlarmControlPanelListener {
public:
explicit PendingTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_PENDING)
this->trigger();
}
};
class ArmedHomeTrigger final : public Trigger<>, public AlarmControlPanelListener {
public:
explicit ArmedHomeTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_ARMED_HOME)
this->trigger();
}
};
class ArmedNightTrigger final : public Trigger<>, public AlarmControlPanelListener {
public:
explicit ArmedNightTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_ARMED_NIGHT)
this->trigger();
}
};
class ArmedAwayTrigger final : public Trigger<>, public AlarmControlPanelListener {
public:
explicit ArmedAwayTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_ARMED_AWAY)
this->trigger();
}
};
class DisarmedTrigger final : public Trigger<>, public AlarmControlPanelListener {
public:
explicit DisarmedTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
if (new_state == ACP_STATE_DISARMED)
this->trigger();
}
};
class ClearedTrigger final : public Trigger<>, public AlarmControlPanelListener {
/// Trigger when leaving TRIGGERED state (alarm cleared)
class ClearedTrigger final : public Trigger<>, public AlarmControlPanelStateListener {
public:
explicit ClearedTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
@@ -84,13 +43,15 @@ class ClearedTrigger final : public Trigger<>, public AlarmControlPanelListener
}
};
class ChimeTrigger final : public Trigger<>, public AlarmControlPanelListener {
/// Trigger on chime event (zone opened while disarmed)
class ChimeTrigger final : public Trigger<>, public AlarmControlPanelEventListener {
public:
explicit ChimeTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_chime() override { this->trigger(); }
};
class ReadyTrigger final : public Trigger<>, public AlarmControlPanelListener {
/// Trigger on ready state change
class ReadyTrigger final : public Trigger<>, public AlarmControlPanelEventListener {
public:
explicit ReadyTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
void on_ready() override { this->trigger(); }

View File

@@ -12,7 +12,7 @@ namespace esphome {
namespace mqtt {
class MQTTAlarmControlPanelComponent final : public mqtt::MQTTComponent,
public alarm_control_panel::AlarmControlPanelListener {
public alarm_control_panel::AlarmControlPanelStateListener {
public:
explicit MQTTAlarmControlPanelComponent(alarm_control_panel::AlarmControlPanel *alarm_control_panel);
@@ -26,7 +26,7 @@ class MQTTAlarmControlPanelComponent final : public mqtt::MQTTComponent,
void dump_config() override;
// AlarmControlPanelListener interface
// AlarmControlPanelStateListener interface
void on_state(alarm_control_panel::AlarmControlPanelState new_state,
alarm_control_panel::AlarmControlPanelState prev_state) override {
this->publish_state();