mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Use EntityDescription - bmw_connected_drive sensor (#57796)
This commit is contained in:
parent
4fd8b27ce6
commit
6ca23c67ff
@ -1,12 +1,16 @@
|
||||
"""Support for reading vehicle status from BMW connected drive portal."""
|
||||
from __future__ import annotations
|
||||
|
||||
from copy import copy
|
||||
from dataclasses import dataclass
|
||||
import logging
|
||||
|
||||
from bimmer_connected.const import SERVICE_ALL_TRIPS, SERVICE_LAST_TRIP, SERVICE_STATUS
|
||||
from bimmer_connected.state import ChargingState
|
||||
from bimmer_connected.vehicle import ConnectedDriveVehicle
|
||||
|
||||
from homeassistant.components.sensor import SensorEntity
|
||||
from homeassistant.components.sensor import SensorEntity, SensorEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
CONF_UNIT_SYSTEM_IMPERIAL,
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
@ -21,390 +25,399 @@ from homeassistant.const import (
|
||||
VOLUME_GALLONS,
|
||||
VOLUME_LITERS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.icon import icon_for_battery_level
|
||||
import homeassistant.util.dt as dt_util
|
||||
from homeassistant.util.unit_system import UnitSystem
|
||||
|
||||
from . import DOMAIN as BMW_DOMAIN, BMWConnectedDriveBaseEntity
|
||||
from . import (
|
||||
DOMAIN as BMW_DOMAIN,
|
||||
BMWConnectedDriveAccount,
|
||||
BMWConnectedDriveBaseEntity,
|
||||
)
|
||||
from .const import CONF_ACCOUNT, DATA_ENTRIES
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
SENSOR_TYPES: dict[str, tuple[str | None, str | None, str | None, str | None, bool]] = {
|
||||
# "<ID>": (<MDI_ICON>, <DEVICE_CLASS>, <UNIT_OF_MEASUREMENT (metric)>, <UNIT_OF_MEASUREMENT (imperial)>, <ENABLED_BY_DEFAULT>),
|
||||
|
||||
@dataclass
|
||||
class BMWSensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes BMW sensor entity."""
|
||||
|
||||
unit_metric: str | None = None
|
||||
unit_imperial: str | None = None
|
||||
|
||||
|
||||
SENSOR_TYPES: dict[str, BMWSensorEntityDescription] = {
|
||||
# --- Generic ---
|
||||
"charging_time_remaining": (
|
||||
"mdi:update",
|
||||
None,
|
||||
TIME_HOURS,
|
||||
TIME_HOURS,
|
||||
True,
|
||||
"charging_time_remaining": BMWSensorEntityDescription(
|
||||
key="charging_time_remaining",
|
||||
icon="mdi:update",
|
||||
unit_metric=TIME_HOURS,
|
||||
unit_imperial=TIME_HOURS,
|
||||
),
|
||||
"charging_status": (
|
||||
"mdi:battery-charging",
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
True,
|
||||
"charging_status": BMWSensorEntityDescription(
|
||||
key="charging_status",
|
||||
icon="mdi:battery-charging",
|
||||
),
|
||||
# No icon as this is dealt with directly as a special case in icon()
|
||||
"charging_level_hv": (
|
||||
None,
|
||||
None,
|
||||
PERCENTAGE,
|
||||
PERCENTAGE,
|
||||
True,
|
||||
"charging_level_hv": BMWSensorEntityDescription(
|
||||
key="charging_level_hv",
|
||||
unit_metric=PERCENTAGE,
|
||||
unit_imperial=PERCENTAGE,
|
||||
),
|
||||
# LastTrip attributes
|
||||
"date_utc": (
|
||||
None,
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
None,
|
||||
None,
|
||||
True,
|
||||
"date_utc": BMWSensorEntityDescription(
|
||||
key="date_utc",
|
||||
device_class=DEVICE_CLASS_TIMESTAMP,
|
||||
),
|
||||
"duration": (
|
||||
"mdi:timer-outline",
|
||||
None,
|
||||
TIME_MINUTES,
|
||||
TIME_MINUTES,
|
||||
True,
|
||||
"duration": BMWSensorEntityDescription(
|
||||
key="duration",
|
||||
icon="mdi:timer-outline",
|
||||
unit_metric=TIME_MINUTES,
|
||||
unit_imperial=TIME_MINUTES,
|
||||
),
|
||||
"electric_distance_ratio": (
|
||||
"mdi:percent-outline",
|
||||
None,
|
||||
PERCENTAGE,
|
||||
PERCENTAGE,
|
||||
False,
|
||||
"electric_distance_ratio": BMWSensorEntityDescription(
|
||||
key="electric_distance_ratio",
|
||||
icon="mdi:percent-outline",
|
||||
unit_metric=PERCENTAGE,
|
||||
unit_imperial=PERCENTAGE,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
# AllTrips attributes
|
||||
"battery_size_max": (
|
||||
"mdi:battery-charging-high",
|
||||
None,
|
||||
ENERGY_WATT_HOUR,
|
||||
ENERGY_WATT_HOUR,
|
||||
False,
|
||||
"battery_size_max": BMWSensorEntityDescription(
|
||||
key="battery_size_max",
|
||||
icon="mdi:battery-charging-high",
|
||||
unit_metric=ENERGY_WATT_HOUR,
|
||||
unit_imperial=ENERGY_WATT_HOUR,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"reset_date_utc": (
|
||||
None,
|
||||
DEVICE_CLASS_TIMESTAMP,
|
||||
None,
|
||||
None,
|
||||
False,
|
||||
"reset_date_utc": BMWSensorEntityDescription(
|
||||
key="reset_date_utc",
|
||||
device_class=DEVICE_CLASS_TIMESTAMP,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"saved_co2": (
|
||||
"mdi:tree-outline",
|
||||
None,
|
||||
MASS_KILOGRAMS,
|
||||
MASS_KILOGRAMS,
|
||||
False,
|
||||
"saved_co2": BMWSensorEntityDescription(
|
||||
key="saved_co2",
|
||||
icon="mdi:tree-outline",
|
||||
unit_metric=MASS_KILOGRAMS,
|
||||
unit_imperial=MASS_KILOGRAMS,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"saved_co2_green_energy": (
|
||||
"mdi:tree-outline",
|
||||
None,
|
||||
MASS_KILOGRAMS,
|
||||
MASS_KILOGRAMS,
|
||||
False,
|
||||
"saved_co2_green_energy": BMWSensorEntityDescription(
|
||||
key="saved_co2_green_energy",
|
||||
icon="mdi:tree-outline",
|
||||
unit_metric=MASS_KILOGRAMS,
|
||||
unit_imperial=MASS_KILOGRAMS,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
# --- Specific ---
|
||||
"mileage": (
|
||||
"mdi:speedometer",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"mileage": BMWSensorEntityDescription(
|
||||
key="mileage",
|
||||
icon="mdi:speedometer",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"remaining_range_total": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"remaining_range_total": BMWSensorEntityDescription(
|
||||
key="remaining_range_total",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"remaining_range_electric": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"remaining_range_electric": BMWSensorEntityDescription(
|
||||
key="remaining_range_electric",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"remaining_range_fuel": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"remaining_range_fuel": BMWSensorEntityDescription(
|
||||
key="remaining_range_fuel",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"max_range_electric": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"max_range_electric": BMWSensorEntityDescription(
|
||||
key="max_range_electric",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"remaining_fuel": (
|
||||
"mdi:gas-station",
|
||||
None,
|
||||
VOLUME_LITERS,
|
||||
VOLUME_GALLONS,
|
||||
True,
|
||||
"remaining_fuel": BMWSensorEntityDescription(
|
||||
key="remaining_fuel",
|
||||
icon="mdi:gas-station",
|
||||
unit_metric=VOLUME_LITERS,
|
||||
unit_imperial=VOLUME_GALLONS,
|
||||
),
|
||||
# LastTrip attributes
|
||||
"average_combined_consumption": (
|
||||
"mdi:flash",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
True,
|
||||
"average_combined_consumption": BMWSensorEntityDescription(
|
||||
key="average_combined_consumption",
|
||||
icon="mdi:flash",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
),
|
||||
"average_electric_consumption": (
|
||||
"mdi:power-plug-outline",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
True,
|
||||
"average_electric_consumption": BMWSensorEntityDescription(
|
||||
key="average_electric_consumption",
|
||||
icon="mdi:power-plug-outline",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
),
|
||||
"average_recuperation": (
|
||||
"mdi:recycle-variant",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
True,
|
||||
"average_recuperation": BMWSensorEntityDescription(
|
||||
key="average_recuperation",
|
||||
icon="mdi:recycle-variant",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
),
|
||||
"electric_distance": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"electric_distance": BMWSensorEntityDescription(
|
||||
key="electric_distance",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"saved_fuel": (
|
||||
"mdi:fuel",
|
||||
None,
|
||||
VOLUME_LITERS,
|
||||
VOLUME_GALLONS,
|
||||
False,
|
||||
"saved_fuel": BMWSensorEntityDescription(
|
||||
key="saved_fuel",
|
||||
icon="mdi:fuel",
|
||||
unit_metric=VOLUME_LITERS,
|
||||
unit_imperial=VOLUME_GALLONS,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"total_distance": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"total_distance": BMWSensorEntityDescription(
|
||||
key="total_distance",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
# AllTrips attributes
|
||||
"average_combined_consumption_community_average": (
|
||||
"mdi:flash",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_combined_consumption_community_average": BMWSensorEntityDescription(
|
||||
key="average_combined_consumption_community_average",
|
||||
icon="mdi:flash",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_combined_consumption_community_high": (
|
||||
"mdi:flash",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_combined_consumption_community_high": BMWSensorEntityDescription(
|
||||
key="average_combined_consumption_community_high",
|
||||
icon="mdi:flash",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_combined_consumption_community_low": (
|
||||
"mdi:flash",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_combined_consumption_community_low": BMWSensorEntityDescription(
|
||||
key="average_combined_consumption_community_low",
|
||||
icon="mdi:flash",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_combined_consumption_user_average": (
|
||||
"mdi:flash",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
True,
|
||||
"average_combined_consumption_user_average": BMWSensorEntityDescription(
|
||||
key="average_combined_consumption_user_average",
|
||||
icon="mdi:flash",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
),
|
||||
"average_electric_consumption_community_average": (
|
||||
"mdi:power-plug-outline",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_electric_consumption_community_average": BMWSensorEntityDescription(
|
||||
key="average_electric_consumption_community_average",
|
||||
icon="mdi:power-plug-outline",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_electric_consumption_community_high": (
|
||||
"mdi:power-plug-outline",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_electric_consumption_community_high": BMWSensorEntityDescription(
|
||||
key="average_electric_consumption_community_high",
|
||||
icon="mdi:power-plug-outline",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_electric_consumption_community_low": (
|
||||
"mdi:power-plug-outline",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_electric_consumption_community_low": BMWSensorEntityDescription(
|
||||
key="average_electric_consumption_community_low",
|
||||
icon="mdi:power-plug-outline",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_electric_consumption_user_average": (
|
||||
"mdi:power-plug-outline",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
True,
|
||||
"average_electric_consumption_user_average": BMWSensorEntityDescription(
|
||||
key="average_electric_consumption_user_average",
|
||||
icon="mdi:power-plug-outline",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
),
|
||||
"average_recuperation_community_average": (
|
||||
"mdi:recycle-variant",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_recuperation_community_average": BMWSensorEntityDescription(
|
||||
key="average_recuperation_community_average",
|
||||
icon="mdi:recycle-variant",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_recuperation_community_high": (
|
||||
"mdi:recycle-variant",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_recuperation_community_high": BMWSensorEntityDescription(
|
||||
key="average_recuperation_community_high",
|
||||
icon="mdi:recycle-variant",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_recuperation_community_low": (
|
||||
"mdi:recycle-variant",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
False,
|
||||
"average_recuperation_community_low": BMWSensorEntityDescription(
|
||||
key="average_recuperation_community_low",
|
||||
icon="mdi:recycle-variant",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"average_recuperation_user_average": (
|
||||
"mdi:recycle-variant",
|
||||
None,
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
True,
|
||||
"average_recuperation_user_average": BMWSensorEntityDescription(
|
||||
key="average_recuperation_user_average",
|
||||
icon="mdi:recycle-variant",
|
||||
unit_metric=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_KILOMETERS}",
|
||||
unit_imperial=f"{ENERGY_KILO_WATT_HOUR}/100{LENGTH_MILES}",
|
||||
),
|
||||
"chargecycle_range_community_average": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"chargecycle_range_community_average": BMWSensorEntityDescription(
|
||||
key="chargecycle_range_community_average",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"chargecycle_range_community_high": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"chargecycle_range_community_high": BMWSensorEntityDescription(
|
||||
key="chargecycle_range_community_high",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"chargecycle_range_community_low": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"chargecycle_range_community_low": BMWSensorEntityDescription(
|
||||
key="chargecycle_range_community_low",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"chargecycle_range_user_average": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"chargecycle_range_user_average": BMWSensorEntityDescription(
|
||||
key="chargecycle_range_user_average",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"chargecycle_range_user_current_charge_cycle": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"chargecycle_range_user_current_charge_cycle": BMWSensorEntityDescription(
|
||||
key="chargecycle_range_user_current_charge_cycle",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"chargecycle_range_user_high": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
True,
|
||||
"chargecycle_range_user_high": BMWSensorEntityDescription(
|
||||
key="chargecycle_range_user_high",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
),
|
||||
"total_electric_distance_community_average": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"total_electric_distance_community_average": BMWSensorEntityDescription(
|
||||
key="total_electric_distance_community_average",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"total_electric_distance_community_high": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"total_electric_distance_community_high": BMWSensorEntityDescription(
|
||||
key="total_electric_distance_community_high",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"total_electric_distance_community_low": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"total_electric_distance_community_low": BMWSensorEntityDescription(
|
||||
key="total_electric_distance_community_low",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"total_electric_distance_user_average": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"total_electric_distance_user_average": BMWSensorEntityDescription(
|
||||
key="total_electric_distance_user_average",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"total_electric_distance_user_total": (
|
||||
"mdi:map-marker-distance",
|
||||
None,
|
||||
LENGTH_KILOMETERS,
|
||||
LENGTH_MILES,
|
||||
False,
|
||||
"total_electric_distance_user_total": BMWSensorEntityDescription(
|
||||
key="total_electric_distance_user_total",
|
||||
icon="mdi:map-marker-distance",
|
||||
unit_metric=LENGTH_KILOMETERS,
|
||||
unit_imperial=LENGTH_MILES,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
"total_saved_fuel": (
|
||||
"mdi:fuel",
|
||||
None,
|
||||
VOLUME_LITERS,
|
||||
VOLUME_GALLONS,
|
||||
False,
|
||||
"total_saved_fuel": BMWSensorEntityDescription(
|
||||
key="total_saved_fuel",
|
||||
icon="mdi:fuel",
|
||||
unit_metric=VOLUME_LITERS,
|
||||
unit_imperial=VOLUME_GALLONS,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
DEFAULT_BMW_DESCRIPTION = BMWSensorEntityDescription(
|
||||
key="",
|
||||
entity_registry_enabled_default=True,
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant,
|
||||
config_entry: ConfigEntry,
|
||||
async_add_entities: AddEntitiesCallback,
|
||||
) -> None:
|
||||
"""Set up the BMW ConnectedDrive sensors from config entry."""
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
account = hass.data[BMW_DOMAIN][DATA_ENTRIES][config_entry.entry_id][CONF_ACCOUNT]
|
||||
entities = []
|
||||
unit_system = hass.config.units
|
||||
account: BMWConnectedDriveAccount = hass.data[BMW_DOMAIN][DATA_ENTRIES][
|
||||
config_entry.entry_id
|
||||
][CONF_ACCOUNT]
|
||||
entities: list[BMWConnectedDriveSensor] = []
|
||||
|
||||
for vehicle in account.account.vehicles:
|
||||
for service in vehicle.available_state_services:
|
||||
if service == SERVICE_STATUS:
|
||||
for attribute_name in vehicle.drive_train_attributes:
|
||||
if attribute_name in vehicle.available_attributes:
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass, account, vehicle, attribute_name
|
||||
entities.extend(
|
||||
[
|
||||
BMWConnectedDriveSensor(
|
||||
account, vehicle, description, unit_system
|
||||
)
|
||||
entities.append(device)
|
||||
for attribute_name in vehicle.drive_train_attributes
|
||||
if attribute_name in vehicle.available_attributes
|
||||
and (description := SENSOR_TYPES.get(attribute_name))
|
||||
]
|
||||
)
|
||||
if service == SERVICE_LAST_TRIP:
|
||||
for attribute_name in vehicle.state.last_trip.available_attributes:
|
||||
if attribute_name == "date":
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass,
|
||||
entities.extend(
|
||||
[
|
||||
BMWConnectedDriveSensor(
|
||||
account, vehicle, description, unit_system, service
|
||||
)
|
||||
for attribute_name in vehicle.state.last_trip.available_attributes
|
||||
if attribute_name != "date"
|
||||
and (description := SENSOR_TYPES.get(attribute_name))
|
||||
]
|
||||
)
|
||||
if "date" in vehicle.state.last_trip.available_attributes:
|
||||
entities.append(
|
||||
BMWConnectedDriveSensor(
|
||||
account,
|
||||
vehicle,
|
||||
"date_utc",
|
||||
SENSOR_TYPES["date_utc"],
|
||||
unit_system,
|
||||
service,
|
||||
)
|
||||
entities.append(device)
|
||||
else:
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass, account, vehicle, attribute_name, service
|
||||
)
|
||||
entities.append(device)
|
||||
)
|
||||
if service == SERVICE_ALL_TRIPS:
|
||||
for attribute_name in vehicle.state.all_trips.available_attributes:
|
||||
if attribute_name == "reset_date":
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass,
|
||||
account,
|
||||
vehicle,
|
||||
"reset_date_utc",
|
||||
service,
|
||||
entities.append(
|
||||
BMWConnectedDriveSensor(
|
||||
account,
|
||||
vehicle,
|
||||
SENSOR_TYPES["reset_date_utc"],
|
||||
unit_system,
|
||||
service,
|
||||
)
|
||||
)
|
||||
entities.append(device)
|
||||
elif attribute_name in (
|
||||
"average_combined_consumption",
|
||||
"average_electric_consumption",
|
||||
@ -412,45 +425,60 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
"chargecycle_range",
|
||||
"total_electric_distance",
|
||||
):
|
||||
for attr in (
|
||||
"community_average",
|
||||
"community_high",
|
||||
"community_low",
|
||||
"user_average",
|
||||
):
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass,
|
||||
entities.extend(
|
||||
[
|
||||
BMWConnectedDriveSensor(
|
||||
account,
|
||||
vehicle,
|
||||
SENSOR_TYPES[f"{attribute_name}_{attr}"],
|
||||
unit_system,
|
||||
service,
|
||||
)
|
||||
for attr in (
|
||||
"community_average",
|
||||
"community_high",
|
||||
"community_low",
|
||||
"user_average",
|
||||
)
|
||||
]
|
||||
)
|
||||
if attribute_name == "chargecycle_range":
|
||||
entities.extend(
|
||||
BMWConnectedDriveSensor(
|
||||
account,
|
||||
vehicle,
|
||||
SENSOR_TYPES[f"{attribute_name}_{attr}"],
|
||||
unit_system,
|
||||
service,
|
||||
)
|
||||
for attr in ("user_current_charge_cycle", "user_high")
|
||||
)
|
||||
elif attribute_name == "total_electric_distance":
|
||||
entities.extend(
|
||||
[
|
||||
BMWConnectedDriveSensor(
|
||||
account,
|
||||
vehicle,
|
||||
SENSOR_TYPES[f"{attribute_name}_{attr}"],
|
||||
unit_system,
|
||||
service,
|
||||
)
|
||||
for attr in ("user_total",)
|
||||
]
|
||||
)
|
||||
else:
|
||||
if (description := SENSOR_TYPES.get(attribute_name)) is None:
|
||||
description = copy(DEFAULT_BMW_DESCRIPTION)
|
||||
description.key = attribute_name
|
||||
entities.append(
|
||||
BMWConnectedDriveSensor(
|
||||
account,
|
||||
vehicle,
|
||||
f"{attribute_name}_{attr}",
|
||||
description,
|
||||
unit_system,
|
||||
service,
|
||||
)
|
||||
entities.append(device)
|
||||
if attribute_name == "chargecycle_range":
|
||||
for attr in ("user_current_charge_cycle", "user_high"):
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass,
|
||||
account,
|
||||
vehicle,
|
||||
f"{attribute_name}_{attr}",
|
||||
service,
|
||||
)
|
||||
entities.append(device)
|
||||
if attribute_name == "total_electric_distance":
|
||||
for attr in ("user_total",):
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass,
|
||||
account,
|
||||
vehicle,
|
||||
f"{attribute_name}_{attr}",
|
||||
service,
|
||||
)
|
||||
entities.append(device)
|
||||
else:
|
||||
device = BMWConnectedDriveSensor(
|
||||
hass, account, vehicle, attribute_name, service
|
||||
)
|
||||
entities.append(device)
|
||||
|
||||
async_add_entities(entities, True)
|
||||
|
||||
@ -458,52 +486,57 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
|
||||
"""Representation of a BMW vehicle sensor."""
|
||||
|
||||
def __init__(self, hass, account, vehicle, attribute: str, service=None):
|
||||
entity_description: BMWSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
account: BMWConnectedDriveAccount,
|
||||
vehicle: ConnectedDriveVehicle,
|
||||
description: BMWSensorEntityDescription,
|
||||
unit_system: UnitSystem,
|
||||
service: str | None = None,
|
||||
) -> None:
|
||||
"""Initialize BMW vehicle sensor."""
|
||||
super().__init__(account, vehicle)
|
||||
self.entity_description = description
|
||||
|
||||
self._attribute = attribute
|
||||
self._service = service
|
||||
if service:
|
||||
self._attr_name = f"{vehicle.name} {service.lower()}_{attribute}"
|
||||
self._attr_unique_id = f"{vehicle.vin}-{service.lower()}-{attribute}"
|
||||
self._attr_name = f"{vehicle.name} {service.lower()}_{description.key}"
|
||||
self._attr_unique_id = f"{vehicle.vin}-{service.lower()}-{description.key}"
|
||||
else:
|
||||
self._attr_name = f"{vehicle.name} {attribute}"
|
||||
self._attr_unique_id = f"{vehicle.vin}-{attribute}"
|
||||
self._attribute_info = SENSOR_TYPES.get(
|
||||
attribute, (None, None, None, None, True)
|
||||
)
|
||||
self._attr_entity_registry_enabled_default = self._attribute_info[4]
|
||||
self._attr_icon = self._attribute_info[0]
|
||||
self._attr_device_class = self._attribute_info[1]
|
||||
if hass.config.units.name == CONF_UNIT_SYSTEM_IMPERIAL:
|
||||
self._attr_native_unit_of_measurement = self._attribute_info[3]
|
||||
self._attr_name = f"{vehicle.name} {description.key}"
|
||||
self._attr_unique_id = f"{vehicle.vin}-{description.key}"
|
||||
|
||||
if unit_system.name == CONF_UNIT_SYSTEM_IMPERIAL:
|
||||
self._attr_native_unit_of_measurement = description.unit_imperial
|
||||
else:
|
||||
self._attr_native_unit_of_measurement = self._attribute_info[2]
|
||||
self._attr_native_unit_of_measurement = description.unit_metric
|
||||
|
||||
def update(self) -> None:
|
||||
"""Read new state data from the library."""
|
||||
_LOGGER.debug("Updating %s", self._vehicle.name)
|
||||
vehicle_state = self._vehicle.state
|
||||
if self._attribute == "charging_status":
|
||||
self._attr_native_value = getattr(vehicle_state, self._attribute).value
|
||||
sensor_key = self.entity_description.key
|
||||
if sensor_key == "charging_status":
|
||||
self._attr_native_value = getattr(vehicle_state, sensor_key).value
|
||||
elif self.unit_of_measurement == VOLUME_GALLONS:
|
||||
value = getattr(vehicle_state, self._attribute)
|
||||
value = getattr(vehicle_state, sensor_key)
|
||||
value_converted = self.hass.config.units.volume(value, VOLUME_LITERS)
|
||||
self._attr_native_value = round(value_converted)
|
||||
elif self.unit_of_measurement == LENGTH_MILES:
|
||||
value = getattr(vehicle_state, self._attribute)
|
||||
value = getattr(vehicle_state, sensor_key)
|
||||
value_converted = self.hass.config.units.length(value, LENGTH_KILOMETERS)
|
||||
self._attr_native_value = round(value_converted)
|
||||
elif self._service is None:
|
||||
self._attr_native_value = getattr(vehicle_state, self._attribute)
|
||||
self._attr_native_value = getattr(vehicle_state, sensor_key)
|
||||
elif self._service == SERVICE_LAST_TRIP:
|
||||
vehicle_last_trip = self._vehicle.state.last_trip
|
||||
if self._attribute == "date_utc":
|
||||
if sensor_key == "date_utc":
|
||||
date_str = getattr(vehicle_last_trip, "date")
|
||||
self._attr_native_value = dt_util.parse_datetime(date_str).isoformat()
|
||||
else:
|
||||
self._attr_native_value = getattr(vehicle_last_trip, self._attribute)
|
||||
self._attr_native_value = getattr(vehicle_last_trip, sensor_key)
|
||||
elif self._service == SERVICE_ALL_TRIPS:
|
||||
vehicle_all_trips = self._vehicle.state.all_trips
|
||||
for attribute in (
|
||||
@ -513,21 +546,21 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, SensorEntity):
|
||||
"chargecycle_range",
|
||||
"total_electric_distance",
|
||||
):
|
||||
if self._attribute.startswith(f"{attribute}_"):
|
||||
if sensor_key.startswith(f"{attribute}_"):
|
||||
attr = getattr(vehicle_all_trips, attribute)
|
||||
sub_attr = self._attribute.replace(f"{attribute}_", "")
|
||||
sub_attr = sensor_key.replace(f"{attribute}_", "")
|
||||
self._attr_native_value = getattr(attr, sub_attr)
|
||||
return
|
||||
if self._attribute == "reset_date_utc":
|
||||
if sensor_key == "reset_date_utc":
|
||||
date_str = getattr(vehicle_all_trips, "reset_date")
|
||||
self._attr_native_value = dt_util.parse_datetime(date_str).isoformat()
|
||||
else:
|
||||
self._attr_native_value = getattr(vehicle_all_trips, self._attribute)
|
||||
self._attr_native_value = getattr(vehicle_all_trips, sensor_key)
|
||||
|
||||
vehicle_state = self._vehicle.state
|
||||
charging_state = vehicle_state.charging_status in [ChargingState.CHARGING]
|
||||
|
||||
if self._attribute == "charging_level_hv":
|
||||
if sensor_key == "charging_level_hv":
|
||||
self._attr_icon = icon_for_battery_level(
|
||||
battery_level=vehicle_state.charging_level_hv, charging=charging_state
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user