Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """Coordinator for the Philips TV integration."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 from collections.abc import Mapping
7 from datetime import timedelta
8 import logging
9 from typing import Any
10 
11 from haphilipsjs import (
12  AutenticationFailure,
13  ConnectionFailure,
14  GeneralFailure,
15  PhilipsTV,
16 )
17 from haphilipsjs.typing import SystemType
18 
19 from homeassistant.config_entries import ConfigEntry
20 from homeassistant.core import HomeAssistant, callback
21 from homeassistant.exceptions import ConfigEntryAuthFailed
22 from homeassistant.helpers.debounce import Debouncer
23 from homeassistant.helpers.device_registry import DeviceInfo
24 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
25 
26 from .const import CONF_ALLOW_NOTIFY, CONF_SYSTEM, DOMAIN
27 
28 _LOGGER = logging.getLogger(__name__)
29 
30 
32  """Coordinator to update data."""
33 
34  config_entry: ConfigEntry
35 
36  def __init__(
37  self, hass: HomeAssistant, api: PhilipsTV, options: Mapping[str, Any]
38  ) -> None:
39  """Set up the coordinator."""
40  self.apiapi = api
41  self.optionsoptions = options
42  self._notify_future_notify_future: asyncio.Task | None = None
43 
44  super().__init__(
45  hass,
46  _LOGGER,
47  name=DOMAIN,
48  update_interval=timedelta(seconds=30),
49  request_refresh_debouncer=Debouncer(
50  hass, _LOGGER, cooldown=2.0, immediate=False
51  ),
52  )
53 
54  @property
55  def device_info(self) -> DeviceInfo:
56  """Return device info."""
57  return DeviceInfo(
58  identifiers={
59  (DOMAIN, self.unique_idunique_id),
60  },
61  manufacturer="Philips",
62  model=self.systemsystem.get("model"),
63  name=self.systemsystem["name"],
64  sw_version=self.systemsystem.get("softwareversion"),
65  )
66 
67  @property
68  def system(self) -> SystemType:
69  """Return the system descriptor."""
70  if self.apiapi.system:
71  return self.apiapi.system
72  return self.config_entryconfig_entry.data[CONF_SYSTEM]
73 
74  @property
75  def unique_id(self) -> str:
76  """Return the system descriptor."""
77  entry = self.config_entryconfig_entry
78  if entry.unique_id:
79  return entry.unique_id
80  assert entry.entry_id
81  return entry.entry_id
82 
83  @property
84  def _notify_wanted(self):
85  """Return if the notify feature should be active.
86 
87  We only run it when TV is considered fully on. When powerstate is in standby, the TV
88  will go in low power states and seemingly break the http server in odd ways.
89  """
90  return (
91  self.apiapi.on
92  and self.apiapi.powerstate == "On"
93  and self.apiapi.notify_change_supported
94  and self.optionsoptions.get(CONF_ALLOW_NOTIFY, False)
95  )
96 
97  async def _notify_task(self):
98  while self._notify_wanted_notify_wanted:
99  try:
100  res = await self.apiapi.notifyChange(130)
101  except (ConnectionFailure, AutenticationFailure):
102  res = None
103 
104  if res:
105  self.async_set_updated_dataasync_set_updated_data(None)
106  elif res is None:
107  _LOGGER.debug("Aborting notify due to unexpected return")
108  break
109 
110  @callback
112  if self._notify_future_notify_future:
113  self._notify_future_notify_future.cancel()
114  self._notify_future_notify_future = None
115 
116  @callback
118  if self._notify_future_notify_future and not self._notify_future_notify_future.done():
119  return
120 
121  if self._notify_wanted_notify_wanted:
122  self._notify_future_notify_future = asyncio.create_task(self._notify_task_notify_task())
123 
124  @callback
125  def _unschedule_refresh(self) -> None:
126  """Remove data update."""
127  super()._unschedule_refresh()
128  self._async_notify_stop_async_notify_stop()
129 
130  async def _async_update_data(self):
131  """Fetch the latest data from the source."""
132  try:
133  await self.apiapi.update()
134  self._async_notify_schedule_async_notify_schedule()
135  except ConnectionFailure:
136  pass
137  except AutenticationFailure as exception:
138  raise ConfigEntryAuthFailed(str(exception)) from exception
139  except GeneralFailure as exception:
140  raise UpdateFailed(str(exception)) from exception
None __init__(self, HomeAssistant hass, PhilipsTV api, Mapping[str, Any] options)
Definition: coordinator.py:38
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
IssData update(pyiss.ISS iss)
Definition: __init__.py:33