core/homeassistant/components/risco/binary_sensor.py

226 lines
7.2 KiB
Python

"""Support for Risco alarm zones."""
from __future__ import annotations
from collections.abc import Mapping
from itertools import chain
from typing import Any
from pyrisco.cloud.zone import Zone as CloudZone
from pyrisco.common import System
from pyrisco.local.zone import Zone as LocalZone
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from . import LocalData, is_local
from .const import DATA_COORDINATOR, DOMAIN, SYSTEM_UPDATE_SIGNAL
from .coordinator import RiscoDataUpdateCoordinator
from .entity import RiscoCloudZoneEntity, RiscoLocalZoneEntity
SYSTEM_ENTITY_DESCRIPTIONS = [
BinarySensorEntityDescription(
key="low_battery_trouble",
translation_key="low_battery_trouble",
device_class=BinarySensorDeviceClass.BATTERY,
),
BinarySensorEntityDescription(
key="ac_trouble",
translation_key="ac_trouble",
device_class=BinarySensorDeviceClass.PROBLEM,
),
BinarySensorEntityDescription(
key="monitoring_station_1_trouble",
translation_key="monitoring_station_1_trouble",
device_class=BinarySensorDeviceClass.PROBLEM,
),
BinarySensorEntityDescription(
key="monitoring_station_2_trouble",
translation_key="monitoring_station_2_trouble",
device_class=BinarySensorDeviceClass.PROBLEM,
),
BinarySensorEntityDescription(
key="monitoring_station_3_trouble",
translation_key="monitoring_station_3_trouble",
device_class=BinarySensorDeviceClass.PROBLEM,
),
BinarySensorEntityDescription(
key="phone_line_trouble",
translation_key="phone_line_trouble",
device_class=BinarySensorDeviceClass.PROBLEM,
),
BinarySensorEntityDescription(
key="clock_trouble",
translation_key="clock_trouble",
device_class=BinarySensorDeviceClass.PROBLEM,
),
BinarySensorEntityDescription(
key="box_tamper",
translation_key="box_tamper",
device_class=BinarySensorDeviceClass.TAMPER,
),
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the Risco alarm control panel."""
if is_local(config_entry):
local_data: LocalData = hass.data[DOMAIN][config_entry.entry_id]
zone_entities = (
entity
for zone_id, zone in local_data.system.zones.items()
for entity in (
RiscoLocalBinarySensor(local_data.system.id, zone_id, zone),
RiscoLocalAlarmedBinarySensor(local_data.system.id, zone_id, zone),
RiscoLocalArmedBinarySensor(local_data.system.id, zone_id, zone),
)
)
system_entities = (
RiscoSystemBinarySensor(
local_data.system.id, local_data.system.system, entity_description
)
for entity_description in SYSTEM_ENTITY_DESCRIPTIONS
)
async_add_entities(chain(system_entities, zone_entities))
else:
coordinator: RiscoDataUpdateCoordinator = hass.data[DOMAIN][
config_entry.entry_id
][DATA_COORDINATOR]
async_add_entities(
RiscoCloudBinarySensor(coordinator, zone_id, zone)
for zone_id, zone in coordinator.data.zones.items()
)
class RiscoCloudBinarySensor(RiscoCloudZoneEntity, BinarySensorEntity):
"""Representation of a Risco cloud zone as a binary sensor."""
_attr_device_class = BinarySensorDeviceClass.MOTION
_attr_name = None
def __init__(
self, coordinator: RiscoDataUpdateCoordinator, zone_id: int, zone: CloudZone
) -> None:
"""Init the zone."""
super().__init__(coordinator=coordinator, suffix="", zone_id=zone_id, zone=zone)
@property
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return self._zone.triggered
class RiscoLocalBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
"""Representation of a Risco local zone as a binary sensor."""
_attr_device_class = BinarySensorDeviceClass.MOTION
_attr_name = None
def __init__(self, system_id: str, zone_id: int, zone: LocalZone) -> None:
"""Init the zone."""
super().__init__(system_id=system_id, suffix="", zone_id=zone_id, zone=zone)
@property
def extra_state_attributes(self) -> Mapping[str, Any] | None:
"""Return the state attributes."""
return {
**(super().extra_state_attributes or {}),
"groups": self._zone.groups,
}
@property
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return self._zone.triggered
class RiscoLocalAlarmedBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
"""Representation whether a zone in Risco local is currently triggering an alarm."""
_attr_translation_key = "alarmed"
def __init__(self, system_id: str, zone_id: int, zone: LocalZone) -> None:
"""Init the zone."""
super().__init__(
system_id=system_id,
suffix="_alarmed",
zone_id=zone_id,
zone=zone,
)
@property
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return self._zone.alarmed
class RiscoLocalArmedBinarySensor(RiscoLocalZoneEntity, BinarySensorEntity):
"""Representation whether a zone in Risco local is currently armed."""
_attr_translation_key = "armed"
def __init__(self, system_id: str, zone_id: int, zone: LocalZone) -> None:
"""Init the zone."""
super().__init__(
system_id=system_id,
suffix="_armed",
zone_id=zone_id,
zone=zone,
)
@property
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return self._zone.armed
class RiscoSystemBinarySensor(BinarySensorEntity):
"""Risco local system binary sensor class."""
_attr_should_poll = False
_attr_has_entity_name = True
def __init__(
self,
system_id: str,
system: System,
entity_description: BinarySensorEntityDescription,
) -> None:
"""Init the sensor."""
self._system = system
self._property = entity_description.key
self._attr_unique_id = f"{system_id}_{self._property}"
self._attr_device_info = DeviceInfo(
identifiers={(DOMAIN, system_id)},
manufacturer="Risco",
name=system.name,
)
self.entity_description = entity_description
async def async_added_to_hass(self) -> None:
"""Subscribe to updates."""
self.async_on_remove(
async_dispatcher_connect(
self.hass, SYSTEM_UPDATE_SIGNAL, self.async_write_ha_state
)
)
@property
def is_on(self) -> bool | None:
"""Return true if sensor is on."""
return getattr(self._system, self._property)