mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 02:37:08 +00:00
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:
parent
671148b6ca
commit
b0fecdcc3d
@ -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]()
|
||||||
|
@ -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"
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user