mirror of
https://github.com/esphome/esphome.git
synced 2026-02-19 07:55:35 -07:00
[alarm_control_panel] Replace callbacks with listener interface
This commit is contained in:
@@ -35,29 +35,15 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
|
||||
ESP_LOGD(TAG, "Set state to: %s, previous: %s", LOG_STR_ARG(alarm_control_panel_state_to_string(state)),
|
||||
LOG_STR_ARG(alarm_control_panel_state_to_string(prev_state)));
|
||||
this->current_state_ = state;
|
||||
this->state_callback_.call();
|
||||
|
||||
for (auto *listener : this->listeners_) {
|
||||
listener->on_state(state, prev_state);
|
||||
}
|
||||
|
||||
#if defined(USE_ALARM_CONTROL_PANEL) && defined(USE_CONTROLLER_REGISTRY)
|
||||
ControllerRegistry::notify_alarm_control_panel_update(this);
|
||||
#endif
|
||||
if (state == ACP_STATE_TRIGGERED) {
|
||||
this->triggered_callback_.call();
|
||||
} else if (state == ACP_STATE_ARMING) {
|
||||
this->arming_callback_.call();
|
||||
} else if (state == ACP_STATE_PENDING) {
|
||||
this->pending_callback_.call();
|
||||
} else if (state == ACP_STATE_ARMED_HOME) {
|
||||
this->armed_home_callback_.call();
|
||||
} else if (state == ACP_STATE_ARMED_NIGHT) {
|
||||
this->armed_night_callback_.call();
|
||||
} else if (state == ACP_STATE_ARMED_AWAY) {
|
||||
this->armed_away_callback_.call();
|
||||
} else if (state == ACP_STATE_DISARMED) {
|
||||
this->disarmed_callback_.call();
|
||||
}
|
||||
|
||||
if (prev_state == ACP_STATE_TRIGGERED) {
|
||||
this->cleared_callback_.call();
|
||||
}
|
||||
if (state == this->desired_state_) {
|
||||
// only store when in the desired state
|
||||
this->pref_.save(&state);
|
||||
@@ -65,48 +51,14 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) {
|
||||
}
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_state_callback(std::function<void()> &&callback) {
|
||||
this->state_callback_.add(std::move(callback));
|
||||
void AlarmControlPanel::notify_chime() {
|
||||
for (auto *listener : this->listeners_)
|
||||
listener->on_chime();
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_triggered_callback(std::function<void()> &&callback) {
|
||||
this->triggered_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_arming_callback(std::function<void()> &&callback) {
|
||||
this->arming_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_armed_home_callback(std::function<void()> &&callback) {
|
||||
this->armed_home_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_armed_night_callback(std::function<void()> &&callback) {
|
||||
this->armed_night_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_armed_away_callback(std::function<void()> &&callback) {
|
||||
this->armed_away_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_pending_callback(std::function<void()> &&callback) {
|
||||
this->pending_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_disarmed_callback(std::function<void()> &&callback) {
|
||||
this->disarmed_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_cleared_callback(std::function<void()> &&callback) {
|
||||
this->cleared_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_chime_callback(std::function<void()> &&callback) {
|
||||
this->chime_callback_.add(std::move(callback));
|
||||
}
|
||||
|
||||
void AlarmControlPanel::add_on_ready_callback(std::function<void()> &&callback) {
|
||||
this->ready_callback_.add(std::move(callback));
|
||||
void AlarmControlPanel::notify_ready() {
|
||||
for (auto *listener : this->listeners_)
|
||||
listener->on_ready();
|
||||
}
|
||||
|
||||
void AlarmControlPanel::arm_away(optional<std::string> code) {
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include "alarm_control_panel_call.h"
|
||||
#include "alarm_control_panel_state.h"
|
||||
|
||||
#include "esphome/core/automation.h"
|
||||
#include "esphome/core/component.h"
|
||||
#include "esphome/core/entity_base.h"
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
#include "esphome/core/preferences.h"
|
||||
|
||||
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 {
|
||||
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) {}
|
||||
/// Called when a chime zone opens while disarmed.
|
||||
virtual void on_chime() {}
|
||||
/// Called when ready state changes.
|
||||
virtual void on_ready() {}
|
||||
};
|
||||
|
||||
enum AlarmControlPanelFeature : uint8_t {
|
||||
// Matches Home Assistant values
|
||||
ACP_FEAT_ARM_HOME = 1 << 0,
|
||||
@@ -35,71 +50,19 @@ class AlarmControlPanel : public EntityBase {
|
||||
*/
|
||||
void publish_state(AlarmControlPanelState state);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel changes
|
||||
/** Register a listener for alarm control panel events.
|
||||
*
|
||||
* @param callback The callback function
|
||||
* @param listener The listener to add (must remain valid for lifetime of panel)
|
||||
*/
|
||||
void add_on_state_callback(std::function<void()> &&callback);
|
||||
void add_listener(AlarmControlPanelListener *listener) { this->listeners_.push_back(listener); }
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel chanes to triggered
|
||||
*
|
||||
* @param callback The callback function
|
||||
/** Notify listeners of a chime event (zone opened while disarmed).
|
||||
*/
|
||||
void add_on_triggered_callback(std::function<void()> &&callback);
|
||||
void notify_chime();
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel chanes to arming
|
||||
*
|
||||
* @param callback The callback function
|
||||
/** Notify listeners of a ready state change.
|
||||
*/
|
||||
void add_on_arming_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel changes to pending
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_pending_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel changes to armed_home
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_armed_home_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel changes to armed_night
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_armed_night_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel changes to armed_away
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_armed_away_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel changes to disarmed
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_disarmed_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when the state of the alarm_control_panel clears from triggered
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_cleared_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when a chime zone goes from closed to open
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_chime_callback(std::function<void()> &&callback);
|
||||
|
||||
/** Add a callback for when a ready state changes
|
||||
*
|
||||
* @param callback The callback function
|
||||
*/
|
||||
void add_on_ready_callback(std::function<void()> &&callback);
|
||||
void notify_ready();
|
||||
|
||||
/** A numeric representation of the supported features as per HomeAssistant
|
||||
*
|
||||
@@ -172,28 +135,8 @@ class AlarmControlPanel : public EntityBase {
|
||||
uint32_t last_update_;
|
||||
// the call control function
|
||||
virtual void control(const AlarmControlPanelCall &call) = 0;
|
||||
// state callback
|
||||
CallbackManager<void()> state_callback_{};
|
||||
// trigger callback
|
||||
CallbackManager<void()> triggered_callback_{};
|
||||
// arming callback
|
||||
CallbackManager<void()> arming_callback_{};
|
||||
// pending callback
|
||||
CallbackManager<void()> pending_callback_{};
|
||||
// armed_home callback
|
||||
CallbackManager<void()> armed_home_callback_{};
|
||||
// armed_night callback
|
||||
CallbackManager<void()> armed_night_callback_{};
|
||||
// armed_away callback
|
||||
CallbackManager<void()> armed_away_callback_{};
|
||||
// disarmed callback
|
||||
CallbackManager<void()> disarmed_callback_{};
|
||||
// clear callback
|
||||
CallbackManager<void()> cleared_callback_{};
|
||||
// chime callback
|
||||
CallbackManager<void()> chime_callback_{};
|
||||
// ready callback
|
||||
CallbackManager<void()> ready_callback_{};
|
||||
// registered listeners
|
||||
std::vector<AlarmControlPanelListener *> listeners_;
|
||||
};
|
||||
|
||||
} // namespace alarm_control_panel
|
||||
|
||||
@@ -6,81 +6,94 @@
|
||||
namespace esphome {
|
||||
namespace alarm_control_panel {
|
||||
|
||||
class StateTrigger : public Trigger<> {
|
||||
class StateTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit StateTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_state_callback([this]() { this->trigger(); });
|
||||
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 {
|
||||
public:
|
||||
explicit TriggeredTrigger(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)
|
||||
this->trigger();
|
||||
}
|
||||
};
|
||||
|
||||
class TriggeredTrigger : public Trigger<> {
|
||||
class ArmingTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit TriggeredTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_triggered_callback([this]() { this->trigger(); });
|
||||
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();
|
||||
}
|
||||
};
|
||||
|
||||
class ArmingTrigger : public Trigger<> {
|
||||
class PendingTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit ArmingTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_arming_callback([this]() { this->trigger(); });
|
||||
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 PendingTrigger : public Trigger<> {
|
||||
class ArmedHomeTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit PendingTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_pending_callback([this]() { this->trigger(); });
|
||||
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 ArmedHomeTrigger : public Trigger<> {
|
||||
class ArmedNightTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit ArmedHomeTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_armed_home_callback([this]() { this->trigger(); });
|
||||
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 ArmedNightTrigger : public Trigger<> {
|
||||
class ArmedAwayTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit ArmedNightTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_armed_night_callback([this]() { this->trigger(); });
|
||||
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 ArmedAwayTrigger : public Trigger<> {
|
||||
class DisarmedTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit ArmedAwayTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_armed_away_callback([this]() { this->trigger(); });
|
||||
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 DisarmedTrigger : public Trigger<> {
|
||||
class ClearedTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit DisarmedTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_disarmed_callback([this]() { this->trigger(); });
|
||||
explicit ClearedTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
|
||||
void on_state(AlarmControlPanelState new_state, AlarmControlPanelState prev_state) override {
|
||||
if (prev_state == ACP_STATE_TRIGGERED)
|
||||
this->trigger();
|
||||
}
|
||||
};
|
||||
|
||||
class ClearedTrigger : public Trigger<> {
|
||||
class ChimeTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit ClearedTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_cleared_callback([this]() { this->trigger(); });
|
||||
}
|
||||
explicit ChimeTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
|
||||
void on_chime() override { this->trigger(); }
|
||||
};
|
||||
|
||||
class ChimeTrigger : public Trigger<> {
|
||||
class ReadyTrigger final : public Trigger<>, public AlarmControlPanelListener {
|
||||
public:
|
||||
explicit ChimeTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_chime_callback([this]() { this->trigger(); });
|
||||
}
|
||||
};
|
||||
|
||||
class ReadyTrigger : public Trigger<> {
|
||||
public:
|
||||
explicit ReadyTrigger(AlarmControlPanel *alarm_control_panel) {
|
||||
alarm_control_panel->add_on_ready_callback([this]() { this->trigger(); });
|
||||
}
|
||||
explicit ReadyTrigger(AlarmControlPanel *alarm_control_panel) { alarm_control_panel->add_listener(this); }
|
||||
void on_ready() override { this->trigger(); }
|
||||
};
|
||||
|
||||
template<typename... Ts> class ArmAwayAction : public Action<Ts...> {
|
||||
|
||||
@@ -16,7 +16,7 @@ using namespace esphome::alarm_control_panel;
|
||||
MQTTAlarmControlPanelComponent::MQTTAlarmControlPanelComponent(AlarmControlPanel *alarm_control_panel)
|
||||
: alarm_control_panel_(alarm_control_panel) {}
|
||||
void MQTTAlarmControlPanelComponent::setup() {
|
||||
this->alarm_control_panel_->add_on_state_callback([this]() { this->publish_state(); });
|
||||
this->alarm_control_panel_->add_listener(this);
|
||||
this->subscribe(this->get_command_topic_(), [this](const std::string &topic, const std::string &payload) {
|
||||
auto call = this->alarm_control_panel_->make_call();
|
||||
if (strcasecmp(payload.c_str(), "ARM_AWAY") == 0) {
|
||||
|
||||
@@ -11,7 +11,8 @@
|
||||
namespace esphome {
|
||||
namespace mqtt {
|
||||
|
||||
class MQTTAlarmControlPanelComponent : public mqtt::MQTTComponent {
|
||||
class MQTTAlarmControlPanelComponent final : public mqtt::MQTTComponent,
|
||||
public alarm_control_panel::AlarmControlPanelListener {
|
||||
public:
|
||||
explicit MQTTAlarmControlPanelComponent(alarm_control_panel::AlarmControlPanel *alarm_control_panel);
|
||||
|
||||
@@ -25,6 +26,12 @@ class MQTTAlarmControlPanelComponent : public mqtt::MQTTComponent {
|
||||
|
||||
void dump_config() override;
|
||||
|
||||
// AlarmControlPanelListener interface
|
||||
void on_state(alarm_control_panel::AlarmControlPanelState new_state,
|
||||
alarm_control_panel::AlarmControlPanelState prev_state) override {
|
||||
this->publish_state();
|
||||
}
|
||||
|
||||
protected:
|
||||
std::string component_type() const override;
|
||||
const EntityBase *get_entity() const override;
|
||||
|
||||
@@ -133,7 +133,7 @@ void TemplateAlarmControlPanel::loop() {
|
||||
if ((!this->sensor_data_[info.store_index].last_chime_state) && (sensor->state)) {
|
||||
// Must be disarmed to chime
|
||||
if (this->current_state_ == ACP_STATE_DISARMED) {
|
||||
this->chime_callback_.call();
|
||||
this->notify_chime();
|
||||
}
|
||||
}
|
||||
// Record the sensor state change
|
||||
@@ -182,7 +182,7 @@ void TemplateAlarmControlPanel::loop() {
|
||||
// Call the ready state change callback if there was a change
|
||||
if (this->sensors_ready_ != sensors_ready) {
|
||||
this->sensors_ready_ = sensors_ready;
|
||||
this->ready_callback_.call();
|
||||
this->notify_ready();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user