Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Hydrawise sprinkler sensors."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from datetime import timedelta
8 from typing import Any
9 
10 from pydrawise.schema import ControllerWaterUseSummary
11 
13  SensorDeviceClass,
14  SensorEntity,
15  SensorEntityDescription,
16 )
17 from homeassistant.config_entries import ConfigEntry
18 from homeassistant.const import UnitOfTime, UnitOfVolume
19 from homeassistant.core import HomeAssistant
20 from homeassistant.helpers.entity_platform import AddEntitiesCallback
21 from homeassistant.util import dt as dt_util
22 
23 from .const import DOMAIN
24 from .coordinator import HydrawiseUpdateCoordinators
25 from .entity import HydrawiseEntity
26 
27 
28 @dataclass(frozen=True, kw_only=True)
30  """Describes Hydrawise binary sensor."""
31 
32  value_fn: Callable[[HydrawiseSensor], Any]
33 
34 
35 def _get_water_use(sensor: HydrawiseSensor) -> ControllerWaterUseSummary:
36  return sensor.coordinator.data.daily_water_summary[sensor.controller.id]
37 
38 
39 WATER_USE_CONTROLLER_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
41  key="daily_active_water_time",
42  translation_key="daily_active_water_time",
43  device_class=SensorDeviceClass.DURATION,
44  native_unit_of_measurement=UnitOfTime.SECONDS,
45  value_fn=lambda sensor: _get_water_use(
46  sensor
47  ).total_active_time.total_seconds(),
48  ),
49 )
50 
51 
52 WATER_USE_ZONE_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
54  key="daily_active_water_time",
55  translation_key="daily_active_water_time",
56  device_class=SensorDeviceClass.DURATION,
57  native_unit_of_measurement=UnitOfTime.SECONDS,
58  value_fn=lambda sensor: (
59  _get_water_use(sensor)
60  .active_time_by_zone_id.get(sensor.zone.id, timedelta())
61  .total_seconds()
62  ),
63  ),
64 )
65 
66 FLOW_CONTROLLER_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
68  key="daily_total_water_use",
69  translation_key="daily_total_water_use",
70  device_class=SensorDeviceClass.VOLUME,
71  suggested_display_precision=1,
72  value_fn=lambda sensor: _get_water_use(sensor).total_use,
73  ),
75  key="daily_active_water_use",
76  translation_key="daily_active_water_use",
77  device_class=SensorDeviceClass.VOLUME,
78  suggested_display_precision=1,
79  value_fn=lambda sensor: _get_water_use(sensor).total_active_use,
80  ),
82  key="daily_inactive_water_use",
83  translation_key="daily_inactive_water_use",
84  device_class=SensorDeviceClass.VOLUME,
85  suggested_display_precision=1,
86  value_fn=lambda sensor: _get_water_use(sensor).total_inactive_use,
87  ),
88 )
89 
90 FLOW_ZONE_SENSORS: tuple[SensorEntityDescription, ...] = (
92  key="daily_active_water_use",
93  translation_key="daily_active_water_use",
94  device_class=SensorDeviceClass.VOLUME,
95  suggested_display_precision=1,
96  value_fn=lambda sensor: float(
97  _get_water_use(sensor).active_use_by_zone_id.get(sensor.zone.id, 0.0)
98  ),
99  ),
100 )
101 
102 ZONE_SENSORS: tuple[HydrawiseSensorEntityDescription, ...] = (
104  key="next_cycle",
105  translation_key="next_cycle",
106  device_class=SensorDeviceClass.TIMESTAMP,
107  value_fn=lambda sensor: (
108  dt_util.as_utc(sensor.zone.scheduled_runs.next_run.start_time)
109  if sensor.zone.scheduled_runs.next_run is not None
110  else None
111  ),
112  ),
114  key="watering_time",
115  translation_key="watering_time",
116  native_unit_of_measurement=UnitOfTime.MINUTES,
117  value_fn=lambda sensor: (
118  int(
119  sensor.zone.scheduled_runs.current_run.remaining_time.total_seconds()
120  / 60
121  )
122  if sensor.zone.scheduled_runs.current_run is not None
123  else 0
124  ),
125  ),
126 )
127 
128 FLOW_MEASUREMENT_KEYS = [x.key for x in FLOW_CONTROLLER_SENSORS]
129 
130 
132  hass: HomeAssistant,
133  config_entry: ConfigEntry,
134  async_add_entities: AddEntitiesCallback,
135 ) -> None:
136  """Set up the Hydrawise sensor platform."""
137  coordinators: HydrawiseUpdateCoordinators = hass.data[DOMAIN][config_entry.entry_id]
138  entities: list[HydrawiseSensor] = []
139  for controller in coordinators.main.data.controllers.values():
140  entities.extend(
141  HydrawiseSensor(coordinators.water_use, description, controller)
142  for description in WATER_USE_CONTROLLER_SENSORS
143  )
144  entities.extend(
146  coordinators.water_use, description, controller, zone_id=zone.id
147  )
148  for zone in controller.zones
149  for description in WATER_USE_ZONE_SENSORS
150  )
151  entities.extend(
152  HydrawiseSensor(coordinators.main, description, controller, zone_id=zone.id)
153  for zone in controller.zones
154  for description in ZONE_SENSORS
155  )
156  if (
157  coordinators.water_use.data.daily_water_summary[controller.id].total_use
158  is not None
159  ):
160  # we have a flow sensor for this controller
161  entities.extend(
162  HydrawiseSensor(coordinators.water_use, description, controller)
163  for description in FLOW_CONTROLLER_SENSORS
164  )
165  entities.extend(
167  coordinators.water_use,
168  description,
169  controller,
170  zone_id=zone.id,
171  )
172  for zone in controller.zones
173  for description in FLOW_ZONE_SENSORS
174  )
175  async_add_entities(entities)
176 
177 
179  """A sensor implementation for Hydrawise device."""
180 
181  entity_description: HydrawiseSensorEntityDescription
182 
183  @property
184  def native_unit_of_measurement(self) -> str | None:
185  """Return the unit_of_measurement of the sensor."""
186  if self.entity_descriptionentity_description.device_class != SensorDeviceClass.VOLUME:
187  return self.entity_descriptionentity_description.native_unit_of_measurement
188  return (
189  UnitOfVolume.GALLONS
190  if self.coordinator.data.user.units.units_name == "imperial"
191  else UnitOfVolume.LITERS
192  )
193 
194  @property
195  def icon(self) -> str | None:
196  """Icon of the entity based on the value."""
197  if (
198  self.entity_descriptionentity_description.key in FLOW_MEASUREMENT_KEYS
199  and self.entity_descriptionentity_description.device_class == SensorDeviceClass.VOLUME
200  and round(self.statestatestate, 2) == 0.0
201  ):
202  return "mdi:water-outline"
203  return None
204 
205  def _update_attrs(self) -> None:
206  """Update state attributes."""
207  self._attr_native_value_attr_native_value = self.entity_descriptionentity_description.value_fn(self)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:135
ControllerWaterUseSummary _get_water_use(HydrawiseSensor sensor)
Definition: sensor.py:35