Renault code quality improvements (#55454)

This commit is contained in:
epenet 2021-08-31 11:06:54 +02:00 committed by GitHub
parent f9225bad5f
commit 1849eae0ff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 58 additions and 64 deletions

View File

@ -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]):

View File

@ -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."""

View File

@ -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,
),
)

View File

@ -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