Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Support for the Airzone sensors."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass
6 from typing import Any, Final
7 
8 from aioairzone.const import (
9  AZD_AIR_DEMAND,
10  AZD_BATTERY_LOW,
11  AZD_ERRORS,
12  AZD_FLOOR_DEMAND,
13  AZD_PROBLEMS,
14  AZD_SYSTEMS,
15  AZD_ZONES,
16 )
17 
19  BinarySensorDeviceClass,
20  BinarySensorEntity,
21  BinarySensorEntityDescription,
22 )
23 from homeassistant.config_entries import ConfigEntry
24 from homeassistant.const import EntityCategory
25 from homeassistant.core import HomeAssistant, callback
26 from homeassistant.helpers.entity_platform import AddEntitiesCallback
27 
28 from . import AirzoneConfigEntry
29 from .coordinator import AirzoneUpdateCoordinator
30 from .entity import AirzoneEntity, AirzoneSystemEntity, AirzoneZoneEntity
31 
32 
33 @dataclass(frozen=True)
35  """A class that describes airzone binary sensor entities."""
36 
37  attributes: dict[str, str] | None = None
38 
39 
40 SYSTEM_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = (
42  attributes={
43  "errors": AZD_ERRORS,
44  },
45  device_class=BinarySensorDeviceClass.PROBLEM,
46  entity_category=EntityCategory.DIAGNOSTIC,
47  key=AZD_PROBLEMS,
48  ),
49 )
50 
51 ZONE_BINARY_SENSOR_TYPES: Final[tuple[AirzoneBinarySensorEntityDescription, ...]] = (
53  device_class=BinarySensorDeviceClass.RUNNING,
54  key=AZD_AIR_DEMAND,
55  translation_key="air_demand",
56  ),
58  device_class=BinarySensorDeviceClass.BATTERY,
59  key=AZD_BATTERY_LOW,
60  ),
62  device_class=BinarySensorDeviceClass.RUNNING,
63  key=AZD_FLOOR_DEMAND,
64  translation_key="floor_demand",
65  ),
67  attributes={
68  "errors": AZD_ERRORS,
69  },
70  device_class=BinarySensorDeviceClass.PROBLEM,
71  entity_category=EntityCategory.DIAGNOSTIC,
72  key=AZD_PROBLEMS,
73  ),
74 )
75 
76 
78  hass: HomeAssistant,
79  entry: AirzoneConfigEntry,
80  async_add_entities: AddEntitiesCallback,
81 ) -> None:
82  """Add Airzone binary sensors from a config_entry."""
83  coordinator = entry.runtime_data
84 
85  added_systems: set[str] = set()
86  added_zones: set[str] = set()
87 
88  def _async_entity_listener() -> None:
89  """Handle additions of binary sensors."""
90 
91  entities: list[AirzoneBinarySensor] = []
92 
93  systems_data = coordinator.data.get(AZD_SYSTEMS, {})
94  received_systems = set(systems_data)
95  new_systems = received_systems - added_systems
96  if new_systems:
97  entities.extend(
99  coordinator,
100  description,
101  entry,
102  system_id,
103  systems_data.get(system_id),
104  )
105  for system_id in new_systems
106  for description in SYSTEM_BINARY_SENSOR_TYPES
107  if description.key in systems_data.get(system_id)
108  )
109  added_systems.update(new_systems)
110 
111  zones_data = coordinator.data.get(AZD_ZONES, {})
112  received_zones = set(zones_data)
113  new_zones = received_zones - added_zones
114  if new_zones:
115  entities.extend(
117  coordinator,
118  description,
119  entry,
120  system_zone_id,
121  zones_data.get(system_zone_id),
122  )
123  for system_zone_id in new_zones
124  for description in ZONE_BINARY_SENSOR_TYPES
125  if description.key in zones_data.get(system_zone_id)
126  )
127  added_zones.update(new_zones)
128 
129  async_add_entities(entities)
130 
131  entry.async_on_unload(coordinator.async_add_listener(_async_entity_listener))
132  _async_entity_listener()
133 
134 
136  """Define an Airzone binary sensor."""
137 
138  entity_description: AirzoneBinarySensorEntityDescription
139 
140  @callback
141  def _handle_coordinator_update(self) -> None:
142  """Update attributes when the coordinator updates."""
143  self._async_update_attrs_async_update_attrs()
145 
146  @callback
147  def _async_update_attrs(self) -> None:
148  """Update binary sensor attributes."""
149  self._attr_is_on_attr_is_on = self.get_airzone_valueget_airzone_value(self.entity_description.key)
150  if self.entity_description.attributes:
151  self._attr_extra_state_attributes_attr_extra_state_attributes = {
152  key: self.get_airzone_valueget_airzone_value(val)
153  for key, val in self.entity_description.attributes.items()
154  }
155 
156 
158  """Define an Airzone System binary sensor."""
159 
160  def __init__(
161  self,
162  coordinator: AirzoneUpdateCoordinator,
163  description: AirzoneBinarySensorEntityDescription,
164  entry: ConfigEntry,
165  system_id: str,
166  system_data: dict[str, Any],
167  ) -> None:
168  """Initialize."""
169  super().__init__(coordinator, entry, system_data)
170  self._attr_unique_id_attr_unique_id_attr_unique_id = f"{self._attr_unique_id}_{system_id}_{description.key}"
171  self.entity_descriptionentity_description = description
172  self._async_update_attrs_async_update_attrs()
173 
174 
176  """Define an Airzone Zone binary sensor."""
177 
178  def __init__(
179  self,
180  coordinator: AirzoneUpdateCoordinator,
181  description: AirzoneBinarySensorEntityDescription,
182  entry: ConfigEntry,
183  system_zone_id: str,
184  zone_data: dict[str, Any],
185  ) -> None:
186  """Initialize."""
187  super().__init__(coordinator, entry, system_zone_id, zone_data)
188 
189  self._attr_unique_id_attr_unique_id_attr_unique_id = (
190  f"{self._attr_unique_id}_{system_zone_id}_{description.key}"
191  )
192  self.entity_descriptionentity_description = description
193  self._async_update_attrs_async_update_attrs()
None __init__(self, AirzoneUpdateCoordinator coordinator, AirzoneBinarySensorEntityDescription description, ConfigEntry entry, str system_id, dict[str, Any] system_data)
None __init__(self, AirzoneUpdateCoordinator coordinator, AirzoneBinarySensorEntityDescription description, ConfigEntry entry, str system_zone_id, dict[str, Any] zone_data)
None async_setup_entry(HomeAssistant hass, AirzoneConfigEntry entry, AddEntitiesCallback async_add_entities)