Home Assistant Unofficial Reference 2024.12.1
renault_hub.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 datetime import timedelta
7 import logging
8 
9 from renault_api.gigya.exceptions import InvalidCredentialsException
10 from renault_api.kamereon.models import KamereonVehiclesLink
11 from renault_api.renault_account import RenaultAccount
12 from renault_api.renault_client import RenaultClient
13 
14 from homeassistant.config_entries import ConfigEntry
15 from homeassistant.const import (
16  ATTR_IDENTIFIERS,
17  ATTR_MANUFACTURER,
18  ATTR_MODEL,
19  ATTR_MODEL_ID,
20  ATTR_NAME,
21 )
22 from homeassistant.core import HomeAssistant
23 from homeassistant.exceptions import ConfigEntryNotReady
24 from homeassistant.helpers import device_registry as dr
25 from homeassistant.helpers.aiohttp_client import async_get_clientsession
26 
27 from .const import CONF_KAMEREON_ACCOUNT_ID, DEFAULT_SCAN_INTERVAL
28 from .renault_vehicle import RenaultVehicleProxy
29 
30 LOGGER = logging.getLogger(__name__)
31 
32 
33 class RenaultHub:
34  """Handle account communication with Renault servers."""
35 
36  def __init__(self, hass: HomeAssistant, locale: str) -> None:
37  """Initialise proxy."""
38  self._hass_hass = hass
39  self._client_client = RenaultClient(
40  websession=async_get_clientsession(self._hass_hass), locale=locale
41  )
42  self._account_account: RenaultAccount | None = None
43  self._vehicles: dict[str, RenaultVehicleProxy] = {}
44 
45  async def attempt_login(self, username: str, password: str) -> bool:
46  """Attempt login to Renault servers."""
47  try:
48  await self._client_client.session.login(username, password)
49  except InvalidCredentialsException as ex:
50  LOGGER.error("Login to Renault failed: %s", ex.error_details)
51  else:
52  return True
53  return False
54 
55  async def async_initialise(self, config_entry: ConfigEntry) -> None:
56  """Set up proxy."""
57  account_id: str = config_entry.data[CONF_KAMEREON_ACCOUNT_ID]
58  scan_interval = timedelta(seconds=DEFAULT_SCAN_INTERVAL)
59 
60  self._account_account = await self._client_client.get_api_account(account_id)
61  vehicles = await self._account_account.get_vehicles()
62  if vehicles.vehicleLinks:
63  if any(
64  vehicle_link.vehicleDetails is None
65  for vehicle_link in vehicles.vehicleLinks
66  ):
67  raise ConfigEntryNotReady(
68  "Failed to retrieve vehicle details from Renault servers"
69  )
70  device_registry = dr.async_get(self._hass_hass)
71  await asyncio.gather(
72  *(
73  self.async_initialise_vehicleasync_initialise_vehicle(
74  vehicle_link,
75  self._account_account,
76  scan_interval,
77  config_entry,
78  device_registry,
79  )
80  for vehicle_link in vehicles.vehicleLinks
81  )
82  )
83 
85  self,
86  vehicle_link: KamereonVehiclesLink,
87  renault_account: RenaultAccount,
88  scan_interval: timedelta,
89  config_entry: ConfigEntry,
90  device_registry: dr.DeviceRegistry,
91  ) -> None:
92  """Set up proxy."""
93  assert vehicle_link.vin is not None
94  assert vehicle_link.vehicleDetails is not None
95  # Generate vehicle proxy
96  vehicle = RenaultVehicleProxy(
97  hass=self._hass_hass,
98  vehicle=await renault_account.get_api_vehicle(vehicle_link.vin),
99  details=vehicle_link.vehicleDetails,
100  scan_interval=scan_interval,
101  )
102  await vehicle.async_initialise()
103  device_registry.async_get_or_create(
104  config_entry_id=config_entry.entry_id,
105  identifiers=vehicle.device_info[ATTR_IDENTIFIERS],
106  manufacturer=vehicle.device_info[ATTR_MANUFACTURER],
107  name=vehicle.device_info[ATTR_NAME],
108  model=vehicle.device_info[ATTR_MODEL],
109  model_id=vehicle.device_info[ATTR_MODEL_ID],
110  )
111  self._vehicles[vehicle_link.vin] = vehicle
112 
113  async def get_account_ids(self) -> list[str]:
114  """Get Kamereon account ids."""
115  accounts = []
116  for account in await self._client_client.get_api_accounts():
117  vehicles = await account.get_vehicles()
118 
119  # Only add the account if it has linked vehicles.
120  if vehicles.vehicleLinks:
121  accounts.append(account.account_id)
122  return accounts
123 
124  @property
125  def vehicles(self) -> dict[str, RenaultVehicleProxy]:
126  """Get list of vehicles."""
127  return self._vehicles
None async_initialise_vehicle(self, KamereonVehiclesLink vehicle_link, RenaultAccount renault_account, timedelta scan_interval, ConfigEntry config_entry, dr.DeviceRegistry device_registry)
Definition: renault_hub.py:91
bool attempt_login(self, str username, str password)
Definition: renault_hub.py:45
dict[str, RenaultVehicleProxy] vehicles(self)
Definition: renault_hub.py:125
None __init__(self, HomeAssistant hass, str locale)
Definition: renault_hub.py:36
None async_initialise(self, ConfigEntry config_entry)
Definition: renault_hub.py:55
aiohttp.ClientSession async_get_clientsession(HomeAssistant hass, bool verify_ssl=True, socket.AddressFamily family=socket.AF_UNSPEC, ssl_util.SSLCipherList ssl_cipher=ssl_util.SSLCipherList.PYTHON_DEFAULT)