Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """History stats data coordinator."""
2 
3 from __future__ import annotations
4 
5 from datetime import timedelta
6 import logging
7 from typing import Any
8 
9 from homeassistant.config_entries import ConfigEntry
10 from homeassistant.core import (
11  CALLBACK_TYPE,
12  Event,
13  EventStateChangedData,
14  HomeAssistant,
15  callback,
16 )
17 from homeassistant.exceptions import TemplateError
18 from homeassistant.helpers.event import async_track_state_change_event
19 from homeassistant.helpers.start import async_at_start
20 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
21 
22 from .data import HistoryStats, HistoryStatsState
23 
24 _LOGGER = logging.getLogger(__name__)
25 
26 
27 UPDATE_INTERVAL = timedelta(minutes=1)
28 
29 
31  """DataUpdateCoordinator for history stats."""
32 
33  def __init__(
34  self,
35  hass: HomeAssistant,
36  history_stats: HistoryStats,
37  config_entry: ConfigEntry | None,
38  name: str,
39  ) -> None:
40  """Initialize DataUpdateCoordinator."""
41  self._history_stats_history_stats = history_stats
42  self._subscriber_count_subscriber_count = 0
43  self._at_start_listener_at_start_listener: CALLBACK_TYPE | None = None
44  self._track_events_listener_track_events_listener: CALLBACK_TYPE | None = None
45  super().__init__(
46  hass,
47  _LOGGER,
48  config_entry=config_entry,
49  name=name,
50  update_interval=UPDATE_INTERVAL,
51  )
52 
53  @callback
54  def async_setup_state_listener(self) -> CALLBACK_TYPE:
55  """Set up listeners and return a callback to cancel them."""
56 
57  @callback
58  def remove_listener() -> None:
59  """Remove update listener."""
60  self._subscriber_count_subscriber_count -= 1
61  if self._subscriber_count_subscriber_count == 0:
62  self._async_remove_listener_async_remove_listener()
63 
64  if self._subscriber_count_subscriber_count == 0:
65  self._async_add_listener_async_add_listener()
66  self._subscriber_count_subscriber_count += 1
67 
68  return remove_listener
69 
70  @callback
71  def _async_remove_listener(self) -> None:
72  """Remove state change listener."""
73  if self._track_events_listener_track_events_listener:
74  self._track_events_listener_track_events_listener()
75  self._track_events_listener_track_events_listener = None
76  if self._at_start_listener_at_start_listener:
77  self._at_start_listener_at_start_listener()
78  self._at_start_listener_at_start_listener = None
79 
80  @callback
81  def _async_add_listener(self) -> None:
82  """Add a listener to start tracking state changes after start."""
83  self._at_start_listener_at_start_listener = async_at_start(
84  self.hasshass, self._async_add_events_listener_async_add_events_listener
85  )
86 
87  @callback
88  def _async_add_events_listener(self, *_: Any) -> None:
89  """Handle hass starting and start tracking events."""
90  self._at_start_listener_at_start_listener = None
91  self._track_events_listener_track_events_listener = async_track_state_change_event(
92  self.hasshass, [self._history_stats_history_stats.entity_id], self._async_update_from_event_async_update_from_event
93  )
94 
96  self, event: Event[EventStateChangedData]
97  ) -> None:
98  """Process an update from an event."""
99  self.async_set_updated_dataasync_set_updated_data(await self._history_stats_history_stats.async_update(event))
100 
101  async def _async_update_data(self) -> HistoryStatsState:
102  """Fetch update the history stats state."""
103  try:
104  return await self._history_stats_history_stats.async_update(None)
105  except (TemplateError, TypeError, ValueError) as ex:
106  raise UpdateFailed(ex) from ex
None __init__(self, HomeAssistant hass, HistoryStats history_stats, ConfigEntry|None config_entry, str name)
Definition: coordinator.py:39
None _async_update_from_event(self, Event[EventStateChangedData] event)
Definition: coordinator.py:97
CALLBACK_TYPE async_track_state_change_event(HomeAssistant hass, str|Iterable[str] entity_ids, Callable[[Event[EventStateChangedData]], Any] action, HassJobType|None job_type=None)
Definition: event.py:314
CALLBACK_TYPE async_at_start(HomeAssistant hass, Callable[[HomeAssistant], Coroutine[Any, Any, None]|None] at_start_cb)
Definition: start.py:61