Renault code quality improvements (#55313)
* Use constants * Drop entity_class for binary_sensor * Move data property from RenaultDataEntity to RenaultSensor * Update function description
This commit is contained in:
parent
259eeb3169
commit
adab367f0e
4 changed files with 40 additions and 33 deletions
|
@ -18,7 +18,7 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .renault_entities import RenaultDataEntity, RenaultEntityDescription, T
|
from .renault_entities import RenaultDataEntity, RenaultEntityDescription
|
||||||
from .renault_hub import RenaultHub
|
from .renault_hub import RenaultHub
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ from .renault_hub import RenaultHub
|
||||||
class RenaultBinarySensorRequiredKeysMixin:
|
class RenaultBinarySensorRequiredKeysMixin:
|
||||||
"""Mixin for required keys."""
|
"""Mixin for required keys."""
|
||||||
|
|
||||||
entity_class: type[RenaultBinarySensor]
|
on_key: str
|
||||||
on_value: StateType
|
on_value: StateType
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ async def async_setup_entry(
|
||||||
"""Set up the Renault entities from config entry."""
|
"""Set up the Renault entities from config entry."""
|
||||||
proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id]
|
proxy: RenaultHub = hass.data[DOMAIN][config_entry.entry_id]
|
||||||
entities: list[RenaultBinarySensor] = [
|
entities: list[RenaultBinarySensor] = [
|
||||||
description.entity_class(vehicle, description)
|
RenaultBinarySensor(vehicle, description)
|
||||||
for vehicle in proxy.vehicles.values()
|
for vehicle in proxy.vehicles.values()
|
||||||
for description in BINARY_SENSOR_TYPES
|
for description in BINARY_SENSOR_TYPES
|
||||||
if description.coordinator in vehicle.coordinators
|
if description.coordinator in vehicle.coordinators
|
||||||
|
@ -55,7 +55,9 @@ async def async_setup_entry(
|
||||||
async_add_entities(entities)
|
async_add_entities(entities)
|
||||||
|
|
||||||
|
|
||||||
class RenaultBinarySensor(RenaultDataEntity[T], BinarySensorEntity):
|
class RenaultBinarySensor(
|
||||||
|
RenaultDataEntity[KamereonVehicleBatteryStatusData], BinarySensorEntity
|
||||||
|
):
|
||||||
"""Mixin for binary sensor specific attributes."""
|
"""Mixin for binary sensor specific attributes."""
|
||||||
|
|
||||||
entity_description: RenaultBinarySensorEntityDescription
|
entity_description: RenaultBinarySensorEntityDescription
|
||||||
|
@ -63,26 +65,27 @@ class RenaultBinarySensor(RenaultDataEntity[T], BinarySensorEntity):
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool | None:
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if the binary sensor is on."""
|
"""Return true if the binary sensor is on."""
|
||||||
return self.data == self.entity_description.on_value
|
return (
|
||||||
|
self._get_data_attr(self.entity_description.on_key)
|
||||||
|
== self.entity_description.on_value
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
BINARY_SENSOR_TYPES: tuple[RenaultBinarySensorEntityDescription, ...] = (
|
BINARY_SENSOR_TYPES: tuple[RenaultBinarySensorEntityDescription, ...] = (
|
||||||
RenaultBinarySensorEntityDescription(
|
RenaultBinarySensorEntityDescription(
|
||||||
key="plugged_in",
|
key="plugged_in",
|
||||||
coordinator="battery",
|
coordinator="battery",
|
||||||
data_key="plugStatus",
|
|
||||||
device_class=DEVICE_CLASS_PLUG,
|
device_class=DEVICE_CLASS_PLUG,
|
||||||
entity_class=RenaultBinarySensor[KamereonVehicleBatteryStatusData],
|
|
||||||
name="Plugged In",
|
name="Plugged In",
|
||||||
|
on_key="plugStatus",
|
||||||
on_value=PlugState.PLUGGED.value,
|
on_value=PlugState.PLUGGED.value,
|
||||||
),
|
),
|
||||||
RenaultBinarySensorEntityDescription(
|
RenaultBinarySensorEntityDescription(
|
||||||
key="charging",
|
key="charging",
|
||||||
coordinator="battery",
|
coordinator="battery",
|
||||||
data_key="chargingStatus",
|
|
||||||
device_class=DEVICE_CLASS_BATTERY_CHARGING,
|
device_class=DEVICE_CLASS_BATTERY_CHARGING,
|
||||||
entity_class=RenaultBinarySensor[KamereonVehicleBatteryStatusData],
|
|
||||||
name="Charging",
|
name="Charging",
|
||||||
|
on_key="chargingStatus",
|
||||||
on_value=ChargeState.CHARGE_IN_PROGRESS.value,
|
on_value=ChargeState.CHARGE_IN_PROGRESS.value,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
"""Constants for the Renault component."""
|
"""Constants for the Renault component."""
|
||||||
|
from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
|
||||||
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
||||||
|
|
||||||
DOMAIN = "renault"
|
DOMAIN = "renault"
|
||||||
|
|
||||||
CONF_LOCALE = "locale"
|
CONF_LOCALE = "locale"
|
||||||
|
@ -7,8 +10,8 @@ CONF_KAMEREON_ACCOUNT_ID = "kamereon_account_id"
|
||||||
DEFAULT_SCAN_INTERVAL = 300 # 5 minutes
|
DEFAULT_SCAN_INTERVAL = 300 # 5 minutes
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
"binary_sensor",
|
BINARY_SENSOR_DOMAIN,
|
||||||
"sensor",
|
SENSOR_DOMAIN,
|
||||||
]
|
]
|
||||||
|
|
||||||
DEVICE_CLASS_PLUG_STATE = "renault__plug_state"
|
DEVICE_CLASS_PLUG_STATE = "renault__plug_state"
|
||||||
|
|
|
@ -19,15 +19,12 @@ class RenaultRequiredKeysMixin:
|
||||||
"""Mixin for required keys."""
|
"""Mixin for required keys."""
|
||||||
|
|
||||||
coordinator: str
|
coordinator: str
|
||||||
data_key: str
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class RenaultEntityDescription(EntityDescription, RenaultRequiredKeysMixin):
|
class RenaultEntityDescription(EntityDescription, RenaultRequiredKeysMixin):
|
||||||
"""Class describing Renault entities."""
|
"""Class describing Renault entities."""
|
||||||
|
|
||||||
requires_fuel: bool | None = None
|
|
||||||
|
|
||||||
|
|
||||||
ATTR_LAST_UPDATE = "last_update"
|
ATTR_LAST_UPDATE = "last_update"
|
||||||
|
|
||||||
|
@ -51,20 +48,17 @@ class RenaultDataEntity(CoordinatorEntity[Optional[T]], Entity):
|
||||||
self._attr_device_info = self.vehicle.device_info
|
self._attr_device_info = self.vehicle.device_info
|
||||||
self._attr_unique_id = f"{self.vehicle.details.vin}_{description.key}".lower()
|
self._attr_unique_id = f"{self.vehicle.details.vin}_{description.key}".lower()
|
||||||
|
|
||||||
@property
|
def _get_data_attr(self, key: str) -> StateType:
|
||||||
def data(self) -> StateType:
|
"""Return the attribute value from the coordinator data."""
|
||||||
"""Return the state of this entity."""
|
|
||||||
if self.coordinator.data is None:
|
if self.coordinator.data is None:
|
||||||
return None
|
return None
|
||||||
return cast(
|
return cast(StateType, getattr(self.coordinator.data, key))
|
||||||
StateType, getattr(self.coordinator.data, self.entity_description.data_key)
|
|
||||||
)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
def extra_state_attributes(self) -> Mapping[str, Any] | None:
|
||||||
"""Return the state attributes of this entity."""
|
"""Return the state attributes of this entity."""
|
||||||
if self.entity_description.coordinator == "battery" and self.coordinator.data:
|
if self.entity_description.coordinator == "battery":
|
||||||
timestamp = getattr(self.coordinator.data, "timestamp")
|
last_update = self._get_data_attr("timestamp")
|
||||||
if timestamp:
|
if last_update:
|
||||||
return {ATTR_LAST_UPDATE: timestamp}
|
return {ATTR_LAST_UPDATE: last_update}
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -50,6 +50,7 @@ from .renault_hub import RenaultHub
|
||||||
class RenaultSensorRequiredKeysMixin:
|
class RenaultSensorRequiredKeysMixin:
|
||||||
"""Mixin for required keys."""
|
"""Mixin for required keys."""
|
||||||
|
|
||||||
|
data_key: str
|
||||||
entity_class: type[RenaultSensor]
|
entity_class: type[RenaultSensor]
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,8 +60,9 @@ class RenaultSensorEntityDescription(
|
||||||
):
|
):
|
||||||
"""Class describing Renault sensor entities."""
|
"""Class describing Renault sensor entities."""
|
||||||
|
|
||||||
icon_lambda: Callable[[RenaultDataEntity[T]], str] | None = None
|
icon_lambda: Callable[[RenaultSensor[T]], str] | None = None
|
||||||
value_lambda: Callable[[RenaultDataEntity[T]], StateType] | None = None
|
requires_fuel: bool | None = None
|
||||||
|
value_lambda: Callable[[RenaultSensor[T]], StateType] | None = None
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
|
@ -85,6 +87,11 @@ class RenaultSensor(RenaultDataEntity[T], SensorEntity):
|
||||||
|
|
||||||
entity_description: RenaultSensorEntityDescription
|
entity_description: RenaultSensorEntityDescription
|
||||||
|
|
||||||
|
@property
|
||||||
|
def data(self) -> StateType:
|
||||||
|
"""Return the state of this entity."""
|
||||||
|
return self._get_data_attr(self.entity_description.data_key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icon(self) -> str | None:
|
def icon(self) -> str | None:
|
||||||
"""Icon handling."""
|
"""Icon handling."""
|
||||||
|
@ -102,49 +109,49 @@ class RenaultSensor(RenaultDataEntity[T], SensorEntity):
|
||||||
return self.entity_description.value_lambda(self)
|
return self.entity_description.value_lambda(self)
|
||||||
|
|
||||||
|
|
||||||
def _get_charge_mode_icon(entity: RenaultDataEntity[T]) -> str:
|
def _get_charge_mode_icon(entity: RenaultSensor[T]) -> str:
|
||||||
"""Return the icon of this entity."""
|
"""Return the icon of this entity."""
|
||||||
if entity.data == "schedule_mode":
|
if entity.data == "schedule_mode":
|
||||||
return "mdi:calendar-clock"
|
return "mdi:calendar-clock"
|
||||||
return "mdi:calendar-remove"
|
return "mdi:calendar-remove"
|
||||||
|
|
||||||
|
|
||||||
def _get_charging_power(entity: RenaultDataEntity[T]) -> StateType:
|
def _get_charging_power(entity: RenaultSensor[T]) -> StateType:
|
||||||
"""Return the charging_power of this entity."""
|
"""Return the charging_power of this entity."""
|
||||||
if entity.vehicle.details.reports_charging_power_in_watts():
|
if entity.vehicle.details.reports_charging_power_in_watts():
|
||||||
return cast(float, entity.data) / 1000
|
return cast(float, entity.data) / 1000
|
||||||
return entity.data
|
return entity.data
|
||||||
|
|
||||||
|
|
||||||
def _get_charge_state_formatted(entity: RenaultDataEntity[T]) -> str | None:
|
def _get_charge_state_formatted(entity: RenaultSensor[T]) -> str | None:
|
||||||
"""Return the charging_status of this entity."""
|
"""Return the charging_status of this entity."""
|
||||||
data = cast(KamereonVehicleBatteryStatusData, entity.coordinator.data)
|
data = cast(KamereonVehicleBatteryStatusData, entity.coordinator.data)
|
||||||
charging_status = data.get_charging_status() if data else None
|
charging_status = data.get_charging_status() if data else None
|
||||||
return charging_status.name.lower() if charging_status else None
|
return charging_status.name.lower() if charging_status else None
|
||||||
|
|
||||||
|
|
||||||
def _get_charge_state_icon(entity: RenaultDataEntity[T]) -> str:
|
def _get_charge_state_icon(entity: RenaultSensor[T]) -> str:
|
||||||
"""Return the icon of this entity."""
|
"""Return the icon of this entity."""
|
||||||
if entity.data == ChargeState.CHARGE_IN_PROGRESS.value:
|
if entity.data == ChargeState.CHARGE_IN_PROGRESS.value:
|
||||||
return "mdi:flash"
|
return "mdi:flash"
|
||||||
return "mdi:flash-off"
|
return "mdi:flash-off"
|
||||||
|
|
||||||
|
|
||||||
def _get_plug_state_formatted(entity: RenaultDataEntity[T]) -> str | None:
|
def _get_plug_state_formatted(entity: RenaultSensor[T]) -> str | None:
|
||||||
"""Return the plug_status of this entity."""
|
"""Return the plug_status of this entity."""
|
||||||
data = cast(KamereonVehicleBatteryStatusData, entity.coordinator.data)
|
data = cast(KamereonVehicleBatteryStatusData, entity.coordinator.data)
|
||||||
plug_status = data.get_plug_status() if data else None
|
plug_status = data.get_plug_status() if data else None
|
||||||
return plug_status.name.lower() if plug_status else None
|
return plug_status.name.lower() if plug_status else None
|
||||||
|
|
||||||
|
|
||||||
def _get_plug_state_icon(entity: RenaultDataEntity[T]) -> str:
|
def _get_plug_state_icon(entity: RenaultSensor[T]) -> str:
|
||||||
"""Return the icon of this entity."""
|
"""Return the icon of this entity."""
|
||||||
if entity.data == PlugState.PLUGGED.value:
|
if entity.data == PlugState.PLUGGED.value:
|
||||||
return "mdi:power-plug"
|
return "mdi:power-plug"
|
||||||
return "mdi:power-plug-off"
|
return "mdi:power-plug-off"
|
||||||
|
|
||||||
|
|
||||||
def _get_rounded_value(entity: RenaultDataEntity[T]) -> float:
|
def _get_rounded_value(entity: RenaultSensor[T]) -> float:
|
||||||
"""Return the icon of this entity."""
|
"""Return the icon of this entity."""
|
||||||
return round(cast(float, entity.data))
|
return round(cast(float, entity.data))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue