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.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 ( | ||||
|     CONF_CODE, | ||||
|     CONF_ID, | ||||
|     CONF_MQTT_ID, | ||||
|     CONF_ON_STATE, | ||||
|     CONF_TRIGGER_ID, | ||||
|     CONF_CODE, | ||||
|     CONF_WEB_SERVER_ID, | ||||
| ) | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
| from esphome.cpp_helpers import setup_entity | ||||
|  | ||||
| CODEOWNERS = ["@grahambrown11", "@hwstar"] | ||||
| @@ -77,11 +78,15 @@ AlarmControlPanelCondition = alarm_control_panel_ns.class_( | ||||
|     "AlarmControlPanelCondition", automation.Condition | ||||
| ) | ||||
|  | ||||
| ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( | ||||
|     web_server.WEBSERVER_SORTING_SCHEMA | ||||
| ).extend( | ||||
| ALARM_CONTROL_PANEL_SCHEMA = ( | ||||
|     cv.ENTITY_BASE_SCHEMA.extend(web_server.WEBSERVER_SORTING_SCHEMA) | ||||
|     .extend(cv.MQTT_COMMAND_COMPONENT_SCHEMA) | ||||
|     .extend( | ||||
|         { | ||||
|             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.GenerateID(CONF_TRIGGER_ID): cv.declare_id(StateTrigger), | ||||
| @@ -139,6 +144,7 @@ ALARM_CONTROL_PANEL_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend( | ||||
|             ), | ||||
|         } | ||||
|     ) | ||||
| ) | ||||
|  | ||||
| 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: | ||||
|         web_server_ = await cg.get_variable(webserver_id) | ||||
|         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): | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| import re | ||||
|  | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import automation | ||||
| from esphome.automation import Condition | ||||
| import esphome.codegen as cg | ||||
| from esphome.components import logger | ||||
| from esphome.components.esp32 import add_idf_sdkconfig_option | ||||
| import esphome.config_validation as cv | ||||
| from esphome.const import ( | ||||
|     CONF_AVAILABILITY, | ||||
|     CONF_BIRTH_MESSAGE, | ||||
| @@ -13,21 +14,21 @@ from esphome.const import ( | ||||
|     CONF_CLIENT_CERTIFICATE, | ||||
|     CONF_CLIENT_CERTIFICATE_KEY, | ||||
|     CONF_CLIENT_ID, | ||||
|     CONF_COMMAND_TOPIC, | ||||
|     CONF_COMMAND_RETAIN, | ||||
|     CONF_COMMAND_TOPIC, | ||||
|     CONF_DISCOVERY, | ||||
|     CONF_DISCOVERY_OBJECT_ID_GENERATOR, | ||||
|     CONF_DISCOVERY_PREFIX, | ||||
|     CONF_DISCOVERY_RETAIN, | ||||
|     CONF_DISCOVERY_UNIQUE_ID_GENERATOR, | ||||
|     CONF_DISCOVERY_OBJECT_ID_GENERATOR, | ||||
|     CONF_ID, | ||||
|     CONF_KEEPALIVE, | ||||
|     CONF_LEVEL, | ||||
|     CONF_LOG_TOPIC, | ||||
|     CONF_ON_JSON_MESSAGE, | ||||
|     CONF_ON_MESSAGE, | ||||
|     CONF_ON_CONNECT, | ||||
|     CONF_ON_DISCONNECT, | ||||
|     CONF_ON_JSON_MESSAGE, | ||||
|     CONF_ON_MESSAGE, | ||||
|     CONF_PASSWORD, | ||||
|     CONF_PAYLOAD, | ||||
|     CONF_PAYLOAD_AVAILABLE, | ||||
| @@ -45,12 +46,11 @@ from esphome.const import ( | ||||
|     CONF_USE_ABBREVIATIONS, | ||||
|     CONF_USERNAME, | ||||
|     CONF_WILL_MESSAGE, | ||||
|     PLATFORM_BK72XX, | ||||
|     PLATFORM_ESP32, | ||||
|     PLATFORM_ESP8266, | ||||
|     PLATFORM_BK72XX, | ||||
| ) | ||||
| from esphome.core import coroutine_with_priority, CORE | ||||
| from esphome.components.esp32 import add_idf_sdkconfig_option | ||||
| from esphome.core import CORE, coroutine_with_priority | ||||
|  | ||||
| DEPENDENCIES = ["network"] | ||||
|  | ||||
| @@ -110,6 +110,9 @@ MQTTDisconnectTrigger = mqtt_ns.class_( | ||||
| MQTTComponent = mqtt_ns.class_("MQTTComponent", cg.Component) | ||||
| MQTTConnectedCondition = mqtt_ns.class_("MQTTConnectedCondition", Condition) | ||||
|  | ||||
| MQTTAlarmControlPanelComponent = mqtt_ns.class_( | ||||
|     "MQTTAlarmControlPanelComponent", MQTTComponent | ||||
| ) | ||||
| MQTTBinarySensorComponent = mqtt_ns.class_("MQTTBinarySensorComponent", MQTTComponent) | ||||
| MQTTClimateComponent = mqtt_ns.class_("MQTTClimateComponent", 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 { | ||||
|         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