From 8600b5597a22b4784bf1aa9091678628c0b7d0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Beamonte?= Date: Mon, 29 Nov 2021 08:41:52 -0500 Subject: [PATCH] Add 'trigger' support for MQTT Alarm Control Panel (#60525) When configuring an Alarm Control Panel through MQTT discovery, it was not possible to use the trigger service. This fixes that by making it available the same way as ARM and DISARM services are. --- homeassistant/components/mqtt/abbreviations.py | 2 ++ .../components/mqtt/alarm_control_panel.py | 18 ++++++++++++++++++ .../mqtt/test_alarm_control_panel.py | 9 ++++++++- 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/mqtt/abbreviations.py b/homeassistant/components/mqtt/abbreviations.py index 1daa6f837c7..9ad5ca4ce1c 100644 --- a/homeassistant/components/mqtt/abbreviations.py +++ b/homeassistant/components/mqtt/abbreviations.py @@ -39,6 +39,7 @@ ABBREVIATIONS = { "cmd_tpl": "command_template", "cod_arm_req": "code_arm_required", "cod_dis_req": "code_disarm_required", + "cod_trig_req": "code_trigger_required", "curr_temp_t": "current_temperature_topic", "curr_temp_tpl": "current_temperature_template", "dev": "device", @@ -147,6 +148,7 @@ ABBREVIATIONS = { "pl_ret": "payload_return_to_base", "pl_toff": "payload_turn_off", "pl_ton": "payload_turn_on", + "pl_trig": "payload_trigger", "pl_unlk": "payload_unlock", "pos_clsd": "position_closed", "pos_open": "position_open", diff --git a/homeassistant/components/mqtt/alarm_control_panel.py b/homeassistant/components/mqtt/alarm_control_panel.py index ffea92f14c3..3c324c0789b 100644 --- a/homeassistant/components/mqtt/alarm_control_panel.py +++ b/homeassistant/components/mqtt/alarm_control_panel.py @@ -12,6 +12,7 @@ from homeassistant.components.alarm_control_panel.const import ( SUPPORT_ALARM_ARM_HOME, SUPPORT_ALARM_ARM_NIGHT, SUPPORT_ALARM_ARM_VACATION, + SUPPORT_ALARM_TRIGGER, ) from homeassistant.const import ( CONF_CODE, @@ -43,12 +44,14 @@ _LOGGER = logging.getLogger(__name__) CONF_CODE_ARM_REQUIRED = "code_arm_required" CONF_CODE_DISARM_REQUIRED = "code_disarm_required" +CONF_CODE_TRIGGER_REQUIRED = "code_trigger_required" CONF_PAYLOAD_DISARM = "payload_disarm" CONF_PAYLOAD_ARM_HOME = "payload_arm_home" CONF_PAYLOAD_ARM_AWAY = "payload_arm_away" CONF_PAYLOAD_ARM_NIGHT = "payload_arm_night" CONF_PAYLOAD_ARM_VACATION = "payload_arm_vacation" CONF_PAYLOAD_ARM_CUSTOM_BYPASS = "payload_arm_custom_bypass" +CONF_PAYLOAD_TRIGGER = "payload_trigger" CONF_COMMAND_TEMPLATE = "command_template" MQTT_ALARM_ATTRIBUTES_BLOCKED = frozenset( @@ -66,6 +69,7 @@ DEFAULT_ARM_AWAY = "ARM_AWAY" DEFAULT_ARM_HOME = "ARM_HOME" DEFAULT_ARM_CUSTOM_BYPASS = "ARM_CUSTOM_BYPASS" DEFAULT_DISARM = "DISARM" +DEFAULT_TRIGGER = "TRIGGER" DEFAULT_NAME = "MQTT Alarm" REMOTE_CODE = "REMOTE_CODE" @@ -76,6 +80,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend( vol.Optional(CONF_CODE): cv.string, vol.Optional(CONF_CODE_ARM_REQUIRED, default=True): cv.boolean, vol.Optional(CONF_CODE_DISARM_REQUIRED, default=True): cv.boolean, + vol.Optional(CONF_CODE_TRIGGER_REQUIRED, default=True): cv.boolean, vol.Optional( CONF_COMMAND_TEMPLATE, default=DEFAULT_COMMAND_TEMPLATE ): cv.template, @@ -91,6 +96,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend( CONF_PAYLOAD_ARM_CUSTOM_BYPASS, default=DEFAULT_ARM_CUSTOM_BYPASS ): cv.string, vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string, + vol.Optional(CONF_PAYLOAD_TRIGGER, default=DEFAULT_TRIGGER): cv.string, vol.Optional(CONF_RETAIN, default=mqtt.DEFAULT_RETAIN): cv.boolean, vol.Required(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic, vol.Optional(CONF_VALUE_TEMPLATE): cv.template, @@ -203,6 +209,7 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity): | SUPPORT_ALARM_ARM_NIGHT | SUPPORT_ALARM_ARM_VACATION | SUPPORT_ALARM_ARM_CUSTOM_BYPASS + | SUPPORT_ALARM_TRIGGER ) @property @@ -286,6 +293,17 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity): action = self._config[CONF_PAYLOAD_ARM_CUSTOM_BYPASS] await self._publish(code, action) + async def async_alarm_trigger(self, code=None): + """Send trigger command. + + This method is a coroutine. + """ + code_required = self._config[CONF_CODE_TRIGGER_REQUIRED] + if code_required and not self._validate_code(code, "triggering"): + return + action = self._config[CONF_PAYLOAD_TRIGGER] + await self._publish(code, action) + async def _publish(self, code, action): """Publish via mqtt.""" command_template = self._config[CONF_COMMAND_TEMPLATE] diff --git a/tests/components/mqtt/test_alarm_control_panel.py b/tests/components/mqtt/test_alarm_control_panel.py index 1351ae59496..2a74a75c241 100644 --- a/tests/components/mqtt/test_alarm_control_panel.py +++ b/tests/components/mqtt/test_alarm_control_panel.py @@ -18,6 +18,7 @@ from homeassistant.const import ( SERVICE_ALARM_ARM_NIGHT, SERVICE_ALARM_ARM_VACATION, SERVICE_ALARM_DISARM, + SERVICE_ALARM_TRIGGER, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_CUSTOM_BYPASS, STATE_ALARM_ARMED_HOME, @@ -192,6 +193,7 @@ async def test_ignore_update_state_if_unknown_via_state_topic(hass, mqtt_mock): (SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (SERVICE_ALARM_DISARM, "DISARM"), + (SERVICE_ALARM_TRIGGER, "TRIGGER"), ], ) async def test_publish_mqtt_no_code(hass, mqtt_mock, service, payload): @@ -222,6 +224,7 @@ async def test_publish_mqtt_no_code(hass, mqtt_mock, service, payload): (SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (SERVICE_ALARM_DISARM, "DISARM"), + (SERVICE_ALARM_TRIGGER, "TRIGGER"), ], ) async def test_publish_mqtt_with_code(hass, mqtt_mock, service, payload): @@ -271,6 +274,7 @@ async def test_publish_mqtt_with_code(hass, mqtt_mock, service, payload): (SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (SERVICE_ALARM_DISARM, "DISARM"), + (SERVICE_ALARM_TRIGGER, "TRIGGER"), ], ) async def test_publish_mqtt_with_remote_code(hass, mqtt_mock, service, payload): @@ -311,6 +315,7 @@ async def test_publish_mqtt_with_remote_code(hass, mqtt_mock, service, payload): (SERVICE_ALARM_ARM_VACATION, "ARM_VACATION"), (SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS"), (SERVICE_ALARM_DISARM, "DISARM"), + (SERVICE_ALARM_TRIGGER, "TRIGGER"), ], ) async def test_publish_mqtt_with_remote_code_text(hass, mqtt_mock, service, payload): @@ -351,6 +356,7 @@ async def test_publish_mqtt_with_remote_code_text(hass, mqtt_mock, service, payl (SERVICE_ALARM_ARM_VACATION, "ARM_VACATION", "code_arm_required"), (SERVICE_ALARM_ARM_CUSTOM_BYPASS, "ARM_CUSTOM_BYPASS", "code_arm_required"), (SERVICE_ALARM_DISARM, "DISARM", "code_disarm_required"), + (SERVICE_ALARM_TRIGGER, "TRIGGER", "code_trigger_required"), ], ) async def test_publish_mqtt_with_code_required_false( @@ -358,7 +364,8 @@ async def test_publish_mqtt_with_code_required_false( ): """Test publishing of MQTT messages when code is configured. - code_arm_required = False / code_disarm_required = false + code_arm_required = False / code_disarm_required = False / + code_trigger_required = False """ config = copy.deepcopy(DEFAULT_CONFIG_CODE) config[alarm_control_panel.DOMAIN][disable_code] = False