Home Assistant Unofficial Reference 2024.12.1
binary_sensor.py
Go to the documentation of this file.
1 """Integration with the Rachio Iro sprinkler system controller."""
2 
3 from abc import abstractmethod
4 import logging
5 from typing import Any
6 
8  BinarySensorDeviceClass,
9  BinarySensorEntity,
10 )
11 from homeassistant.config_entries import ConfigEntry
12 from homeassistant.core import HomeAssistant, callback
13 from homeassistant.helpers.dispatcher import async_dispatcher_connect
14 from homeassistant.helpers.entity import Entity
15 from homeassistant.helpers.entity_platform import AddEntitiesCallback
16 
17 from .const import (
18  DOMAIN as DOMAIN_RACHIO,
19  KEY_BATTERY_STATUS,
20  KEY_DEVICE_ID,
21  KEY_LOW,
22  KEY_RAIN_SENSOR_TRIPPED,
23  KEY_REPLACE,
24  KEY_REPORTED_STATE,
25  KEY_STATE,
26  KEY_STATUS,
27  KEY_SUBTYPE,
28  SIGNAL_RACHIO_CONTROLLER_UPDATE,
29  SIGNAL_RACHIO_RAIN_SENSOR_UPDATE,
30  STATUS_ONLINE,
31 )
32 from .coordinator import RachioUpdateCoordinator
33 from .device import RachioPerson
34 from .entity import RachioDevice, RachioHoseTimerEntity
35 from .webhooks import (
36  SUBTYPE_COLD_REBOOT,
37  SUBTYPE_OFFLINE,
38  SUBTYPE_ONLINE,
39  SUBTYPE_RAIN_SENSOR_DETECTION_OFF,
40  SUBTYPE_RAIN_SENSOR_DETECTION_ON,
41 )
42 
43 _LOGGER = logging.getLogger(__name__)
44 
45 
47  hass: HomeAssistant,
48  config_entry: ConfigEntry,
49  async_add_entities: AddEntitiesCallback,
50 ) -> None:
51  """Set up the Rachio binary sensors."""
52  entities = await hass.async_add_executor_job(_create_entities, hass, config_entry)
53  async_add_entities(entities)
54 
55 
56 def _create_entities(hass: HomeAssistant, config_entry: ConfigEntry) -> list[Entity]:
57  entities: list[Entity] = []
58  person: RachioPerson = hass.data[DOMAIN_RACHIO][config_entry.entry_id]
59  for controller in person.controllers:
60  entities.append(RachioControllerOnlineBinarySensor(controller))
61  entities.append(RachioRainSensor(controller))
62  entities.extend(
63  RachioHoseTimerBattery(valve, base_station.status_coordinator)
64  for base_station in person.base_stations
65  for valve in base_station.status_coordinator.data.values()
66  )
67  return entities
68 
69 
71  """Represent a binary sensor that reflects a Rachio state."""
72 
73  _attr_has_entity_name = True
74 
75  @callback
76  def _async_handle_any_update(self, *args, **kwargs) -> None:
77  """Determine whether an update event applies to this device."""
78  if args[0][KEY_DEVICE_ID] != self._controller_controller.controller_id:
79  # For another device
80  return
81 
82  # For this device
83  self._async_handle_update_async_handle_update(args, kwargs)
84 
85  @abstractmethod
86  def _async_handle_update(self, *args, **kwargs) -> None:
87  """Handle an update to the state of this sensor."""
88 
89 
90 class RachioControllerOnlineBinarySensor(RachioControllerBinarySensor):
91  """Represent a binary sensor that reflects if the controller is online."""
92 
93  _attr_device_class = BinarySensorDeviceClass.CONNECTIVITY
94 
95  @property
96  def unique_id(self) -> str:
97  """Return a unique id for this entity."""
98  return f"{self._controller.controller_id}-online"
99 
100  @callback
101  def _async_handle_update(self, *args, **kwargs) -> None:
102  """Handle an update to the state of this sensor."""
103  if args[0][0][KEY_SUBTYPE] in (SUBTYPE_ONLINE, SUBTYPE_COLD_REBOOT):
104  self._attr_is_on_attr_is_on = True
105  elif args[0][0][KEY_SUBTYPE] == SUBTYPE_OFFLINE:
106  self._attr_is_on_attr_is_on = False
107 
108  self.async_write_ha_stateasync_write_ha_state()
109 
110  async def async_added_to_hass(self) -> None:
111  """Subscribe to updates."""
112  self._attr_is_on_attr_is_on = self._controller_controller.init_data[KEY_STATUS] == STATUS_ONLINE
113 
114  self.async_on_removeasync_on_remove(
116  self.hasshass,
117  SIGNAL_RACHIO_CONTROLLER_UPDATE,
118  self._async_handle_any_update_async_handle_any_update,
119  )
120  )
121 
122 
124  """Represent a binary sensor that reflects the status of the rain sensor."""
125 
126  _attr_device_class = BinarySensorDeviceClass.MOISTURE
127  _attr_translation_key = "rain"
128 
129  @property
130  def unique_id(self) -> str:
131  """Return a unique id for this entity."""
132  return f"{self._controller.controller_id}-rain_sensor"
133 
134  @callback
135  def _async_handle_update(self, *args, **kwargs) -> None:
136  """Handle an update to the state of this sensor."""
137  if args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_SENSOR_DETECTION_ON:
138  self._attr_is_on_attr_is_on = True
139  elif args[0][0][KEY_SUBTYPE] == SUBTYPE_RAIN_SENSOR_DETECTION_OFF:
140  self._attr_is_on_attr_is_on = False
141 
142  self.async_write_ha_stateasync_write_ha_state()
143 
144  async def async_added_to_hass(self) -> None:
145  """Subscribe to updates."""
146  self._attr_is_on_attr_is_on = self._controller_controller.init_data[KEY_RAIN_SENSOR_TRIPPED]
147 
148  self.async_on_removeasync_on_remove(
150  self.hasshass,
151  SIGNAL_RACHIO_RAIN_SENSOR_UPDATE,
152  self._async_handle_any_update_async_handle_any_update,
153  )
154  )
155 
156 
158  """Represents a battery sensor for a smart hose timer."""
159 
160  _attr_device_class = BinarySensorDeviceClass.BATTERY
161 
162  def __init__(
163  self, data: dict[str, Any], coordinator: RachioUpdateCoordinator
164  ) -> None:
165  """Initialize a smart hose timer battery sensor."""
166  super().__init__(data, coordinator)
167  self._attr_unique_id_attr_unique_id = f"{self.id}-battery"
168 
169  @callback
170  def _update_attr(self) -> None:
171  """Handle updated coordinator data."""
172  data = self.coordinator.data[self.idid]
173 
174  self._static_attrs_static_attrs = data[KEY_STATE][KEY_REPORTED_STATE]
175  self._attr_is_on_attr_is_on = self._static_attrs_static_attrs[KEY_BATTERY_STATUS] in [
176  KEY_LOW,
177  KEY_REPLACE,
178  ]
None __init__(self, dict[str, Any] data, RachioUpdateCoordinator coordinator)
None async_on_remove(self, CALLBACK_TYPE func)
Definition: entity.py:1331
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
list[Entity] _create_entities(HomeAssistant hass, ConfigEntry config_entry)
Callable[[], None] async_dispatcher_connect(HomeAssistant hass, str signal, Callable[..., Any] target)
Definition: dispatcher.py:103