Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Binary sensors for the Elexa Guardian integration."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from typing import Any
8 
10  DOMAIN as BINARY_SENSOR_DOMAIN,
11  BinarySensorDeviceClass,
12  BinarySensorEntity,
13  BinarySensorEntityDescription,
14 )
15 from homeassistant.config_entries import ConfigEntry
16 from homeassistant.const import EntityCategory
17 from homeassistant.core import HomeAssistant, callback
18 from homeassistant.helpers.dispatcher import async_dispatcher_connect
19 from homeassistant.helpers.entity_platform import AddEntitiesCallback
20 
21 from . import GuardianData
22 from .const import (
23  API_SYSTEM_ONBOARD_SENSOR_STATUS,
24  CONF_UID,
25  DOMAIN,
26  SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED,
27 )
28 from .coordinator import GuardianDataUpdateCoordinator
29 from .entity import (
30  PairedSensorEntity,
31  ValveControllerEntity,
32  ValveControllerEntityDescription,
33 )
34 from .util import (
35  EntityDomainReplacementStrategy,
36  async_finish_entity_domain_replacements,
37 )
38 
39 ATTR_CONNECTED_CLIENTS = "connected_clients"
40 
41 SENSOR_KIND_LEAK_DETECTED = "leak_detected"
42 SENSOR_KIND_MOVED = "moved"
43 
44 
45 @dataclass(frozen=True, kw_only=True)
47  """Describe a Guardian paired sensor binary sensor."""
48 
49  is_on_fn: Callable[[dict[str, Any]], bool]
50 
51 
52 @dataclass(frozen=True, kw_only=True)
54  BinarySensorEntityDescription, ValveControllerEntityDescription
55 ):
56  """Describe a Guardian valve controller binary sensor."""
57 
58  is_on_fn: Callable[[dict[str, Any]], bool]
59 
60 
61 PAIRED_SENSOR_DESCRIPTIONS = (
63  key=SENSOR_KIND_LEAK_DETECTED,
64  translation_key="leak",
65  device_class=BinarySensorDeviceClass.MOISTURE,
66  is_on_fn=lambda data: data["wet"],
67  ),
69  key=SENSOR_KIND_MOVED,
70  translation_key="moved",
71  device_class=BinarySensorDeviceClass.MOVING,
72  entity_category=EntityCategory.DIAGNOSTIC,
73  is_on_fn=lambda data: data["moved"],
74  ),
75 )
76 
77 VALVE_CONTROLLER_DESCRIPTIONS = (
79  key=SENSOR_KIND_LEAK_DETECTED,
80  translation_key="leak",
81  device_class=BinarySensorDeviceClass.MOISTURE,
82  api_category=API_SYSTEM_ONBOARD_SENSOR_STATUS,
83  is_on_fn=lambda data: data["wet"],
84  ),
85 )
86 
87 
89  hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
90 ) -> None:
91  """Set up Guardian switches based on a config entry."""
92  data: GuardianData = hass.data[DOMAIN][entry.entry_id]
93  uid = entry.data[CONF_UID]
94 
96  hass,
97  entry,
98  (
100  BINARY_SENSOR_DOMAIN,
101  f"{uid}_ap_enabled",
102  ),
103  ),
104  )
105 
106  @callback
107  def add_new_paired_sensor(uid: str) -> None:
108  """Add a new paired sensor."""
111  entry, data.paired_sensor_manager.coordinators[uid], description
112  )
113  for description in PAIRED_SENSOR_DESCRIPTIONS
114  )
115 
116  # Handle adding paired sensors after HASS startup:
117  entry.async_on_unload(
119  hass,
120  SIGNAL_PAIRED_SENSOR_COORDINATOR_ADDED.format(entry.data[CONF_UID]),
121  add_new_paired_sensor,
122  )
123  )
124 
125  # Add all valve controller-specific binary sensors:
126  sensors: list[PairedSensorBinarySensor | ValveControllerBinarySensor] = [
128  entry, data.valve_controller_coordinators, description
129  )
130  for description in VALVE_CONTROLLER_DESCRIPTIONS
131  ]
132 
133  # Add all paired sensor-specific binary sensors:
134  sensors.extend(
135  [
136  PairedSensorBinarySensor(entry, coordinator, description)
137  for coordinator in data.paired_sensor_manager.coordinators.values()
138  for description in PAIRED_SENSOR_DESCRIPTIONS
139  ]
140  )
141 
142  async_add_entities(sensors)
143 
144 
146  """Define a binary sensor related to a Guardian valve controller."""
147 
148  entity_description: PairedSensorBinarySensorDescription
149 
150  def __init__(
151  self,
152  entry: ConfigEntry,
153  coordinator: GuardianDataUpdateCoordinator,
154  description: BinarySensorEntityDescription,
155  ) -> None:
156  """Initialize."""
157  super().__init__(entry, coordinator, description)
158 
159  self._attr_is_on_attr_is_on = True
160 
161  @property
162  def is_on(self) -> bool:
163  """Return true if the binary sensor is on."""
164  return self.entity_descriptionentity_description.is_on_fn(self.coordinator.data)
165 
166 
168  """Define a binary sensor related to a Guardian valve controller."""
169 
170  entity_description: ValveControllerBinarySensorDescription
171 
172  def __init__(
173  self,
174  entry: ConfigEntry,
175  coordinators: dict[str, GuardianDataUpdateCoordinator],
176  description: ValveControllerBinarySensorDescription,
177  ) -> None:
178  """Initialize."""
179  super().__init__(entry, coordinators, description)
180 
181  self._attr_is_on_attr_is_on = True
182 
183  @property
184  def is_on(self) -> bool:
185  """Return true if the binary sensor is on."""
186  return self.entity_descriptionentity_description.is_on_fn(self.coordinator.data)
None __init__(self, ConfigEntry entry, GuardianDataUpdateCoordinator coordinator, BinarySensorEntityDescription description)
None __init__(self, ConfigEntry entry, dict[str, GuardianDataUpdateCoordinator] coordinators, ValveControllerBinarySensorDescription description)
None async_setup_entry(HomeAssistant hass, ConfigEntry entry, AddEntitiesCallback async_add_entities)
None async_finish_entity_domain_replacements(HomeAssistant hass, ConfigEntry entry, Iterable[EntityDomainReplacementStrategy] entity_replacement_strategies)
Definition: util.py:41
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103