diff --git a/esphome/components/alarm_control_panel/__init__.py b/esphome/components/alarm_control_panel/__init__.py index 52f8ac7894..d9cafb4f30 100644 --- a/esphome/components/alarm_control_panel/__init__.py +++ b/esphome/components/alarm_control_panel/__init__.py @@ -16,6 +16,12 @@ IS_PLATFORM_COMPONENT = True CONF_ON_TRIGGERED = "on_triggered" CONF_ON_CLEARED = "on_cleared" +CONF_ON_ARMING = "on_arming" +CONF_ON_PENDING = "on_pending" +CONF_ON_ARMED_HOME = "on_armed_home" +CONF_ON_ARMED_NIGHT = "on_armed_night" +CONF_ON_ARMED_AWAY = "on_armed_away" +CONF_ON_DISARMED = "on_disarmed" alarm_control_panel_ns = cg.esphome_ns.namespace("alarm_control_panel") AlarmControlPanel = alarm_control_panel_ns.class_("AlarmControlPanel", cg.EntityBase) @@ -29,6 +35,24 @@ TriggeredTrigger = alarm_control_panel_ns.class_( ClearedTrigger = alarm_control_panel_ns.class_( "ClearedTrigger", automation.Trigger.template() ) +ArmingTrigger = alarm_control_panel_ns.class_( + "ArmingTrigger", automation.Trigger.template() +) +PendingTrigger = alarm_control_panel_ns.class_( + "PendingTrigger", automation.Trigger.template() +) +ArmedHomeTrigger = alarm_control_panel_ns.class_( + "ArmedHomeTrigger", automation.Trigger.template() +) +ArmedNightTrigger = alarm_control_panel_ns.class_( + "ArmedNightTrigger", automation.Trigger.template() +) +ArmedAwayTrigger = alarm_control_panel_ns.class_( + "ArmedAwayTrigger", automation.Trigger.template() +) +DisarmedTrigger = alarm_control_panel_ns.class_( + "DisarmedTrigger", automation.Trigger.template() +) ArmAwayAction = alarm_control_panel_ns.class_("ArmAwayAction", automation.Action) ArmHomeAction = alarm_control_panel_ns.class_("ArmHomeAction", automation.Action) ArmNightAction = alarm_control_panel_ns.class_("ArmNightAction", automation.Action) @@ -52,6 +76,36 @@ ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(TriggeredTrigger), } ), + cv.Optional(CONF_ON_ARMING): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmingTrigger), + } + ), + cv.Optional(CONF_ON_PENDING): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(PendingTrigger), + } + ), + cv.Optional(CONF_ON_ARMED_HOME): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedHomeTrigger), + } + ), + cv.Optional(CONF_ON_ARMED_NIGHT): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedNightTrigger), + } + ), + cv.Optional(CONF_ON_ARMED_AWAY): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ArmedAwayTrigger), + } + ), + cv.Optional(CONF_ON_DISARMED): automation.validate_automation( + { + cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(DisarmedTrigger), + } + ), cv.Optional(CONF_ON_CLEARED): automation.validate_automation( { cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ClearedTrigger), @@ -82,6 +136,24 @@ async def setup_alarm_control_panel_core_(var, config): for conf in config.get(CONF_ON_TRIGGERED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_ARMING, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_PENDING, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_ARMED_HOME, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_ARMED_NIGHT, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_ARMED_AWAY, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) + for conf in config.get(CONF_ON_DISARMED, []): + trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) + await automation.build_automation(trigger, [], conf) for conf in config.get(CONF_ON_CLEARED, []): trigger = cg.new_Pvariable(conf[CONF_TRIGGER_ID], var) await automation.build_automation(trigger, [], conf) diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.cpp b/esphome/components/alarm_control_panel/alarm_control_panel.cpp index 74c9a502df..9dc083c004 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.cpp +++ b/esphome/components/alarm_control_panel/alarm_control_panel.cpp @@ -36,7 +36,20 @@ void AlarmControlPanel::publish_state(AlarmControlPanelState state) { this->state_callback_.call(); 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(); } @@ -55,6 +68,30 @@ void AlarmControlPanel::add_on_triggered_callback(std::function &&callba this->triggered_callback_.add(std::move(callback)); } +void AlarmControlPanel::add_on_arming_callback(std::function &&callback) { + this->arming_callback_.add(std::move(callback)); +} + +void AlarmControlPanel::add_on_armed_home_callback(std::function &&callback) { + this->armed_home_callback_.add(std::move(callback)); +} + +void AlarmControlPanel::add_on_armed_night_callback(std::function &&callback) { + this->armed_night_callback_.add(std::move(callback)); +} + +void AlarmControlPanel::add_on_armed_away_callback(std::function &&callback) { + this->armed_away_callback_.add(std::move(callback)); +} + +void AlarmControlPanel::add_on_pending_callback(std::function &&callback) { + this->pending_callback_.add(std::move(callback)); +} + +void AlarmControlPanel::add_on_disarmed_callback(std::function &&callback) { + this->disarmed_callback_.add(std::move(callback)); +} + void AlarmControlPanel::add_on_cleared_callback(std::function &&callback) { this->cleared_callback_.add(std::move(callback)); } diff --git a/esphome/components/alarm_control_panel/alarm_control_panel.h b/esphome/components/alarm_control_panel/alarm_control_panel.h index 4f15ccb45a..dc0b92df76 100644 --- a/esphome/components/alarm_control_panel/alarm_control_panel.h +++ b/esphome/components/alarm_control_panel/alarm_control_panel.h @@ -47,6 +47,42 @@ class AlarmControlPanel : public EntityBase { */ void add_on_triggered_callback(std::function &&callback); + /** Add a callback for when the state of the alarm_control_panel chanes to arming + * + * @param callback The callback function + */ + void add_on_arming_callback(std::function &&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 &&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 &&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 &&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 &&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 &&callback); + /** Add a callback for when the state of the alarm_control_panel clears from triggered * * @param callback The callback function @@ -128,6 +164,18 @@ class AlarmControlPanel : public EntityBase { CallbackManager state_callback_{}; // trigger callback CallbackManager triggered_callback_{}; + // arming callback + CallbackManager arming_callback_{}; + // pending callback + CallbackManager pending_callback_{}; + // armed_home callback + CallbackManager armed_home_callback_{}; + // armed_night callback + CallbackManager armed_night_callback_{}; + // armed_away callback + CallbackManager armed_away_callback_{}; + // disarmed callback + CallbackManager disarmed_callback_{}; // clear callback CallbackManager cleared_callback_{}; }; diff --git a/esphome/components/alarm_control_panel/automation.h b/esphome/components/alarm_control_panel/automation.h index 81ac584f71..8538020c53 100644 --- a/esphome/components/alarm_control_panel/automation.h +++ b/esphome/components/alarm_control_panel/automation.h @@ -20,6 +20,48 @@ class TriggeredTrigger : public Trigger<> { } }; +class ArmingTrigger : public Trigger<> { + public: + explicit ArmingTrigger(AlarmControlPanel *alarm_control_panel) { + alarm_control_panel->add_on_arming_callback([this]() { this->trigger(); }); + } +}; + +class PendingTrigger : public Trigger<> { + public: + explicit PendingTrigger(AlarmControlPanel *alarm_control_panel) { + alarm_control_panel->add_on_pending_callback([this]() { this->trigger(); }); + } +}; + +class ArmedHomeTrigger : public Trigger<> { + public: + explicit ArmedHomeTrigger(AlarmControlPanel *alarm_control_panel) { + alarm_control_panel->add_on_armed_home_callback([this]() { this->trigger(); }); + } +}; + +class ArmedNightTrigger : public Trigger<> { + public: + explicit ArmedNightTrigger(AlarmControlPanel *alarm_control_panel) { + alarm_control_panel->add_on_armed_night_callback([this]() { this->trigger(); }); + } +}; + +class ArmedAwayTrigger : public Trigger<> { + public: + explicit ArmedAwayTrigger(AlarmControlPanel *alarm_control_panel) { + alarm_control_panel->add_on_armed_away_callback([this]() { this->trigger(); }); + } +}; + +class DisarmedTrigger : public Trigger<> { + public: + explicit DisarmedTrigger(AlarmControlPanel *alarm_control_panel) { + alarm_control_panel->add_on_disarmed_callback([this]() { this->trigger(); }); + } +}; + class ClearedTrigger : public Trigger<> { public: explicit ClearedTrigger(AlarmControlPanel *alarm_control_panel) { diff --git a/tests/test3.yaml b/tests/test3.yaml index 3ab1d561b3..5bda0afb1b 100644 --- a/tests/test3.yaml +++ b/tests/test3.yaml @@ -1206,3 +1206,42 @@ alarm_control_panel: then: - lambda: !lambda |- ESP_LOGD("TEST", "State change %s", alarm_control_panel_state_to_string(id(alarmcontrolpanel1)->get_state())); + - platform: template + id: alarmcontrolpanel2 + name: Alarm Panel + codes: + - "1234" + requires_code_to_arm: true + arming_home_time: 1s + arming_night_time: 1s + arming_away_time: 15s + pending_time: 15s + trigger_time: 30s + binary_sensors: + - input: bin1 + bypass_armed_home: true + bypass_armed_night: true + on_disarmed: + then: + - logger.log: "### DISARMED ###" + on_pending: + then: + - logger.log: "### PENDING ###" + on_arming: + then: + - logger.log: "### ARMING ###" + on_armed_home: + then: + - logger.log: "### ARMED HOME ###" + on_armed_night: + then: + - logger.log: "### ARMED NIGHT ###" + on_armed_away: + then: + - logger.log: "### ARMED AWAY ###" + on_triggered: + then: + - logger.log: "### TRIGGERED ###" + on_cleared: + then: + - logger.log: "### CLEARED ###"