Implementation of new Vacation mode for MQTT-based alarm panels (#53561)
* Impelentation of new Vacation Mode for MQTT-based alarm panels * Fixed typo * another typo fix * Split integrations: remove manual_mqtt * added newline * Impelentation of new Vacation Mode for MQTT-based alarm panels * Fixed typo * another typo fix * Split integrations: remove manual_mqtt * added newline * missing abbreviation * Fix tests Co-authored-by: Erik Montnemery <erik@montnemery.com>pull/55145/head
parent
a5e498207d
commit
547ede1e91
|
@ -113,6 +113,7 @@ ABBREVIATIONS = {
|
|||
"pl_arm_away": "payload_arm_away",
|
||||
"pl_arm_home": "payload_arm_home",
|
||||
"pl_arm_nite": "payload_arm_night",
|
||||
"pl_arm_vacation": "payload_arm_vacation",
|
||||
"pl_arm_custom_b": "payload_arm_custom_bypass",
|
||||
"pl_avail": "payload_available",
|
||||
"pl_cln_sp": "payload_clean_spot",
|
||||
|
|
|
@ -11,6 +11,7 @@ from homeassistant.components.alarm_control_panel.const import (
|
|||
SUPPORT_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SUPPORT_ALARM_ARM_HOME,
|
||||
SUPPORT_ALARM_ARM_NIGHT,
|
||||
SUPPORT_ALARM_ARM_VACATION,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_CODE,
|
||||
|
@ -20,6 +21,7 @@ from homeassistant.const import (
|
|||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_ARMING,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_DISARMING,
|
||||
|
@ -52,6 +54,7 @@ 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_COMMAND_TEMPLATE = "command_template"
|
||||
|
||||
|
@ -65,6 +68,7 @@ MQTT_ALARM_ATTRIBUTES_BLOCKED = frozenset(
|
|||
|
||||
DEFAULT_COMMAND_TEMPLATE = "{{action}}"
|
||||
DEFAULT_ARM_NIGHT = "ARM_NIGHT"
|
||||
DEFAULT_ARM_VACATION = "ARM_VACATION"
|
||||
DEFAULT_ARM_AWAY = "ARM_AWAY"
|
||||
DEFAULT_ARM_HOME = "ARM_HOME"
|
||||
DEFAULT_ARM_CUSTOM_BYPASS = "ARM_CUSTOM_BYPASS"
|
||||
|
@ -83,6 +87,9 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend(
|
|||
vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string,
|
||||
vol.Optional(CONF_PAYLOAD_ARM_NIGHT, default=DEFAULT_ARM_NIGHT): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_VACATION, default=DEFAULT_ARM_VACATION
|
||||
): cv.string,
|
||||
vol.Optional(
|
||||
CONF_PAYLOAD_ARM_CUSTOM_BYPASS, default=DEFAULT_ARM_CUSTOM_BYPASS
|
||||
): cv.string,
|
||||
|
@ -158,6 +165,7 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
|||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_PENDING,
|
||||
STATE_ALARM_ARMING,
|
||||
|
@ -193,6 +201,7 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
|||
SUPPORT_ALARM_ARM_HOME
|
||||
| SUPPORT_ALARM_ARM_AWAY
|
||||
| SUPPORT_ALARM_ARM_NIGHT
|
||||
| SUPPORT_ALARM_ARM_VACATION
|
||||
| SUPPORT_ALARM_ARM_CUSTOM_BYPASS
|
||||
)
|
||||
|
||||
|
@ -256,6 +265,17 @@ class MqttAlarm(MqttEntity, alarm.AlarmControlPanelEntity):
|
|||
action = self._config[CONF_PAYLOAD_ARM_NIGHT]
|
||||
self._publish(code, action)
|
||||
|
||||
async def async_alarm_arm_vacation(self, code=None):
|
||||
"""Send arm vacation command.
|
||||
|
||||
This method is a coroutine.
|
||||
"""
|
||||
code_required = self._config[CONF_CODE_ARM_REQUIRED]
|
||||
if code_required and not self._validate_code(code, "arming vacation"):
|
||||
return
|
||||
action = self._config[CONF_PAYLOAD_ARM_VACATION]
|
||||
self._publish(code, action)
|
||||
|
||||
async def async_alarm_arm_custom_bypass(self, code=None):
|
||||
"""Send arm custom bypass command.
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ from homeassistant.const import (
|
|||
SERVICE_ALARM_ARM_CUSTOM_BYPASS,
|
||||
SERVICE_ALARM_ARM_HOME,
|
||||
SERVICE_ALARM_ARM_NIGHT,
|
||||
SERVICE_ALARM_ARM_VACATION,
|
||||
SERVICE_ALARM_DISARM,
|
||||
SERVICE_ALARM_TRIGGER,
|
||||
)
|
||||
|
@ -61,6 +62,19 @@ async def async_alarm_arm_night(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
|||
await hass.services.async_call(DOMAIN, SERVICE_ALARM_ARM_NIGHT, data, blocking=True)
|
||||
|
||||
|
||||
async def async_alarm_arm_vacation(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for vacation mode."""
|
||||
data = {}
|
||||
if code:
|
||||
data[ATTR_CODE] = code
|
||||
if entity_id:
|
||||
data[ATTR_ENTITY_ID] = entity_id
|
||||
|
||||
await hass.services.async_call(
|
||||
DOMAIN, SERVICE_ALARM_ARM_VACATION, data, blocking=True
|
||||
)
|
||||
|
||||
|
||||
async def async_alarm_trigger(hass, code=None, entity_id=ENTITY_MATCH_ALL):
|
||||
"""Send the alarm the command for disarm."""
|
||||
data = {}
|
||||
|
|
|
@ -14,6 +14,7 @@ from homeassistant.const import (
|
|||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_ARMING,
|
||||
STATE_ALARM_DISARMED,
|
||||
STATE_ALARM_DISARMING,
|
||||
|
@ -124,6 +125,7 @@ async def test_update_state_via_state_topic(hass, mqtt_mock):
|
|||
STATE_ALARM_ARMED_HOME,
|
||||
STATE_ALARM_ARMED_AWAY,
|
||||
STATE_ALARM_ARMED_NIGHT,
|
||||
STATE_ALARM_ARMED_VACATION,
|
||||
STATE_ALARM_ARMED_CUSTOM_BYPASS,
|
||||
STATE_ALARM_PENDING,
|
||||
STATE_ALARM_ARMING,
|
||||
|
@ -176,6 +178,7 @@ async def test_arm_home_not_publishes_mqtt_with_invalid_code_when_req(hass, mqtt
|
|||
alarm_control_panel.DOMAIN,
|
||||
DEFAULT_CONFIG_CODE,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
call_count = mqtt_mock.async_publish.call_count
|
||||
await common.async_alarm_arm_home(hass, "abcd")
|
||||
|
@ -227,6 +230,7 @@ async def test_arm_away_not_publishes_mqtt_with_invalid_code_when_req(hass, mqtt
|
|||
alarm_control_panel.DOMAIN,
|
||||
DEFAULT_CONFIG_CODE,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
call_count = mqtt_mock.async_publish.call_count
|
||||
await common.async_alarm_arm_away(hass, "abcd")
|
||||
|
@ -278,6 +282,7 @@ async def test_arm_night_not_publishes_mqtt_with_invalid_code_when_req(hass, mqt
|
|||
alarm_control_panel.DOMAIN,
|
||||
DEFAULT_CONFIG_CODE,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
call_count = mqtt_mock.async_publish.call_count
|
||||
await common.async_alarm_arm_night(hass, "abcd")
|
||||
|
@ -304,6 +309,60 @@ async def test_arm_night_publishes_mqtt_when_code_not_req(hass, mqtt_mock):
|
|||
)
|
||||
|
||||
|
||||
async def test_arm_vacation_publishes_mqtt(hass, mqtt_mock):
|
||||
"""Test publishing of MQTT messages while armed."""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
alarm_control_panel.DOMAIN,
|
||||
DEFAULT_CONFIG,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await common.async_alarm_arm_vacation(hass)
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
"alarm/command", "ARM_VACATION", 0, False
|
||||
)
|
||||
|
||||
|
||||
async def test_arm_vacation_not_publishes_mqtt_with_invalid_code_when_req(
|
||||
hass, mqtt_mock
|
||||
):
|
||||
"""Test not publishing of MQTT messages with invalid code.
|
||||
|
||||
When code_arm_required = True
|
||||
"""
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
alarm_control_panel.DOMAIN,
|
||||
DEFAULT_CONFIG_CODE,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
call_count = mqtt_mock.async_publish.call_count
|
||||
await common.async_alarm_arm_vacation(hass, "abcd")
|
||||
assert mqtt_mock.async_publish.call_count == call_count
|
||||
|
||||
|
||||
async def test_arm_vacation_publishes_mqtt_when_code_not_req(hass, mqtt_mock):
|
||||
"""Test publishing of MQTT messages.
|
||||
|
||||
When code_arm_required = False
|
||||
"""
|
||||
config = copy.deepcopy(DEFAULT_CONFIG_CODE)
|
||||
config[alarm_control_panel.DOMAIN]["code_arm_required"] = False
|
||||
assert await async_setup_component(
|
||||
hass,
|
||||
alarm_control_panel.DOMAIN,
|
||||
config,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
await common.async_alarm_arm_vacation(hass)
|
||||
mqtt_mock.async_publish.assert_called_once_with(
|
||||
"alarm/command", "ARM_VACATION", 0, False
|
||||
)
|
||||
|
||||
|
||||
async def test_arm_custom_bypass_publishes_mqtt(hass, mqtt_mock):
|
||||
"""Test publishing of MQTT messages while armed."""
|
||||
assert await async_setup_component(
|
||||
|
@ -446,6 +505,7 @@ async def test_disarm_not_publishes_mqtt_with_invalid_code_when_req(hass, mqtt_m
|
|||
alarm_control_panel.DOMAIN,
|
||||
DEFAULT_CONFIG_CODE,
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
call_count = mqtt_mock.async_publish.call_count
|
||||
await common.async_alarm_disarm(hass, "abcd")
|
||||
|
|
Loading…
Reference in New Issue