Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Support for deCONZ binary sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 
8 from pydeconz.interfaces.sensors import SensorResources
9 from pydeconz.models.event import EventType
10 from pydeconz.models.sensor import SensorBase as PydeconzSensorBase
11 from pydeconz.models.sensor.alarm import Alarm
12 from pydeconz.models.sensor.carbon_monoxide import CarbonMonoxide
13 from pydeconz.models.sensor.fire import Fire
14 from pydeconz.models.sensor.generic_flag import GenericFlag
15 from pydeconz.models.sensor.open_close import OpenClose
16 from pydeconz.models.sensor.presence import Presence
17 from pydeconz.models.sensor.vibration import Vibration
18 from pydeconz.models.sensor.water import Water
19 
21  DOMAIN as BINARY_SENSOR_DOMAIN,
22  BinarySensorDeviceClass,
23  BinarySensorEntity,
24  BinarySensorEntityDescription,
25 )
26 from homeassistant.config_entries import ConfigEntry
27 from homeassistant.const import ATTR_TEMPERATURE, EntityCategory
28 from homeassistant.core import HomeAssistant, callback
29 from homeassistant.helpers.entity_platform import AddEntitiesCallback
30 
31 from .const import ATTR_DARK, ATTR_ON
32 from .entity import DeconzDevice
33 from .hub import DeconzHub
34 
35 ATTR_ORIENTATION = "orientation"
36 ATTR_TILTANGLE = "tiltangle"
37 ATTR_VIBRATIONSTRENGTH = "vibrationstrength"
38 
39 PROVIDES_EXTRA_ATTRIBUTES = (
40  "alarm",
41  "carbon_monoxide",
42  "fire",
43  "flag",
44  "open",
45  "presence",
46  "vibration",
47  "water",
48 )
49 
50 
51 @dataclass(frozen=True, kw_only=True)
53  _T: (
54  Alarm,
55  CarbonMonoxide,
56  Fire,
57  GenericFlag,
58  OpenClose,
59  Presence,
60  Vibration,
61  Water,
62  PydeconzSensorBase,
63  )
64 ](BinarySensorEntityDescription):
65  """Class describing deCONZ binary sensor entities."""
66 
67  instance_check: type[_T] | None = None
68  name_suffix: str = ""
69  old_unique_id_suffix: str = ""
70  update_key: str
71  value_fn: Callable[[_T], bool | None]
72 
73 
74 ENTITY_DESCRIPTIONS: tuple[DeconzBinarySensorDescription, ...] = (
75  DeconzBinarySensorDescription[Alarm](
76  key="alarm",
77  update_key="alarm",
78  value_fn=lambda device: device.alarm,
79  instance_check=Alarm,
80  device_class=BinarySensorDeviceClass.SAFETY,
81  ),
82  DeconzBinarySensorDescription[CarbonMonoxide](
83  key="carbon_monoxide",
84  update_key="carbonmonoxide",
85  value_fn=lambda device: device.carbon_monoxide,
86  instance_check=CarbonMonoxide,
87  device_class=BinarySensorDeviceClass.CO,
88  ),
89  DeconzBinarySensorDescription[Fire](
90  key="fire",
91  update_key="fire",
92  value_fn=lambda device: device.fire,
93  instance_check=Fire,
94  device_class=BinarySensorDeviceClass.SMOKE,
95  ),
96  DeconzBinarySensorDescription[Fire](
97  key="in_test_mode",
98  update_key="test",
99  value_fn=lambda device: device.in_test_mode,
100  instance_check=Fire,
101  name_suffix="Test Mode",
102  old_unique_id_suffix="test mode",
103  device_class=BinarySensorDeviceClass.SMOKE,
104  entity_category=EntityCategory.DIAGNOSTIC,
105  ),
106  DeconzBinarySensorDescription[GenericFlag](
107  key="flag",
108  update_key="flag",
109  value_fn=lambda device: device.flag,
110  instance_check=GenericFlag,
111  ),
112  DeconzBinarySensorDescription[OpenClose](
113  key="open",
114  update_key="open",
115  value_fn=lambda device: device.open,
116  instance_check=OpenClose,
117  device_class=BinarySensorDeviceClass.OPENING,
118  ),
119  DeconzBinarySensorDescription[Presence](
120  key="presence",
121  update_key="presence",
122  value_fn=lambda device: device.presence,
123  instance_check=Presence,
124  device_class=BinarySensorDeviceClass.MOTION,
125  ),
126  DeconzBinarySensorDescription[Vibration](
127  key="vibration",
128  update_key="vibration",
129  value_fn=lambda device: device.vibration,
130  instance_check=Vibration,
131  device_class=BinarySensorDeviceClass.VIBRATION,
132  ),
133  DeconzBinarySensorDescription[Water](
134  key="water",
135  update_key="water",
136  value_fn=lambda device: device.water,
137  instance_check=Water,
138  device_class=BinarySensorDeviceClass.MOISTURE,
139  ),
140  DeconzBinarySensorDescription[SensorResources](
141  key="tampered",
142  update_key="tampered",
143  value_fn=lambda device: device.tampered,
144  name_suffix="Tampered",
145  old_unique_id_suffix="tampered",
146  device_class=BinarySensorDeviceClass.TAMPER,
147  entity_category=EntityCategory.DIAGNOSTIC,
148  ),
149  DeconzBinarySensorDescription[SensorResources](
150  key="low_battery",
151  update_key="lowbattery",
152  value_fn=lambda device: device.low_battery,
153  name_suffix="Low Battery",
154  old_unique_id_suffix="low battery",
155  device_class=BinarySensorDeviceClass.BATTERY,
156  entity_category=EntityCategory.DIAGNOSTIC,
157  ),
158 )
159 
160 
162  hass: HomeAssistant,
163  config_entry: ConfigEntry,
164  async_add_entities: AddEntitiesCallback,
165 ) -> None:
166  """Set up the deCONZ binary sensor."""
167  hub = DeconzHub.get_hub(hass, config_entry)
168  hub.entities[BINARY_SENSOR_DOMAIN] = set()
169 
170  @callback
171  def async_add_sensor(_: EventType, sensor_id: str) -> None:
172  """Add sensor from deCONZ."""
173  sensor = hub.api.sensors[sensor_id]
174 
175  for description in ENTITY_DESCRIPTIONS:
176  if (
177  description.instance_check
178  and not isinstance(sensor, description.instance_check)
179  ) or description.value_fn(sensor) is None:
180  continue
181  async_add_entities([DeconzBinarySensor(sensor, hub, description)])
182 
183  hub.register_platform_add_device_callback(
184  async_add_sensor,
185  hub.api.sensors,
186  )
187 
188 
189 class DeconzBinarySensor(DeconzDevice[SensorResources], BinarySensorEntity):
190  """Representation of a deCONZ binary sensor."""
191 
192  TYPE = BINARY_SENSOR_DOMAIN
193  entity_description: DeconzBinarySensorDescription
194 
195  def __init__(
196  self,
197  device: SensorResources,
198  hub: DeconzHub,
199  description: DeconzBinarySensorDescription,
200  ) -> None:
201  """Initialize deCONZ binary sensor."""
202  self.entity_descriptionentity_description = description
203  self.unique_id_suffixunique_id_suffix = description.key
204  self._update_key_update_key = description.update_key
205  if description.name_suffix:
206  self._name_suffix_name_suffix = description.name_suffix
207  super().__init__(device, hub)
208 
209  if (
210  self.entity_descriptionentity_description.key in PROVIDES_EXTRA_ATTRIBUTES
211  and self._update_keys is not None
212  ):
213  self._update_keys.update({"on", "state"})
214 
215  @property
216  def is_on(self) -> bool | None:
217  """Return the state of the sensor."""
218  return self.entity_descriptionentity_description.value_fn(self._device)
219 
220  @property
221  def extra_state_attributes(self) -> dict[str, bool | float | int | list | None]:
222  """Return the state attributes of the sensor."""
223  attr: dict[str, bool | float | int | list | None] = {}
224 
225  if self.entity_descriptionentity_description.key not in PROVIDES_EXTRA_ATTRIBUTES:
226  return attr
227 
228  if self._device.on is not None:
229  attr[ATTR_ON] = self._device.on
230 
231  if self._device.internal_temperature is not None:
232  attr[ATTR_TEMPERATURE] = self._device.internal_temperature
233 
234  if isinstance(self._device, Presence):
235  if self._device.dark is not None:
236  attr[ATTR_DARK] = self._device.dark
237 
238  elif isinstance(self._device, Vibration):
239  attr[ATTR_ORIENTATION] = self._device.orientation
240  attr[ATTR_TILTANGLE] = self._device.tilt_angle
241  attr[ATTR_VIBRATIONSTRENGTH] = self._device.vibration_strength
242 
243  return attr
dict[str, bool|float|int|list|None] extra_state_attributes(self)
None __init__(self, SensorResources device, DeconzHub hub, DeconzBinarySensorDescription description)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
IssData update(pyiss.ISS iss)
Definition: __init__.py:33