mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Adds MQTT component to Alarm Control panel component (#7188)
This commit is contained in:
		| @@ -1,16 +1,17 @@ | |||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome.components import web_server |  | ||||||
| from esphome import automation | from esphome import automation | ||||||
| from esphome.automation import maybe_simple_id | from esphome.automation import maybe_simple_id | ||||||
| from esphome.core import CORE, coroutine_with_priority | import esphome.codegen as cg | ||||||
|  | from esphome.components import mqtt, web_server | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|  |     CONF_CODE, | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|  |     CONF_MQTT_ID, | ||||||
|     CONF_ON_STATE, |     CONF_ON_STATE, | ||||||
|     CONF_TRIGGER_ID, |     CONF_TRIGGER_ID, | ||||||
|     CONF_CODE, |  | ||||||
|     CONF_WEB_SERVER_ID, |     CONF_WEB_SERVER_ID, | ||||||
| ) | ) | ||||||
|  | from esphome.core import CORE, coroutine_with_priority | ||||||
| from esphome.cpp_helpers import setup_entity | from esphome.cpp_helpers import setup_entity | ||||||
|  |  | ||||||
| CODEOWNERS = ["@grahambrown11", "@hwstar"] | CODEOWNERS = ["@grahambrown11", "@hwstar"] | ||||||
| @@ -77,11 +78,15 @@ AlarmControlPanelCondition = alarm_control_panel_ns.class_( | |||||||
|     "AlarmControlPanelCondition", automation.Condition |     "AlarmControlPanelCondition", automation.Condition | ||||||
| ) | ) | ||||||
|  |  | ||||||
| ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( | ALARM_CONTROL_PANEL_SCHEMA = ( | ||||||
|     web_server.WEBSERVER_SORTING_SCHEMA |     cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) | ||||||
| ).extend( |     .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) | ||||||
|  |     .extend( | ||||||
|         { |         { | ||||||
|             cv.GenerateID(): cv.declare_id(AlarmControlPanel), |             cv.GenerateID(): cv.declare_id(AlarmControlPanel), | ||||||
|  |             cv.OnlyWith(CONF_MQTT_ID, "mqtt"): cv.declare_id( | ||||||
|  |                 mqtt.MQTTAlarmControlPanelComponent | ||||||
|  |             ), | ||||||
|             cv.Optional(CONF_ON_STATE): automation.validate_automation( |             cv.Optional(CONF_ON_STATE): automation.validate_automation( | ||||||
|                 { |                 { | ||||||
|                     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), |                     cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), | ||||||
| @@ -138,6 +143,7 @@ ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( | |||||||
|                 } |                 } | ||||||
|             ), |             ), | ||||||
|         } |         } | ||||||
|  |     ) | ||||||
| ) | ) | ||||||
|  |  | ||||||
| ALARM_CONTROL_PANEL_ACTION_SCHEMA = maybe_simple_id( | ALARM_CONTROL_PANEL_ACTION_SCHEMA = maybe_simple_id( | ||||||
| @@ -192,6 +198,9 @@ async def setup_alarm_control_panel_core_(var, config): | |||||||
|     if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: |     if (webserver_id := config.get(CONF_WEB_SERVER_ID)) is not None: | ||||||
|         web_server_ = await cg.get_variable(webserver_id) |         web_server_ = await cg.get_variable(webserver_id) | ||||||
|         web_server.add_entity_to_sorting_list(web_server_, var, config) |         web_server.add_entity_to_sorting_list(web_server_, var, config) | ||||||
|  |     if mqtt_id := config.get(CONF_MQTT_ID): | ||||||
|  |         mqtt_ = cg.new_Pvariable(mqtt_id, var) | ||||||
|  |         await mqtt.register_mqtt_component(mqtt_, config) | ||||||
|  |  | ||||||
|  |  | ||||||
| async def register_alarm_control_panel(var, config): | async def register_alarm_control_panel(var, config): | ||||||
|   | |||||||
| @@ -1,10 +1,11 @@ | |||||||
| import re | import re | ||||||
|  |  | ||||||
| import esphome.codegen as cg |  | ||||||
| import esphome.config_validation as cv |  | ||||||
| from esphome import automation | from esphome import automation | ||||||
| from esphome.automation import Condition | from esphome.automation import Condition | ||||||
|  | import esphome.codegen as cg | ||||||
| from esphome.components import logger | from esphome.components import logger | ||||||
|  | from esphome.components.esp32 import add_idf_sdkconfig_option | ||||||
|  | import esphome.config_validation as cv | ||||||
| from esphome.const import ( | from esphome.const import ( | ||||||
|     CONF_AVAILABILITY, |     CONF_AVAILABILITY, | ||||||
|     CONF_BIRTH_MESSAGE, |     CONF_BIRTH_MESSAGE, | ||||||
| @@ -13,21 +14,21 @@ from esphome.const import ( | |||||||
|     CONF_CLIENT_CERTIFICATE, |     CONF_CLIENT_CERTIFICATE, | ||||||
|     CONF_CLIENT_CERTIFICATE_KEY, |     CONF_CLIENT_CERTIFICATE_KEY, | ||||||
|     CONF_CLIENT_ID, |     CONF_CLIENT_ID, | ||||||
|     CONF_COMMAND_TOPIC, |  | ||||||
|     CONF_COMMAND_RETAIN, |     CONF_COMMAND_RETAIN, | ||||||
|  |     CONF_COMMAND_TOPIC, | ||||||
|     CONF_DISCOVERY, |     CONF_DISCOVERY, | ||||||
|  |     CONF_DISCOVERY_OBJECT_ID_GENERATOR, | ||||||
|     CONF_DISCOVERY_PREFIX, |     CONF_DISCOVERY_PREFIX, | ||||||
|     CONF_DISCOVERY_RETAIN, |     CONF_DISCOVERY_RETAIN, | ||||||
|     CONF_DISCOVERY_UNIQUE_ID_GENERATOR, |     CONF_DISCOVERY_UNIQUE_ID_GENERATOR, | ||||||
|     CONF_DISCOVERY_OBJECT_ID_GENERATOR, |  | ||||||
|     CONF_ID, |     CONF_ID, | ||||||
|     CONF_KEEPALIVE, |     CONF_KEEPALIVE, | ||||||
|     CONF_LEVEL, |     CONF_LEVEL, | ||||||
|     CONF_LOG_TOPIC, |     CONF_LOG_TOPIC, | ||||||
|     CONF_ON_JSON_MESSAGE, |  | ||||||
|     CONF_ON_MESSAGE, |  | ||||||
|     CONF_ON_CONNECT, |     CONF_ON_CONNECT, | ||||||
|     CONF_ON_DISCONNECT, |     CONF_ON_DISCONNECT, | ||||||
|  |     CONF_ON_JSON_MESSAGE, | ||||||
|  |     CONF_ON_MESSAGE, | ||||||
|     CONF_PASSWORD, |     CONF_PASSWORD, | ||||||
|     CONF_PAYLOAD, |     CONF_PAYLOAD, | ||||||
|     CONF_PAYLOAD_AVAILABLE, |     CONF_PAYLOAD_AVAILABLE, | ||||||
| @@ -45,12 +46,11 @@ from esphome.const import ( | |||||||
|     CONF_USE_ABBREVIATIONS, |     CONF_USE_ABBREVIATIONS, | ||||||
|     CONF_USERNAME, |     CONF_USERNAME, | ||||||
|     CONF_WILL_MESSAGE, |     CONF_WILL_MESSAGE, | ||||||
|  |     PLATFORM_BK72XX, | ||||||
|     PLATFORM_ESP32, |     PLATFORM_ESP32, | ||||||
|     PLATFORM_ESP8266, |     PLATFORM_ESP8266, | ||||||
|     PLATFORM_BK72XX, |  | ||||||
| ) | ) | ||||||
| from esphome.core import coroutine_with_priority, CORE | from esphome.core import CORE, coroutine_with_priority | ||||||
| from esphome.components.esp32 import add_idf_sdkconfig_option |  | ||||||
|  |  | ||||||
| DEPENDENCIES = ["network"] | DEPENDENCIES = ["network"] | ||||||
|  |  | ||||||
| @@ -110,6 +110,9 @@ MQTTDisconnectTrigger = mqtt_ns.class_( | |||||||
| MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component) | MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component) | ||||||
| MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition) | MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition) | ||||||
|  |  | ||||||
|  | MQTTAlarmControlPanelComponent = mqtt_ns.class_( | ||||||
|  |     "MQTTAlarmControlPanelComponent", MQTTComponent | ||||||
|  | ) | ||||||
| MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent) | MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent) | ||||||
| MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", MQTTComponent) | MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", MQTTComponent) | ||||||
| MQTTCoverComponent = mqtt_ns.class_("MQTTCoverComponent", MQTTComponent) | MQTTCoverComponent = mqtt_ns.class_("MQTTCoverComponent", MQTTComponent) | ||||||
|   | |||||||
							
								
								
									
										128
									
								
								esphome/components/mqtt/mqtt_alarm_control_panel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								esphome/components/mqtt/mqtt_alarm_control_panel.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | #include "mqtt_alarm_control_panel.h" | ||||||
|  | #include "esphome/core/log.h" | ||||||
|  |  | ||||||
|  | #include "mqtt_const.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_MQTT | ||||||
|  | #ifdef USE_ALARM_CONTROL_PANEL | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace mqtt { | ||||||
|  |  | ||||||
|  | static const char *const TAG = "mqtt.alarm_control_panel"; | ||||||
|  |  | ||||||
|  | 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->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) { | ||||||
|  |       call.arm_away(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "ARM_HOME") == 0) { | ||||||
|  |       call.arm_home(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "ARM_NIGHT") == 0) { | ||||||
|  |       call.arm_night(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "ARM_VACATION") == 0) { | ||||||
|  |       call.arm_vacation(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "ARM_CUSTOM_BYPASS") == 0) { | ||||||
|  |       call.arm_custom_bypass(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "DISARM") == 0) { | ||||||
|  |       call.disarm(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "PENDING") == 0) { | ||||||
|  |       call.pending(); | ||||||
|  |     } else if (strcasecmp(payload.c_str(), "TRIGGERED") == 0) { | ||||||
|  |       call.triggered(); | ||||||
|  |     } else { | ||||||
|  |       ESP_LOGW(TAG, "'%s': Received unknown command payload %s", this->friendly_name().c_str(), payload.c_str()); | ||||||
|  |     } | ||||||
|  |     call.perform(); | ||||||
|  |   }); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MQTTAlarmControlPanelComponent::dump_config() { | ||||||
|  |   ESP_LOGCONFIG(TAG, "MQTT alarm_control_panel '%s':", this->alarm_control_panel_->get_name().c_str()); | ||||||
|  |   LOG_MQTT_COMPONENT(true, true) | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Supported Features: %" PRIu32, this->alarm_control_panel_->get_supported_features()); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Requires Code to Disarm: %s", YESNO(this->alarm_control_panel_->get_requires_code())); | ||||||
|  |   ESP_LOGCONFIG(TAG, "  Requires Code To Arm: %s", YESNO(this->alarm_control_panel_->get_requires_code_to_arm())); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void MQTTAlarmControlPanelComponent::send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) { | ||||||
|  |   JsonArray supported_features = root.createNestedArray(MQTT_SUPPORTED_FEATURES); | ||||||
|  |   const uint32_t acp_supported_features = this->alarm_control_panel_->get_supported_features(); | ||||||
|  |   if (acp_supported_features & ACP_FEAT_ARM_AWAY) { | ||||||
|  |     supported_features.add("arm_away"); | ||||||
|  |   } | ||||||
|  |   if (acp_supported_features & ACP_FEAT_ARM_HOME) { | ||||||
|  |     supported_features.add("arm_home"); | ||||||
|  |   } | ||||||
|  |   if (acp_supported_features & ACP_FEAT_ARM_NIGHT) { | ||||||
|  |     supported_features.add("arm_night"); | ||||||
|  |   } | ||||||
|  |   if (acp_supported_features & ACP_FEAT_ARM_VACATION) { | ||||||
|  |     supported_features.add("arm_vacation"); | ||||||
|  |   } | ||||||
|  |   if (acp_supported_features & ACP_FEAT_ARM_CUSTOM_BYPASS) { | ||||||
|  |     supported_features.add("arm_custom_bypass"); | ||||||
|  |   } | ||||||
|  |   if (acp_supported_features & ACP_FEAT_TRIGGER) { | ||||||
|  |     supported_features.add("trigger"); | ||||||
|  |   } | ||||||
|  |   root[MQTT_CODE_DISARM_REQUIRED] = this->alarm_control_panel_->get_requires_code(); | ||||||
|  |   root[MQTT_CODE_ARM_REQUIRED] = this->alarm_control_panel_->get_requires_code_to_arm(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | std::string MQTTAlarmControlPanelComponent::component_type() const { return "alarm_control_panel"; } | ||||||
|  | const EntityBase *MQTTAlarmControlPanelComponent::get_entity() const { return this->alarm_control_panel_; } | ||||||
|  |  | ||||||
|  | bool MQTTAlarmControlPanelComponent::send_initial_state() { return this->publish_state(); } | ||||||
|  | bool MQTTAlarmControlPanelComponent::publish_state() { | ||||||
|  |   bool success = true; | ||||||
|  |   const char *state_s = ""; | ||||||
|  |   switch (this->alarm_control_panel_->get_state()) { | ||||||
|  |     case ACP_STATE_DISARMED: | ||||||
|  |       state_s = "disarmed"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_ARMED_HOME: | ||||||
|  |       state_s = "armed_home"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_ARMED_AWAY: | ||||||
|  |       state_s = "armed_away"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_ARMED_NIGHT: | ||||||
|  |       state_s = "armed_night"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_ARMED_VACATION: | ||||||
|  |       state_s = "armed_vacation"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_ARMED_CUSTOM_BYPASS: | ||||||
|  |       state_s = "armed_custom_bypass"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_PENDING: | ||||||
|  |       state_s = "pending"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_ARMING: | ||||||
|  |       state_s = "arming"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_DISARMING: | ||||||
|  |       state_s = "disarming"; | ||||||
|  |       break; | ||||||
|  |     case ACP_STATE_TRIGGERED: | ||||||
|  |       state_s = "triggered"; | ||||||
|  |       break; | ||||||
|  |     default: | ||||||
|  |       state_s = "unknown"; | ||||||
|  |   } | ||||||
|  |   if (!this->publish(this->get_state_topic_(), state_s)) | ||||||
|  |     success = false; | ||||||
|  |   return success; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | }  // namespace mqtt | ||||||
|  | }  // namespace esphome | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  | #endif  // USE_MQTT | ||||||
							
								
								
									
										39
									
								
								esphome/components/mqtt/mqtt_alarm_control_panel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								esphome/components/mqtt/mqtt_alarm_control_panel.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "esphome/core/defines.h" | ||||||
|  |  | ||||||
|  | #ifdef USE_MQTT | ||||||
|  | #ifdef USE_ALARM_CONTROL_PANEL | ||||||
|  |  | ||||||
|  | #include "mqtt_component.h" | ||||||
|  | #include "esphome/components/alarm_control_panel/alarm_control_panel.h" | ||||||
|  |  | ||||||
|  | namespace esphome { | ||||||
|  | namespace mqtt { | ||||||
|  |  | ||||||
|  | class MQTTAlarmControlPanelComponent : public mqtt::MQTTComponent { | ||||||
|  |  public: | ||||||
|  |   explicit MQTTAlarmControlPanelComponent(alarm_control_panel::AlarmControlPanel *alarm_control_panel); | ||||||
|  |  | ||||||
|  |   void setup() override; | ||||||
|  |  | ||||||
|  |   void send_discovery(JsonObject root, mqtt::SendDiscoveryConfig &config) override; | ||||||
|  |  | ||||||
|  |   bool send_initial_state() override; | ||||||
|  |  | ||||||
|  |   bool publish_state(); | ||||||
|  |  | ||||||
|  |   void dump_config() override; | ||||||
|  |  | ||||||
|  |  protected: | ||||||
|  |   std::string component_type() const override; | ||||||
|  |   const EntityBase *get_entity() const override; | ||||||
|  |  | ||||||
|  |   alarm_control_panel::AlarmControlPanel *alarm_control_panel_; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | }  // namespace mqtt | ||||||
|  | }  // namespace esphome | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  | #endif  // USE_MQTT | ||||||
| @@ -426,3 +426,9 @@ valve: | |||||||
|       } else { |       } else { | ||||||
|         return VALVE_CLOSED; |         return VALVE_CLOSED; | ||||||
|       } |       } | ||||||
|  |  | ||||||
|  | alarm_control_panel: | ||||||
|  |   - platform: template | ||||||
|  |     name: Alarm Control Panel | ||||||
|  |     binary_sensors: | ||||||
|  |       - input: some_binary_sensor | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user