core/homeassistant/components/sia/binary_sensor.py

164 lines
5.0 KiB
Python

"""Module for SIA Binary Sensors."""
from __future__ import annotations
from collections.abc import Iterable
import logging
from typing import Any
from pysiaalarm import SIAEvent
from homeassistant.components.binary_sensor import (
BinarySensorDeviceClass,
BinarySensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant, State
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import (
CONF_ACCOUNT,
CONF_ACCOUNTS,
CONF_ZONES,
SIA_HUB_ZONE,
SIA_UNIQUE_ID_FORMAT_BINARY,
)
from .sia_entity_base import SIABaseEntity
_LOGGER = logging.getLogger(__name__)
POWER_CODE_CONSEQUENCES: dict[str, bool] = {
"AT": False,
"AR": True,
}
SMOKE_CODE_CONSEQUENCES: dict[str, bool] = {
"GA": True,
"GH": False,
"FA": True,
"FH": False,
"KA": True,
"KH": False,
}
MOISTURE_CODE_CONSEQUENCES: dict[str, bool] = {
"WA": True,
"WH": False,
}
def generate_binary_sensors(entry) -> Iterable[SIABinarySensorBase]:
"""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 in entry.data[CONF_ACCOUNTS]:
yield SIABinarySensorPower(entry, account)
zones = entry.options[CONF_ACCOUNTS][account[CONF_ACCOUNT]][CONF_ZONES]
for zone in range(1, zones + 1):
yield SIABinarySensorSmoke(entry, account, zone)
yield SIABinarySensorMoisture(entry, account, zone)
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 SIABinarySensorBase(SIABaseEntity, BinarySensorEntity):
"""Class for SIA Binary Sensors."""
def __init__(
self,
entry: ConfigEntry,
account_data: dict[str, Any],
zone: int,
device_class: BinarySensorDeviceClass,
) -> None:
"""Initialize a base binary sensor."""
super().__init__(entry, account_data, zone)
self._attr_device_class = device_class
self._attr_unique_id = SIA_UNIQUE_ID_FORMAT_BINARY.format(
self._entry.entry_id, self._account, self._zone, self._attr_device_class
)
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
class SIABinarySensorMoisture(SIABinarySensorBase):
"""Class for Moisture Binary Sensors."""
def __init__(
self,
entry: ConfigEntry,
account_data: dict[str, Any],
zone: int,
) -> None:
"""Initialize a Moisture binary sensor."""
super().__init__(entry, account_data, zone, BinarySensorDeviceClass.MOISTURE)
self._attr_entity_registry_enabled_default = False
def update_state(self, sia_event: SIAEvent) -> None:
"""Update the state of the binary sensor."""
new_state = MOISTURE_CODE_CONSEQUENCES.get(sia_event.code, None)
if new_state is not None:
_LOGGER.debug("New state will be %s", new_state)
self._attr_is_on = new_state
class SIABinarySensorSmoke(SIABinarySensorBase):
"""Class for Smoke Binary Sensors."""
def __init__(
self,
entry: ConfigEntry,
account_data: dict[str, Any],
zone: int,
) -> None:
"""Initialize a Smoke binary sensor."""
super().__init__(entry, account_data, zone, BinarySensorDeviceClass.SMOKE)
self._attr_entity_registry_enabled_default = False
def update_state(self, sia_event: SIAEvent) -> None:
"""Update the state of the binary sensor."""
new_state = SMOKE_CODE_CONSEQUENCES.get(sia_event.code, None)
if new_state is not None:
_LOGGER.debug("New state will be %s", new_state)
self._attr_is_on = new_state
class SIABinarySensorPower(SIABinarySensorBase):
"""Class for Power Binary Sensors."""
def __init__(
self,
entry: ConfigEntry,
account_data: dict[str, Any],
) -> None:
"""Initialize a Power binary sensor."""
super().__init__(
entry, account_data, SIA_HUB_ZONE, BinarySensorDeviceClass.POWER
)
self._attr_entity_registry_enabled_default = True
def update_state(self, sia_event: SIAEvent) -> None:
"""Update the state of the binary sensor."""
new_state = POWER_CODE_CONSEQUENCES.get(sia_event.code, None)
if new_state is not None:
_LOGGER.debug("New state will be %s", new_state)
self._attr_is_on = new_state