Home Assistant Unofficial Reference 2024.12.1
coordinator.py
Go to the documentation of this file.
1 """Proxy to handle account communication with Renault servers."""
2 
3 from __future__ import annotations
4 
5 import asyncio
6 from collections.abc import Awaitable, Callable
7 from datetime import timedelta
8 import logging
9 from typing import TypeVar
10 
11 from renault_api.kamereon.exceptions import (
12  AccessDeniedException,
13  KamereonResponseException,
14  NotSupportedException,
15 )
16 from renault_api.kamereon.models import KamereonVehicleDataAttributes
17 
18 from homeassistant.core import HomeAssistant
19 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
20 
21 T = TypeVar("T", bound=KamereonVehicleDataAttributes | None)
22 
23 # We have potentially 7 coordinators per vehicle
24 _PARALLEL_SEMAPHORE = asyncio.Semaphore(1)
25 
26 
28  """Handle vehicle communication with Renault servers."""
29 
30  def __init__(
31  self,
32  hass: HomeAssistant,
33  logger: logging.Logger,
34  *,
35  name: str,
36  update_interval: timedelta,
37  update_method: Callable[[], Awaitable[T]],
38  ) -> None:
39  """Initialise coordinator."""
40  super().__init__(
41  hass,
42  logger,
43  name=name,
44  update_interval=update_interval,
45  update_method=update_method,
46  )
47  self.access_deniedaccess_denied = False
48  self.not_supportednot_supported = False
49  self._has_already_worked_has_already_worked = False
50 
51  async def _async_update_data(self) -> T:
52  """Fetch the latest data from the source."""
53  if self.update_methodupdate_method is None:
54  raise NotImplementedError("Update method not implemented")
55  try:
56  async with _PARALLEL_SEMAPHORE:
57  data = await self.update_methodupdate_method()
58 
59  except AccessDeniedException as err:
60  # This can mean both a temporary error or a permanent error. If it has
61  # worked before, make it temporary, if not disable the update interval.
62  if not self._has_already_worked_has_already_worked:
64  self.access_deniedaccess_denied = True
65  raise UpdateFailed(f"This endpoint is denied: {err}") from err
66 
67  except NotSupportedException as err:
68  # Disable because the vehicle does not support this Renault endpoint.
70  self.not_supportednot_supported = True
71  raise UpdateFailed(f"This endpoint is not supported: {err}") from err
72 
73  except KamereonResponseException as err:
74  # Other Renault errors.
75  raise UpdateFailed(f"Error communicating with API: {err}") from err
76 
77  self._has_already_worked_has_already_worked = True
78  return data
79 
80  async def async_config_entry_first_refresh(self) -> None:
81  """Refresh data for the first time when a config entry is setup.
82 
83  Contrary to base implementation, we are not raising ConfigEntryNotReady
84  but only updating the `access_denied` and `not_supported` flags.
85  """
86  await self._async_refresh_async_refresh(log_failures=False, raise_on_auth_failed=True)
None __init__(self, HomeAssistant hass, logging.Logger logger, *str name, timedelta update_interval, Callable[[], Awaitable[T]] update_method)
Definition: coordinator.py:38
None _async_refresh(self, bool log_failures=True, bool raise_on_auth_failed=False, bool scheduled=False, bool raise_on_entry_error=False)