2021-04-20 15:34:11 +00:00
|
|
|
"""Support for deCONZ alarm control panel devices."""
|
|
|
|
from __future__ import annotations
|
|
|
|
|
2022-04-24 08:17:46 +00:00
|
|
|
from pydeconz.models.alarm_system import AlarmSystem
|
2022-04-23 19:59:51 +00:00
|
|
|
from pydeconz.models.sensor.ancillary_control import (
|
2021-04-20 15:34:11 +00:00
|
|
|
ANCILLARY_CONTROL_ARMED_AWAY,
|
|
|
|
ANCILLARY_CONTROL_ARMED_NIGHT,
|
|
|
|
ANCILLARY_CONTROL_ARMED_STAY,
|
2021-08-23 18:56:45 +00:00
|
|
|
ANCILLARY_CONTROL_ARMING_AWAY,
|
|
|
|
ANCILLARY_CONTROL_ARMING_NIGHT,
|
|
|
|
ANCILLARY_CONTROL_ARMING_STAY,
|
2021-04-20 15:34:11 +00:00
|
|
|
ANCILLARY_CONTROL_DISARMED,
|
2021-08-23 18:56:45 +00:00
|
|
|
ANCILLARY_CONTROL_ENTRY_DELAY,
|
|
|
|
ANCILLARY_CONTROL_EXIT_DELAY,
|
|
|
|
ANCILLARY_CONTROL_IN_ALARM,
|
2021-04-20 15:34:11 +00:00
|
|
|
AncillaryControl,
|
|
|
|
)
|
|
|
|
|
|
|
|
from homeassistant.components.alarm_control_panel import (
|
|
|
|
DOMAIN,
|
|
|
|
AlarmControlPanelEntity,
|
2022-04-05 22:00:37 +00:00
|
|
|
AlarmControlPanelEntityFeature,
|
2022-04-18 17:37:32 +00:00
|
|
|
CodeFormat,
|
2021-04-20 15:34:11 +00:00
|
|
|
)
|
2021-11-16 19:01:10 +00:00
|
|
|
from homeassistant.config_entries import ConfigEntry
|
2021-04-20 15:34:11 +00:00
|
|
|
from homeassistant.const import (
|
|
|
|
STATE_ALARM_ARMED_AWAY,
|
|
|
|
STATE_ALARM_ARMED_HOME,
|
|
|
|
STATE_ALARM_ARMED_NIGHT,
|
2021-08-23 18:56:45 +00:00
|
|
|
STATE_ALARM_ARMING,
|
2021-04-20 15:34:11 +00:00
|
|
|
STATE_ALARM_DISARMED,
|
2021-08-23 18:56:45 +00:00
|
|
|
STATE_ALARM_PENDING,
|
|
|
|
STATE_ALARM_TRIGGERED,
|
2021-04-20 15:34:11 +00:00
|
|
|
)
|
2021-11-16 19:01:10 +00:00
|
|
|
from homeassistant.core import HomeAssistant, callback
|
2021-04-20 15:34:11 +00:00
|
|
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
2021-11-16 19:01:10 +00:00
|
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
2021-04-20 15:34:11 +00:00
|
|
|
|
|
|
|
from .deconz_device import DeconzDevice
|
2021-11-16 19:01:10 +00:00
|
|
|
from .gateway import DeconzGateway, get_gateway_from_config_entry
|
2021-04-20 15:34:11 +00:00
|
|
|
|
|
|
|
DECONZ_TO_ALARM_STATE = {
|
|
|
|
ANCILLARY_CONTROL_ARMED_AWAY: STATE_ALARM_ARMED_AWAY,
|
|
|
|
ANCILLARY_CONTROL_ARMED_NIGHT: STATE_ALARM_ARMED_NIGHT,
|
|
|
|
ANCILLARY_CONTROL_ARMED_STAY: STATE_ALARM_ARMED_HOME,
|
2021-08-23 18:56:45 +00:00
|
|
|
ANCILLARY_CONTROL_ARMING_AWAY: STATE_ALARM_ARMING,
|
|
|
|
ANCILLARY_CONTROL_ARMING_NIGHT: STATE_ALARM_ARMING,
|
|
|
|
ANCILLARY_CONTROL_ARMING_STAY: STATE_ALARM_ARMING,
|
2021-04-20 15:34:11 +00:00
|
|
|
ANCILLARY_CONTROL_DISARMED: STATE_ALARM_DISARMED,
|
2021-08-23 18:56:45 +00:00
|
|
|
ANCILLARY_CONTROL_ENTRY_DELAY: STATE_ALARM_PENDING,
|
|
|
|
ANCILLARY_CONTROL_EXIT_DELAY: STATE_ALARM_PENDING,
|
|
|
|
ANCILLARY_CONTROL_IN_ALARM: STATE_ALARM_TRIGGERED,
|
2021-04-20 15:34:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
def get_alarm_system_for_unique_id(
|
|
|
|
gateway: DeconzGateway, unique_id: str
|
|
|
|
) -> AlarmSystem | None:
|
2021-08-23 18:56:45 +00:00
|
|
|
"""Retrieve alarm system unique ID is registered to."""
|
2021-09-18 07:05:08 +00:00
|
|
|
for alarm_system in gateway.api.alarmsystems.values():
|
2021-08-23 18:56:45 +00:00
|
|
|
if unique_id in alarm_system.devices:
|
|
|
|
return alarm_system
|
2021-11-16 19:01:10 +00:00
|
|
|
return None
|
2021-08-23 18:56:45 +00:00
|
|
|
|
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
async def async_setup_entry(
|
|
|
|
hass: HomeAssistant,
|
|
|
|
config_entry: ConfigEntry,
|
|
|
|
async_add_entities: AddEntitiesCallback,
|
|
|
|
) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Set up the deCONZ alarm control panel devices.
|
|
|
|
|
|
|
|
Alarm control panels are based on the same device class as sensors in deCONZ.
|
|
|
|
"""
|
|
|
|
gateway = get_gateway_from_config_entry(hass, config_entry)
|
|
|
|
gateway.entities[DOMAIN] = set()
|
|
|
|
|
|
|
|
@callback
|
2021-11-16 19:01:10 +00:00
|
|
|
def async_add_alarm_control_panel(
|
2022-04-05 20:44:04 +00:00
|
|
|
sensors: list[AncillaryControl] | None = None,
|
2021-11-16 19:01:10 +00:00
|
|
|
) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Add alarm control panel devices from deCONZ."""
|
|
|
|
entities = []
|
|
|
|
|
2022-04-05 20:44:04 +00:00
|
|
|
if sensors is None:
|
|
|
|
sensors = list(gateway.api.sensors.ancillary_control.values())
|
|
|
|
|
2021-04-20 15:34:11 +00:00
|
|
|
for sensor in sensors:
|
|
|
|
|
|
|
|
if (
|
2021-09-29 19:19:21 +00:00
|
|
|
isinstance(sensor, AncillaryControl)
|
2021-09-18 07:05:08 +00:00
|
|
|
and sensor.unique_id not in gateway.entities[DOMAIN]
|
2021-11-16 19:01:10 +00:00
|
|
|
and (
|
|
|
|
alarm_system := get_alarm_system_for_unique_id(
|
|
|
|
gateway, sensor.unique_id
|
|
|
|
)
|
|
|
|
)
|
|
|
|
is not None
|
2021-04-20 15:34:11 +00:00
|
|
|
):
|
2021-08-23 18:56:45 +00:00
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
entities.append(DeconzAlarmControlPanel(sensor, gateway, alarm_system))
|
2021-04-20 15:34:11 +00:00
|
|
|
|
|
|
|
if entities:
|
|
|
|
async_add_entities(entities)
|
|
|
|
|
2021-04-20 18:20:57 +00:00
|
|
|
config_entry.async_on_unload(
|
2021-04-20 15:34:11 +00:00
|
|
|
async_dispatcher_connect(
|
|
|
|
hass,
|
2021-10-07 10:48:27 +00:00
|
|
|
gateway.signal_new_sensor,
|
2021-04-20 15:34:11 +00:00
|
|
|
async_add_alarm_control_panel,
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
async_add_alarm_control_panel()
|
|
|
|
|
|
|
|
|
|
|
|
class DeconzAlarmControlPanel(DeconzDevice, AlarmControlPanelEntity):
|
|
|
|
"""Representation of a deCONZ alarm control panel."""
|
|
|
|
|
|
|
|
TYPE = DOMAIN
|
2021-11-16 19:01:10 +00:00
|
|
|
_device: AncillaryControl
|
2021-04-20 15:34:11 +00:00
|
|
|
|
2022-04-18 17:37:32 +00:00
|
|
|
_attr_code_format = CodeFormat.NUMBER
|
2021-05-31 12:54:42 +00:00
|
|
|
_attr_supported_features = (
|
2022-04-05 22:00:37 +00:00
|
|
|
AlarmControlPanelEntityFeature.ARM_AWAY
|
|
|
|
| AlarmControlPanelEntityFeature.ARM_HOME
|
|
|
|
| AlarmControlPanelEntityFeature.ARM_NIGHT
|
2021-05-31 12:54:42 +00:00
|
|
|
)
|
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
device: AncillaryControl,
|
|
|
|
gateway: DeconzGateway,
|
|
|
|
alarm_system: AlarmSystem,
|
|
|
|
) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Set up alarm control panel device."""
|
|
|
|
super().__init__(device, gateway)
|
2021-11-16 19:01:10 +00:00
|
|
|
self.alarm_system = alarm_system
|
2021-04-24 13:46:16 +00:00
|
|
|
|
2021-04-20 15:34:11 +00:00
|
|
|
@callback
|
2021-10-20 12:59:36 +00:00
|
|
|
def async_update_callback(self) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Update the control panels state."""
|
2021-08-23 18:56:45 +00:00
|
|
|
keys = {"panel", "reachable"}
|
2021-10-20 12:59:36 +00:00
|
|
|
if (
|
2021-04-20 15:34:11 +00:00
|
|
|
self._device.changed_keys.intersection(keys)
|
2022-04-05 20:44:04 +00:00
|
|
|
and self._device.panel in DECONZ_TO_ALARM_STATE
|
2021-04-20 15:34:11 +00:00
|
|
|
):
|
2021-10-20 12:59:36 +00:00
|
|
|
super().async_update_callback()
|
2021-04-20 15:34:11 +00:00
|
|
|
|
|
|
|
@property
|
2021-05-31 12:54:42 +00:00
|
|
|
def state(self) -> str | None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Return the state of the control panel."""
|
2022-04-11 14:19:54 +00:00
|
|
|
if self._device.panel in DECONZ_TO_ALARM_STATE:
|
|
|
|
return DECONZ_TO_ALARM_STATE[self._device.panel]
|
|
|
|
return None
|
2021-04-20 15:34:11 +00:00
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
async def async_alarm_arm_away(self, code: str | None = None) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Send arm away command."""
|
2022-04-11 14:19:54 +00:00
|
|
|
if code:
|
|
|
|
await self.alarm_system.arm_away(code)
|
2021-04-20 15:34:11 +00:00
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
async def async_alarm_arm_home(self, code: str | None = None) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Send arm home command."""
|
2022-04-11 14:19:54 +00:00
|
|
|
if code:
|
|
|
|
await self.alarm_system.arm_stay(code)
|
2021-04-20 15:34:11 +00:00
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
async def async_alarm_arm_night(self, code: str | None = None) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Send arm night command."""
|
2022-04-11 14:19:54 +00:00
|
|
|
if code:
|
|
|
|
await self.alarm_system.arm_night(code)
|
2021-04-20 15:34:11 +00:00
|
|
|
|
2021-11-16 19:01:10 +00:00
|
|
|
async def async_alarm_disarm(self, code: str | None = None) -> None:
|
2021-04-20 15:34:11 +00:00
|
|
|
"""Send disarm command."""
|
2022-04-11 14:19:54 +00:00
|
|
|
if code:
|
|
|
|
await self.alarm_system.disarm(code)
|