Add entity service for deCONZ alarm control panel to control states used to help guide user transition between primary states (#49606)

This commit is contained in:
Robert Svensson 2021-04-24 15:46:16 +02:00 committed by GitHub
parent 671148b6ca
commit b0fecdcc3d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 169 additions and 0 deletions

View File

@ -8,6 +8,7 @@ from pydeconz.sensor import (
ANCILLARY_CONTROL_DISARMED, ANCILLARY_CONTROL_DISARMED,
AncillaryControl, AncillaryControl,
) )
import voluptuous as vol
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
DOMAIN, DOMAIN,
@ -24,12 +25,35 @@ from homeassistant.const import (
STATE_UNKNOWN, STATE_UNKNOWN,
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import entity_platform
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .const import NEW_SENSOR from .const import NEW_SENSOR
from .deconz_device import DeconzDevice from .deconz_device import DeconzDevice
from .gateway import get_gateway_from_config_entry from .gateway import get_gateway_from_config_entry
PANEL_ARMING_AWAY = "arming_away"
PANEL_ARMING_HOME = "arming_home"
PANEL_ARMING_NIGHT = "arming_night"
PANEL_ENTRY_DELAY = "entry_delay"
PANEL_EXIT_DELAY = "exit_delay"
PANEL_NOT_READY_TO_ARM = "not_ready_to_arm"
SERVICE_ALARM_PANEL_STATE = "alarm_panel_state"
CONF_ALARM_PANEL_STATE = "panel_state"
SERVICE_ALARM_PANEL_STATE_SCHEMA = {
vol.Required(CONF_ALARM_PANEL_STATE): vol.In(
[
PANEL_ARMING_AWAY,
PANEL_ARMING_HOME,
PANEL_ARMING_NIGHT,
PANEL_ENTRY_DELAY,
PANEL_EXIT_DELAY,
PANEL_NOT_READY_TO_ARM,
]
)
}
DECONZ_TO_ALARM_STATE = { DECONZ_TO_ALARM_STATE = {
ANCILLARY_CONTROL_ARMED_AWAY: STATE_ALARM_ARMED_AWAY, ANCILLARY_CONTROL_ARMED_AWAY: STATE_ALARM_ARMED_AWAY,
ANCILLARY_CONTROL_ARMED_NIGHT: STATE_ALARM_ARMED_NIGHT, ANCILLARY_CONTROL_ARMED_NIGHT: STATE_ALARM_ARMED_NIGHT,
@ -46,6 +70,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities) -> None:
gateway = get_gateway_from_config_entry(hass, config_entry) gateway = get_gateway_from_config_entry(hass, config_entry)
gateway.entities[DOMAIN] = set() gateway.entities[DOMAIN] = set()
platform = entity_platform.current_platform.get()
@callback @callback
def async_add_alarm_control_panel(sensors=gateway.api.sensors.values()) -> None: def async_add_alarm_control_panel(sensors=gateway.api.sensors.values()) -> None:
"""Add alarm control panel devices from deCONZ.""" """Add alarm control panel devices from deCONZ."""
@ -60,6 +86,11 @@ async def async_setup_entry(hass, config_entry, async_add_entities) -> None:
entities.append(DeconzAlarmControlPanel(sensor, gateway)) entities.append(DeconzAlarmControlPanel(sensor, gateway))
if entities: if entities:
platform.async_register_entity_service(
SERVICE_ALARM_PANEL_STATE,
SERVICE_ALARM_PANEL_STATE_SCHEMA,
"async_set_panel_state",
)
async_add_entities(entities) async_add_entities(entities)
config_entry.async_on_unload( config_entry.async_on_unload(
@ -86,6 +117,15 @@ class DeconzAlarmControlPanel(DeconzDevice, AlarmControlPanelEntity):
self._features |= SUPPORT_ALARM_ARM_HOME self._features |= SUPPORT_ALARM_ARM_HOME
self._features |= SUPPORT_ALARM_ARM_NIGHT self._features |= SUPPORT_ALARM_ARM_NIGHT
self._service_to_device_panel_command = {
PANEL_ARMING_AWAY: self._device.arming_away,
PANEL_ARMING_HOME: self._device.arming_stay,
PANEL_ARMING_NIGHT: self._device.arming_night,
PANEL_ENTRY_DELAY: self._device.entry_delay,
PANEL_EXIT_DELAY: self._device.exit_delay,
PANEL_NOT_READY_TO_ARM: self._device.not_ready_to_arm,
}
@property @property
def supported_features(self) -> int: def supported_features(self) -> int:
"""Return the list of supported features.""" """Return the list of supported features."""
@ -131,3 +171,7 @@ class DeconzAlarmControlPanel(DeconzDevice, AlarmControlPanelEntity):
async def async_alarm_disarm(self, code: None = None) -> None: async def async_alarm_disarm(self, code: None = None) -> None:
"""Send disarm command.""" """Send disarm command."""
await self._device.disarm() await self._device.disarm()
async def async_set_panel_state(self, panel_state: str) -> None:
"""Send panel_state command."""
await self._service_to_device_panel_command[panel_state]()

View File

@ -64,3 +64,29 @@ remove_orphaned_entries:
It can be found as part of the integration name. It can be found as part of the integration name.
Useful if you run multiple deCONZ integrations. Useful if you run multiple deCONZ integrations.
example: "00212EFFFF012345" example: "00212EFFFF012345"
alarm_panel_state:
name: Alarm panel state
description: Put keypad panel in an intermediate state, to help with visual and audible cues to the user.
target:
entity:
integration: deconz
domain: alarm_control_panel
fields:
panel_state:
name: Panel state
description: >-
- "arming_away/home/night": set panel in right visual arming state.
- "entry_delay": make panel beep until panel is disarmed. Beep interval is short.
- "exit_delay": make panel beep until panel is set to armed state. Beep interval is long.
- "not_ready_to_arm": turn on yellow status led on the panel. Indicate not all conditions for arming are met.
required: true
selector:
select:
options:
- "arming_away"
- "arming_home"
- "arming_night"
- "entry_delay"
- "exit_delay"
- "not_ready_to_arm"

View File

@ -6,12 +6,29 @@ from pydeconz.sensor import (
ANCILLARY_CONTROL_ARMED_AWAY, ANCILLARY_CONTROL_ARMED_AWAY,
ANCILLARY_CONTROL_ARMED_NIGHT, ANCILLARY_CONTROL_ARMED_NIGHT,
ANCILLARY_CONTROL_ARMED_STAY, ANCILLARY_CONTROL_ARMED_STAY,
ANCILLARY_CONTROL_ARMING_AWAY,
ANCILLARY_CONTROL_ARMING_NIGHT,
ANCILLARY_CONTROL_ARMING_STAY,
ANCILLARY_CONTROL_DISARMED, ANCILLARY_CONTROL_DISARMED,
ANCILLARY_CONTROL_ENTRY_DELAY,
ANCILLARY_CONTROL_EXIT_DELAY,
ANCILLARY_CONTROL_NOT_READY_TO_ARM,
) )
from homeassistant.components.alarm_control_panel import ( from homeassistant.components.alarm_control_panel import (
DOMAIN as ALARM_CONTROL_PANEL_DOMAIN, DOMAIN as ALARM_CONTROL_PANEL_DOMAIN,
) )
from homeassistant.components.deconz.alarm_control_panel import (
CONF_ALARM_PANEL_STATE,
PANEL_ARMING_AWAY,
PANEL_ARMING_HOME,
PANEL_ARMING_NIGHT,
PANEL_ENTRY_DELAY,
PANEL_EXIT_DELAY,
PANEL_NOT_READY_TO_ARM,
SERVICE_ALARM_PANEL_STATE,
)
from homeassistant.components.deconz.const import DOMAIN as DECONZ_DOMAIN
from homeassistant.const import ( from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_ENTITY_ID,
SERVICE_ALARM_ARM_AWAY, SERVICE_ALARM_ARM_AWAY,
@ -204,6 +221,88 @@ async def test_alarm_control_panel(hass, aioclient_mock, mock_deconz_websocket):
"panel": ANCILLARY_CONTROL_DISARMED, "panel": ANCILLARY_CONTROL_DISARMED,
} }
# Verify entity service calls
# Service set panel to arming away
await hass.services.async_call(
DECONZ_DOMAIN,
SERVICE_ALARM_PANEL_STATE,
{
ATTR_ENTITY_ID: "alarm_control_panel.keypad",
CONF_ALARM_PANEL_STATE: PANEL_ARMING_AWAY,
},
blocking=True,
)
assert aioclient_mock.mock_calls[5][2] == {"panel": ANCILLARY_CONTROL_ARMING_AWAY}
# Service set panel to arming home
await hass.services.async_call(
DECONZ_DOMAIN,
SERVICE_ALARM_PANEL_STATE,
{
ATTR_ENTITY_ID: "alarm_control_panel.keypad",
CONF_ALARM_PANEL_STATE: PANEL_ARMING_HOME,
},
blocking=True,
)
assert aioclient_mock.mock_calls[6][2] == {"panel": ANCILLARY_CONTROL_ARMING_STAY}
# Service set panel to arming night
await hass.services.async_call(
DECONZ_DOMAIN,
SERVICE_ALARM_PANEL_STATE,
{
ATTR_ENTITY_ID: "alarm_control_panel.keypad",
CONF_ALARM_PANEL_STATE: PANEL_ARMING_NIGHT,
},
blocking=True,
)
assert aioclient_mock.mock_calls[7][2] == {"panel": ANCILLARY_CONTROL_ARMING_NIGHT}
# Service set panel to entry delay
await hass.services.async_call(
DECONZ_DOMAIN,
SERVICE_ALARM_PANEL_STATE,
{
ATTR_ENTITY_ID: "alarm_control_panel.keypad",
CONF_ALARM_PANEL_STATE: PANEL_ENTRY_DELAY,
},
blocking=True,
)
assert aioclient_mock.mock_calls[8][2] == {"panel": ANCILLARY_CONTROL_ENTRY_DELAY}
# Service set panel to exit delay
await hass.services.async_call(
DECONZ_DOMAIN,
SERVICE_ALARM_PANEL_STATE,
{
ATTR_ENTITY_ID: "alarm_control_panel.keypad",
CONF_ALARM_PANEL_STATE: PANEL_EXIT_DELAY,
},
blocking=True,
)
assert aioclient_mock.mock_calls[9][2] == {"panel": ANCILLARY_CONTROL_EXIT_DELAY}
# Service set panel to not ready to arm
await hass.services.async_call(
DECONZ_DOMAIN,
SERVICE_ALARM_PANEL_STATE,
{
ATTR_ENTITY_ID: "alarm_control_panel.keypad",
CONF_ALARM_PANEL_STATE: PANEL_NOT_READY_TO_ARM,
},
blocking=True,
)
assert aioclient_mock.mock_calls[10][2] == {
"panel": ANCILLARY_CONTROL_NOT_READY_TO_ARM
}
await hass.config_entries.async_unload(config_entry.entry_id) await hass.config_entries.async_unload(config_entry.entry_id)
states = hass.states.async_all() states = hass.states.async_all()