Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """DataUpdateCoordinator for the Hydrawise integration."""
2 
3 from __future__ import annotations
4 
5 from dataclasses import dataclass, field
6 
7 from pydrawise import Hydrawise
8 from pydrawise.schema import Controller, ControllerWaterUseSummary, Sensor, User, Zone
9 
10 from homeassistant.core import HomeAssistant
11 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
12 from homeassistant.util.dt import now
13 
14 from .const import DOMAIN, LOGGER, MAIN_SCAN_INTERVAL, WATER_USE_SCAN_INTERVAL
15 
16 
17 @dataclass
19  """Container for data fetched from the Hydrawise API."""
20 
21  user: User
22  controllers: dict[int, Controller] = field(default_factory=dict)
23  zones: dict[int, Zone] = field(default_factory=dict)
24  sensors: dict[int, Sensor] = field(default_factory=dict)
25  daily_water_summary: dict[int, ControllerWaterUseSummary] = field(
26  default_factory=dict
27  )
28 
29 
30 @dataclass
32  """Container for all Hydrawise DataUpdateCoordinator instances."""
33 
34  main: HydrawiseMainDataUpdateCoordinator
35  water_use: HydrawiseWaterUseDataUpdateCoordinator
36 
37 
39  """Base class for Hydrawise Data Update Coordinators."""
40 
41  api: Hydrawise
42 
43 
45  """The main Hydrawise Data Update Coordinator.
46 
47  This fetches the primary state data for Hydrawise controllers and zones
48  at a relatively frequent interval so that the primary functions of the
49  integration are updated in a timely manner.
50  """
51 
52  def __init__(self, hass: HomeAssistant, api: Hydrawise) -> None:
53  """Initialize HydrawiseDataUpdateCoordinator."""
54  super().__init__(hass, LOGGER, name=DOMAIN, update_interval=MAIN_SCAN_INTERVAL)
55  self.apiapi = api
56 
57  async def _async_update_data(self) -> HydrawiseData:
58  """Fetch the latest data from Hydrawise."""
59  # Don't fetch zones. We'll fetch them for each controller later.
60  # This is to prevent 502 errors in some cases.
61  # See: https://github.com/home-assistant/core/issues/120128
62  data = HydrawiseData(user=await self.apiapi.get_user(fetch_zones=False))
63  for controller in data.user.controllers:
64  data.controllers[controller.id] = controller
65  controller.zones = await self.apiapi.get_zones(controller)
66  for zone in controller.zones:
67  data.zones[zone.id] = zone
68  for sensor in controller.sensors:
69  data.sensors[sensor.id] = sensor
70  return data
71 
72 
74  """Data Update Coordinator for Hydrawise Water Use.
75 
76  This fetches data that is more expensive for the Hydrawise API to compute
77  at a less frequent interval as to not overload the Hydrawise servers.
78  """
79 
80  _main_coordinator: HydrawiseMainDataUpdateCoordinator
81 
82  def __init__(
83  self,
84  hass: HomeAssistant,
85  api: Hydrawise,
86  main_coordinator: HydrawiseMainDataUpdateCoordinator,
87  ) -> None:
88  """Initialize HydrawiseWaterUseDataUpdateCoordinator."""
89  super().__init__(
90  hass,
91  LOGGER,
92  name=f"{DOMAIN} water use",
93  update_interval=WATER_USE_SCAN_INTERVAL,
94  )
95  self.apiapi = api
96  self._main_coordinator_main_coordinator = main_coordinator
97 
98  async def _async_update_data(self) -> HydrawiseData:
99  """Fetch the latest data from Hydrawise."""
100  daily_water_summary: dict[int, ControllerWaterUseSummary] = {}
101  for controller in self._main_coordinator_main_coordinator.data.controllers.values():
102  daily_water_summary[controller.id] = await self.apiapi.get_water_use_summary(
103  controller,
104  now().replace(hour=0, minute=0, second=0, microsecond=0),
105  now(),
106  )
107  main_data = self._main_coordinator_main_coordinator.data
108  return HydrawiseData(
109  user=main_data.user,
110  controllers=main_data.controllers,
111  zones=main_data.zones,
112  sensors=main_data.sensors,
113  daily_water_summary=daily_water_summary,
114  )
None __init__(self, HomeAssistant hass, Hydrawise api, HydrawiseMainDataUpdateCoordinator main_coordinator)
Definition: coordinator.py:87
datetime now(HomeAssistant hass)
Definition: template.py:1890