Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """YoLink BinarySensor."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from typing import Any
8 
9 from yolink.const import (
10  ATTR_DEVICE_CO_SMOKE_SENSOR,
11  ATTR_DEVICE_DOOR_SENSOR,
12  ATTR_DEVICE_LEAK_SENSOR,
13  ATTR_DEVICE_MOTION_SENSOR,
14  ATTR_DEVICE_VIBRATION_SENSOR,
15 )
16 from yolink.device import YoLinkDevice
17 
19  BinarySensorDeviceClass,
20  BinarySensorEntity,
21  BinarySensorEntityDescription,
22 )
23 from homeassistant.config_entries import ConfigEntry
24 from homeassistant.core import HomeAssistant, callback
25 from homeassistant.helpers.entity_platform import AddEntitiesCallback
26 
27 from .const import DOMAIN
28 from .coordinator import YoLinkCoordinator
29 from .entity import YoLinkEntity
30 
31 
32 @dataclass(frozen=True)
34  """YoLink BinarySensorEntityDescription."""
35 
36  exists_fn: Callable[[YoLinkDevice], bool] = lambda _: True
37  state_key: str = "state"
38  value: Callable[[Any], bool | None] = lambda _: None
39 
40 
41 SENSOR_DEVICE_TYPE = [
42  ATTR_DEVICE_DOOR_SENSOR,
43  ATTR_DEVICE_MOTION_SENSOR,
44  ATTR_DEVICE_LEAK_SENSOR,
45  ATTR_DEVICE_VIBRATION_SENSOR,
46  ATTR_DEVICE_CO_SMOKE_SENSOR,
47 ]
48 
49 
50 SENSOR_TYPES: tuple[YoLinkBinarySensorEntityDescription, ...] = (
52  key="door_state",
53  device_class=BinarySensorDeviceClass.DOOR,
54  value=lambda value: value == "open" if value is not None else None,
55  exists_fn=lambda device: device.device_type == ATTR_DEVICE_DOOR_SENSOR,
56  ),
58  key="motion_state",
59  device_class=BinarySensorDeviceClass.MOTION,
60  value=lambda value: value == "alert" if value is not None else None,
61  exists_fn=lambda device: device.device_type == ATTR_DEVICE_MOTION_SENSOR,
62  ),
64  key="leak_state",
65  device_class=BinarySensorDeviceClass.MOISTURE,
66  value=lambda value: value in ("alert", "full") if value is not None else None,
67  exists_fn=lambda device: device.device_type == ATTR_DEVICE_LEAK_SENSOR,
68  ),
70  key="vibration_state",
71  device_class=BinarySensorDeviceClass.VIBRATION,
72  value=lambda value: value == "alert" if value is not None else None,
73  exists_fn=lambda device: device.device_type == ATTR_DEVICE_VIBRATION_SENSOR,
74  ),
76  key="co_detected",
77  device_class=BinarySensorDeviceClass.CO,
78  value=lambda state: state.get("gasAlarm"),
79  exists_fn=lambda device: device.device_type == ATTR_DEVICE_CO_SMOKE_SENSOR,
80  ),
82  key="smoke_detected",
83  device_class=BinarySensorDeviceClass.SMOKE,
84  value=lambda state: state.get("smokeAlarm"),
85  exists_fn=lambda device: device.device_type == ATTR_DEVICE_CO_SMOKE_SENSOR,
86  ),
87 )
88 
89 
91  hass: HomeAssistant,
92  config_entry: ConfigEntry,
93  async_add_entities: AddEntitiesCallback,
94 ) -> None:
95  """Set up YoLink Sensor from a config entry."""
96  device_coordinators = hass.data[DOMAIN][config_entry.entry_id].device_coordinators
97  binary_sensor_device_coordinators = [
98  device_coordinator
99  for device_coordinator in device_coordinators.values()
100  if device_coordinator.device.device_type in SENSOR_DEVICE_TYPE
101  ]
104  config_entry, binary_sensor_device_coordinator, description
105  )
106  for binary_sensor_device_coordinator in binary_sensor_device_coordinators
107  for description in SENSOR_TYPES
108  if description.exists_fn(binary_sensor_device_coordinator.device)
109  )
110 
111 
113  """YoLink Sensor Entity."""
114 
115  entity_description: YoLinkBinarySensorEntityDescription
116 
117  def __init__(
118  self,
119  config_entry: ConfigEntry,
120  coordinator: YoLinkCoordinator,
121  description: YoLinkBinarySensorEntityDescription,
122  ) -> None:
123  """Init YoLink Sensor."""
124  super().__init__(config_entry, coordinator)
125  self.entity_descriptionentity_description = description
126  self._attr_unique_id_attr_unique_id = (
127  f"{coordinator.device.device_id} {self.entity_description.key}"
128  )
129 
130  @callback
131  def update_entity_state(self, state: dict[str, Any]) -> None:
132  """Update HA Entity State."""
133  self._attr_is_on_attr_is_on = self.entity_descriptionentity_description.value(
134  state.get(self.entity_descriptionentity_description.state_key)
135  )
136  self.async_write_ha_stateasync_write_ha_state()
137 
138  @property
139  def available(self) -> bool:
140  """Return true is device is available."""
141  return super().available and self.coordinator.dev_online