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.
This commit is contained in:
Raphaël Beamonte 2021-11-29 08:41:52 -05:00 committed by GitHub
parent 1f2a5ae98d
commit 8600b5597a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 1 deletions

View File

@ -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",

View File

@ -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]

View File

@ -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