1 """Proxy to handle account communication with Renault servers."""
3 from __future__
import annotations
6 from collections.abc
import Awaitable, Callable, Coroutine
7 from dataclasses
import dataclass
8 from datetime
import datetime, timedelta
9 from functools
import wraps
11 from typing
import Any, Concatenate, cast
13 from renault_api.exceptions
import RenaultException
14 from renault_api.kamereon
import models
15 from renault_api.renault_vehicle
import RenaultVehicle
21 from .const
import DOMAIN
22 from .coordinator
import RenaultDataUpdateCoordinator
24 LOGGER = logging.getLogger(__name__)
27 def with_error_wrapping[**_P, _R](
28 func: Callable[Concatenate[RenaultVehicleProxy, _P], Awaitable[_R]],
29 ) -> Callable[Concatenate[RenaultVehicleProxy, _P], Coroutine[Any, Any, _R]]:
30 """Catch Renault errors."""
34 self: RenaultVehicleProxy,
38 """Catch RenaultException errors and raise HomeAssistantError."""
40 return await func(self, *args, **kwargs)
41 except RenaultException
as err:
49 """Class describing Renault coordinators."""
53 update_method: Callable[
55 Callable[[], Awaitable[models.KamereonVehicleDataAttributes]],
58 requires_electricity: bool =
False
62 """Handle vehicle communication with Renault servers."""
67 vehicle: RenaultVehicle,
68 details: models.KamereonVehicleDetails,
69 scan_interval: timedelta,
71 """Initialise vehicle proxy."""
76 identifiers={(DOMAIN, cast(str, details.vin))},
77 manufacturer=(details.get_brand_label()
or "").capitalize(),
78 model=(details.get_model_label()
or "").capitalize(),
79 model_id=(details.get_model_code()
or ""),
80 name=details.registrationNumber
or "",
82 self.
coordinatorscoordinators: dict[str, RenaultDataUpdateCoordinator] = {}
87 def details(self) -> models.KamereonVehicleDetails:
88 """Return the specs of the vehicle."""
93 """Return a device description for device registry."""
97 """Load available coordinators."""
103 name=f
"{self.details.vin} {coord.key}",
104 update_method=coord.update_method(self.
_vehicle_vehicle),
108 for coord
in COORDINATORS
110 self.
detailsdetails.supports_endpoint(coord.endpoint)
111 and (
not coord.requires_electricity
or self.
detailsdetails.uses_electricity())
115 await asyncio.gather(
117 coordinator.async_config_entry_first_refresh()
118 for coordinator
in self.
coordinatorscoordinators.values()
124 if coordinator.not_supported:
127 "Ignoring endpoint %s as it is not supported: %s",
129 coordinator.last_exception,
132 elif coordinator.access_denied:
135 "Ignoring endpoint %s as it is denied: %s",
137 coordinator.last_exception,
143 self, charge_mode: str
144 ) -> models.KamereonVehicleChargeModeActionData:
145 """Set vehicle charge mode."""
150 """Start vehicle charge."""
155 """Stop vehicle charge."""
159 async
def set_ac_stop(self) -> models.KamereonVehicleHvacStartActionData:
160 """Stop vehicle ac."""
165 self, temperature: float, when: datetime |
None =
None
166 ) -> models.KamereonVehicleHvacStartActionData:
167 """Start vehicle ac."""
172 """Get vehicle hvac settings."""
177 self, schedules: list[models.HvacSchedule]
178 ) -> models.KamereonVehicleHvacScheduleActionData:
179 """Set vehicle hvac schedules."""
184 """Get vehicle charging settings."""
189 self, schedules: list[models.ChargeSchedule]
190 ) -> models.KamereonVehicleChargeScheduleActionData:
191 """Set vehicle charge schedules."""
195 COORDINATORS: tuple[RenaultCoordinatorDescription, ...] = (
199 update_method=
lambda x: x.get_cockpit,
202 endpoint=
"hvac-status",
204 update_method=
lambda x: x.get_hvac_status,
209 update_method=
lambda x: x.get_location,
212 endpoint=
"battery-status",
214 requires_electricity=
True,
215 update_method=
lambda x: x.get_battery_status,
218 endpoint=
"charge-mode",
220 requires_electricity=
True,
221 update_method=
lambda x: x.get_charge_mode,
224 endpoint=
"lock-status",
226 update_method=
lambda x: x.get_lock_status,
229 endpoint=
"res-state",
231 update_method=
lambda x: x.get_res_state,
models.KamereonVehicleHvacSettingsData get_hvac_settings(self)
models.KamereonVehicleHvacScheduleActionData set_hvac_schedules(self, list[models.HvacSchedule] schedules)
models.KamereonVehicleChargingStartActionData set_charge_stop(self)
models.KamereonVehicleChargingStartActionData set_charge_start(self)
models.KamereonVehicleChargingSettingsData get_charging_settings(self)
models.KamereonVehicleChargeModeActionData set_charge_mode(self, str charge_mode)
models.KamereonVehicleChargeScheduleActionData set_charge_schedules(self, list[models.ChargeSchedule] schedules)
models.KamereonVehicleDetails details(self)
models.KamereonVehicleHvacStartActionData set_ac_stop(self)
None __init__(self, HomeAssistant hass, RenaultVehicle vehicle, models.KamereonVehicleDetails details, timedelta scan_interval)
models.KamereonVehicleHvacStartActionData set_ac_start(self, float temperature, datetime|None when=None)
None async_initialise(self)
DeviceInfo device_info(self)