181 lines
5.8 KiB
Python
181 lines
5.8 KiB
Python
"""Module for SIA Binary Sensors."""
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterable
|
|
from dataclasses import dataclass
|
|
import logging
|
|
|
|
from pysiaalarm import SIAEvent
|
|
|
|
from homeassistant.components.binary_sensor import (
|
|
BinarySensorDeviceClass,
|
|
BinarySensorEntity,
|
|
BinarySensorEntityDescription,
|
|
)
|
|
from homeassistant.config_entries import ConfigEntry
|
|
from homeassistant.const import CONF_PORT, STATE_OFF, STATE_ON, STATE_UNAVAILABLE
|
|
from homeassistant.core import HomeAssistant, State
|
|
from homeassistant.helpers.entity import EntityCategory
|
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
|
|
|
from .const import (
|
|
CONF_ACCOUNT,
|
|
CONF_ACCOUNTS,
|
|
CONF_PING_INTERVAL,
|
|
CONF_ZONES,
|
|
KEY_MOISTURE,
|
|
KEY_POWER,
|
|
KEY_SMOKE,
|
|
SIA_HUB_ZONE,
|
|
SIA_NAME_FORMAT,
|
|
SIA_NAME_FORMAT_HUB,
|
|
SIA_UNIQUE_ID_FORMAT_BINARY,
|
|
)
|
|
from .sia_entity_base import SIABaseEntity, SIAEntityDescription
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
@dataclass
|
|
class SIABinarySensorEntityDescription(
|
|
BinarySensorEntityDescription,
|
|
SIAEntityDescription,
|
|
):
|
|
"""Describes SIA sensor entity."""
|
|
|
|
|
|
ENTITY_DESCRIPTION_POWER = SIABinarySensorEntityDescription(
|
|
key=KEY_POWER,
|
|
device_class=BinarySensorDeviceClass.POWER,
|
|
entity_category=EntityCategory.DIAGNOSTIC,
|
|
code_consequences={
|
|
"AT": False,
|
|
"AR": True,
|
|
},
|
|
)
|
|
|
|
ENTITY_DESCRIPTION_SMOKE = SIABinarySensorEntityDescription(
|
|
key=KEY_SMOKE,
|
|
device_class=BinarySensorDeviceClass.SMOKE,
|
|
code_consequences={
|
|
"GA": True,
|
|
"GH": False,
|
|
"FA": True,
|
|
"FH": False,
|
|
"KA": True,
|
|
"KH": False,
|
|
},
|
|
entity_registry_enabled_default=False,
|
|
)
|
|
|
|
ENTITY_DESCRIPTION_MOISTURE = SIABinarySensorEntityDescription(
|
|
key=KEY_MOISTURE,
|
|
device_class=BinarySensorDeviceClass.MOISTURE,
|
|
code_consequences={
|
|
"WA": True,
|
|
"WH": False,
|
|
},
|
|
entity_registry_enabled_default=False,
|
|
)
|
|
|
|
|
|
def generate_binary_sensors(entry) -> Iterable[SIABinarySensor]:
|
|
"""Generate binary sensors.
|
|
|
|
For each Account there is one power sensor with zone == 0.
|
|
For each Zone in each Account there is one smoke and one moisture sensor.
|
|
"""
|
|
for account_data in entry.data[CONF_ACCOUNTS]:
|
|
yield SIABinarySensor(
|
|
port=entry.data[CONF_PORT],
|
|
account=account_data[CONF_ACCOUNT],
|
|
zone=SIA_HUB_ZONE,
|
|
ping_interval=account_data[CONF_PING_INTERVAL],
|
|
entity_description=ENTITY_DESCRIPTION_POWER,
|
|
unique_id=SIA_UNIQUE_ID_FORMAT_BINARY.format(
|
|
entry.entry_id,
|
|
account_data[CONF_ACCOUNT],
|
|
SIA_HUB_ZONE,
|
|
ENTITY_DESCRIPTION_POWER.device_class,
|
|
),
|
|
name=SIA_NAME_FORMAT_HUB.format(
|
|
entry.data[CONF_PORT],
|
|
account_data[CONF_ACCOUNT],
|
|
ENTITY_DESCRIPTION_POWER.device_class,
|
|
),
|
|
)
|
|
zones = entry.options[CONF_ACCOUNTS][account_data[CONF_ACCOUNT]][CONF_ZONES]
|
|
for zone in range(1, zones + 1):
|
|
yield SIABinarySensor(
|
|
port=entry.data[CONF_PORT],
|
|
account=account_data[CONF_ACCOUNT],
|
|
zone=zone,
|
|
ping_interval=account_data[CONF_PING_INTERVAL],
|
|
entity_description=ENTITY_DESCRIPTION_SMOKE,
|
|
unique_id=SIA_UNIQUE_ID_FORMAT_BINARY.format(
|
|
entry.entry_id,
|
|
account_data[CONF_ACCOUNT],
|
|
zone,
|
|
ENTITY_DESCRIPTION_SMOKE.device_class,
|
|
),
|
|
name=SIA_NAME_FORMAT.format(
|
|
entry.data[CONF_PORT],
|
|
account_data[CONF_ACCOUNT],
|
|
zone,
|
|
ENTITY_DESCRIPTION_SMOKE.device_class,
|
|
),
|
|
)
|
|
yield SIABinarySensor(
|
|
port=entry.data[CONF_PORT],
|
|
account=account_data[CONF_ACCOUNT],
|
|
zone=zone,
|
|
ping_interval=account_data[CONF_PING_INTERVAL],
|
|
entity_description=ENTITY_DESCRIPTION_MOISTURE,
|
|
unique_id=SIA_UNIQUE_ID_FORMAT_BINARY.format(
|
|
entry.entry_id,
|
|
account_data[CONF_ACCOUNT],
|
|
zone,
|
|
ENTITY_DESCRIPTION_MOISTURE.device_class,
|
|
),
|
|
name=SIA_NAME_FORMAT.format(
|
|
entry.data[CONF_PORT],
|
|
account_data[CONF_ACCOUNT],
|
|
zone,
|
|
ENTITY_DESCRIPTION_MOISTURE.device_class,
|
|
),
|
|
)
|
|
|
|
|
|
async def async_setup_entry(
|
|
hass: HomeAssistant,
|
|
entry: ConfigEntry,
|
|
async_add_entities: AddEntitiesCallback,
|
|
) -> None:
|
|
"""Set up SIA binary sensors from a config entry."""
|
|
async_add_entities(generate_binary_sensors(entry))
|
|
|
|
|
|
class SIABinarySensor(SIABaseEntity, BinarySensorEntity):
|
|
"""Class for SIA Binary Sensors."""
|
|
|
|
entity_description: SIABinarySensorEntityDescription
|
|
|
|
def handle_last_state(self, last_state: State | None) -> None:
|
|
"""Handle the last state."""
|
|
if last_state is not None and last_state.state is not None:
|
|
if last_state.state == STATE_ON:
|
|
self._attr_is_on = True
|
|
elif last_state.state == STATE_OFF:
|
|
self._attr_is_on = False
|
|
elif last_state.state == STATE_UNAVAILABLE:
|
|
self._attr_available = False
|
|
|
|
def update_state(self, sia_event: SIAEvent) -> bool:
|
|
"""Update the state of the binary sensor."""
|
|
new_state = self.entity_description.code_consequences.get(sia_event.code)
|
|
if new_state is None:
|
|
return False
|
|
_LOGGER.debug("New state will be %s", new_state)
|
|
self._attr_is_on = bool(new_state)
|
|
return True
|