mirror of
https://github.com/home-assistant/core.git
synced 2025-07-18 18:57:06 +00:00
Renault code quality improvements (#55454)
This commit is contained in:
parent
f9225bad5f
commit
1849eae0ff
@ -11,11 +11,12 @@ from renault_api.kamereon.exceptions import (
|
||||
KamereonResponseException,
|
||||
NotSupportedException,
|
||||
)
|
||||
from renault_api.kamereon.models import KamereonVehicleDataAttributes
|
||||
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||
|
||||
T = TypeVar("T")
|
||||
T = TypeVar("T", bound=KamereonVehicleDataAttributes)
|
||||
|
||||
|
||||
class RenaultDataUpdateCoordinator(DataUpdateCoordinator[T]):
|
||||
|
@ -3,14 +3,13 @@ from __future__ import annotations
|
||||
|
||||
from collections.abc import Mapping
|
||||
from dataclasses import dataclass
|
||||
from typing import Any, Optional, TypeVar, cast
|
||||
|
||||
from renault_api.kamereon.models import KamereonVehicleDataAttributes
|
||||
from typing import Any, Optional, cast
|
||||
|
||||
from homeassistant.helpers.entity import Entity, EntityDescription
|
||||
from homeassistant.helpers.typing import StateType
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
|
||||
from .renault_coordinator import T
|
||||
from .renault_vehicle import RenaultVehicleProxy
|
||||
|
||||
|
||||
@ -28,8 +27,6 @@ class RenaultEntityDescription(EntityDescription, RenaultRequiredKeysMixin):
|
||||
|
||||
ATTR_LAST_UPDATE = "last_update"
|
||||
|
||||
T = TypeVar("T", bound=KamereonVehicleDataAttributes)
|
||||
|
||||
|
||||
class RenaultDataEntity(CoordinatorEntity[Optional[T]], Entity):
|
||||
"""Implementation of a Renault entity with a data coordinator."""
|
||||
|
@ -2,9 +2,11 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Awaitable
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import cast
|
||||
from typing import Callable, cast
|
||||
|
||||
from renault_api.kamereon import models
|
||||
from renault_api.renault_vehicle import RenaultVehicle
|
||||
@ -25,6 +27,20 @@ from .renault_coordinator import RenaultDataUpdateCoordinator
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@dataclass
|
||||
class RenaultCoordinatorDescription:
|
||||
"""Class describing Renault coordinators."""
|
||||
|
||||
endpoint: str
|
||||
key: str
|
||||
update_method: Callable[
|
||||
[RenaultVehicle],
|
||||
Callable[[], Awaitable[models.KamereonVehicleDataAttributes]],
|
||||
]
|
||||
# Optional keys
|
||||
requires_electricity: bool = False
|
||||
|
||||
|
||||
class RenaultVehicleProxy:
|
||||
"""Handle vehicle communication with Renault servers."""
|
||||
|
||||
@ -61,48 +77,23 @@ class RenaultVehicleProxy:
|
||||
return self._device_info
|
||||
|
||||
async def async_initialise(self) -> None:
|
||||
"""Load available sensors."""
|
||||
if await self.endpoint_available("cockpit"):
|
||||
self.coordinators["cockpit"] = RenaultDataUpdateCoordinator(
|
||||
"""Load available coordinators."""
|
||||
self.coordinators = {
|
||||
coord.key: RenaultDataUpdateCoordinator(
|
||||
self.hass,
|
||||
LOGGER,
|
||||
# Name of the data. For logging purposes.
|
||||
name=f"{self.details.vin} cockpit",
|
||||
update_method=self.get_cockpit,
|
||||
name=f"{self.details.vin} {coord.key}",
|
||||
update_method=coord.update_method(self._vehicle),
|
||||
# Polling interval. Will only be polled if there are subscribers.
|
||||
update_interval=self._scan_interval,
|
||||
)
|
||||
if await self.endpoint_available("hvac-status"):
|
||||
self.coordinators["hvac_status"] = RenaultDataUpdateCoordinator(
|
||||
self.hass,
|
||||
LOGGER,
|
||||
# Name of the data. For logging purposes.
|
||||
name=f"{self.details.vin} hvac_status",
|
||||
update_method=self.get_hvac_status,
|
||||
# Polling interval. Will only be polled if there are subscribers.
|
||||
update_interval=self._scan_interval,
|
||||
for coord in COORDINATORS
|
||||
if (
|
||||
self.details.supports_endpoint(coord.endpoint)
|
||||
and (not coord.requires_electricity or self.details.uses_electricity())
|
||||
)
|
||||
if self.details.uses_electricity():
|
||||
if await self.endpoint_available("battery-status"):
|
||||
self.coordinators["battery"] = RenaultDataUpdateCoordinator(
|
||||
self.hass,
|
||||
LOGGER,
|
||||
# Name of the data. For logging purposes.
|
||||
name=f"{self.details.vin} battery",
|
||||
update_method=self.get_battery_status,
|
||||
# Polling interval. Will only be polled if there are subscribers.
|
||||
update_interval=self._scan_interval,
|
||||
)
|
||||
if await self.endpoint_available("charge-mode"):
|
||||
self.coordinators["charge_mode"] = RenaultDataUpdateCoordinator(
|
||||
self.hass,
|
||||
LOGGER,
|
||||
# Name of the data. For logging purposes.
|
||||
name=f"{self.details.vin} charge_mode",
|
||||
update_method=self.get_charge_mode,
|
||||
# Polling interval. Will only be polled if there are subscribers.
|
||||
update_interval=self._scan_interval,
|
||||
)
|
||||
}
|
||||
# Check all coordinators
|
||||
await asyncio.gather(
|
||||
*(
|
||||
@ -130,24 +121,28 @@ class RenaultVehicleProxy:
|
||||
)
|
||||
del self.coordinators[key]
|
||||
|
||||
async def endpoint_available(self, endpoint: str) -> bool:
|
||||
"""Ensure the endpoint is available to avoid unnecessary queries."""
|
||||
return await self._vehicle.supports_endpoint(
|
||||
endpoint
|
||||
) and await self._vehicle.has_contract_for_endpoint(endpoint)
|
||||
|
||||
async def get_battery_status(self) -> models.KamereonVehicleBatteryStatusData:
|
||||
"""Get battery status information from vehicle."""
|
||||
return await self._vehicle.get_battery_status()
|
||||
|
||||
async def get_charge_mode(self) -> models.KamereonVehicleChargeModeData:
|
||||
"""Get charge mode information from vehicle."""
|
||||
return await self._vehicle.get_charge_mode()
|
||||
|
||||
async def get_cockpit(self) -> models.KamereonVehicleCockpitData:
|
||||
"""Get cockpit information from vehicle."""
|
||||
return await self._vehicle.get_cockpit()
|
||||
|
||||
async def get_hvac_status(self) -> models.KamereonVehicleHvacStatusData:
|
||||
"""Get hvac status information from vehicle."""
|
||||
return await self._vehicle.get_hvac_status()
|
||||
COORDINATORS: tuple[RenaultCoordinatorDescription, ...] = (
|
||||
RenaultCoordinatorDescription(
|
||||
endpoint="cockpit",
|
||||
key="cockpit",
|
||||
update_method=lambda x: x.get_cockpit,
|
||||
),
|
||||
RenaultCoordinatorDescription(
|
||||
endpoint="hvac-status",
|
||||
key="hvac_status",
|
||||
update_method=lambda x: x.get_hvac_status,
|
||||
),
|
||||
RenaultCoordinatorDescription(
|
||||
endpoint="battery-status",
|
||||
key="battery",
|
||||
requires_electricity=True,
|
||||
update_method=lambda x: x.get_battery_status,
|
||||
),
|
||||
RenaultCoordinatorDescription(
|
||||
endpoint="charge-mode",
|
||||
key="charge_mode",
|
||||
requires_electricity=True,
|
||||
update_method=lambda x: x.get_charge_mode,
|
||||
),
|
||||
)
|
||||
|
@ -42,7 +42,8 @@ from .const import (
|
||||
DEVICE_CLASS_PLUG_STATE,
|
||||
DOMAIN,
|
||||
)
|
||||
from .renault_entities import RenaultDataEntity, RenaultEntityDescription, T
|
||||
from .renault_coordinator import T
|
||||
from .renault_entities import RenaultDataEntity, RenaultEntityDescription
|
||||
from .renault_hub import RenaultHub
|
||||
|
||||
|
||||
@ -61,7 +62,7 @@ class RenaultSensorEntityDescription(
|
||||
"""Class describing Renault sensor entities."""
|
||||
|
||||
icon_lambda: Callable[[RenaultSensor[T]], str] | None = None
|
||||
requires_fuel: bool | None = None
|
||||
requires_fuel: bool = False
|
||||
value_lambda: Callable[[RenaultSensor[T]], StateType] | None = None
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user