Use EntityDescription - bmw_connected_drive (#56861)

This commit is contained in:
Marc Mueller 2021-10-12 11:46:23 +02:00 committed by GitHub
parent d44e323e95
commit c4f8c52df9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -1,4 +1,6 @@
"""Reads vehicle status from BMW connected drive portal.""" """Reads vehicle status from BMW connected drive portal."""
from __future__ import annotations
import logging import logging
from bimmer_connected.state import ChargingState, LockState from bimmer_connected.state import ChargingState, LockState
@ -8,6 +10,7 @@ from homeassistant.components.binary_sensor import (
DEVICE_CLASS_PLUG, DEVICE_CLASS_PLUG,
DEVICE_CLASS_PROBLEM, DEVICE_CLASS_PROBLEM,
BinarySensorEntity, BinarySensorEntity,
BinarySensorEntityDescription,
) )
from homeassistant.const import LENGTH_KILOMETERS from homeassistant.const import LENGTH_KILOMETERS
@ -16,89 +19,101 @@ from .const import CONF_ACCOUNT, DATA_ENTRIES
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SENSOR_TYPES = { SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = (
"lids": ["Doors", DEVICE_CLASS_OPENING, "mdi:car-door-lock"], BinarySensorEntityDescription(
"windows": ["Windows", DEVICE_CLASS_OPENING, "mdi:car-door"], key="lids",
"door_lock_state": ["Door lock state", "lock", "mdi:car-key"], name="Doors",
"lights_parking": ["Parking lights", "light", "mdi:car-parking-lights"], device_class=DEVICE_CLASS_OPENING,
"condition_based_services": [ icon="mdi:car-door-lock",
"Condition based services", ),
DEVICE_CLASS_PROBLEM, BinarySensorEntityDescription(
"mdi:wrench", key="windows",
], name="Windows",
"check_control_messages": [ device_class=DEVICE_CLASS_OPENING,
"Control messages", icon="mdi:car-door",
DEVICE_CLASS_PROBLEM, ),
"mdi:car-tire-alert", BinarySensorEntityDescription(
], key="door_lock_state",
} name="Door lock state",
device_class="lock",
SENSOR_TYPES_ELEC = { icon="mdi:car-key",
"charging_status": ["Charging status", "power", "mdi:ev-station"], ),
"connection_status": ["Connection status", DEVICE_CLASS_PLUG, "mdi:car-electric"], BinarySensorEntityDescription(
} key="lights_parking",
name="Parking lights",
SENSOR_TYPES_ELEC.update(SENSOR_TYPES) device_class="light",
icon="mdi:car-parking-lights",
),
BinarySensorEntityDescription(
key="condition_based_services",
name="Condition based services",
device_class=DEVICE_CLASS_PROBLEM,
icon="mdi:wrench",
),
BinarySensorEntityDescription(
key="check_control_messages",
name="Control messages",
device_class=DEVICE_CLASS_PROBLEM,
icon="mdi:car-tire-alert",
),
# electric
BinarySensorEntityDescription(
key="charging_status",
name="Charging status",
device_class="power",
icon="mdi:ev-station",
),
BinarySensorEntityDescription(
key="connection_status",
name="Connection status",
device_class=DEVICE_CLASS_PLUG,
icon="mdi:car-electric",
),
)
async def async_setup_entry(hass, config_entry, async_add_entities): async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the BMW ConnectedDrive binary sensors from config entry.""" """Set up the BMW ConnectedDrive binary sensors from config entry."""
account = hass.data[BMW_DOMAIN][DATA_ENTRIES][config_entry.entry_id][CONF_ACCOUNT] account = hass.data[BMW_DOMAIN][DATA_ENTRIES][config_entry.entry_id][CONF_ACCOUNT]
entities = []
for vehicle in account.account.vehicles: entities = [
if vehicle.has_hv_battery: BMWConnectedDriveSensor(account, vehicle, description)
_LOGGER.debug("BMW with a high voltage battery") for vehicle in account.account.vehicles
for key, value in sorted(SENSOR_TYPES_ELEC.items()): for description in SENSOR_TYPES
if key in vehicle.available_attributes: if description.key in vehicle.available_attributes
device = BMWConnectedDriveSensor( ]
account, vehicle, key, value[0], value[1], value[2]
)
entities.append(device)
elif vehicle.has_internal_combustion_engine:
_LOGGER.debug("BMW with an internal combustion engine")
for key, value in sorted(SENSOR_TYPES.items()):
if key in vehicle.available_attributes:
device = BMWConnectedDriveSensor(
account, vehicle, key, value[0], value[1], value[2]
)
entities.append(device)
async_add_entities(entities, True) async_add_entities(entities, True)
class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity): class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity):
"""Representation of a BMW vehicle binary sensor.""" """Representation of a BMW vehicle binary sensor."""
def __init__( def __init__(self, account, vehicle, description: BinarySensorEntityDescription):
self, account, vehicle, attribute: str, sensor_name, device_class, icon
):
"""Initialize sensor.""" """Initialize sensor."""
super().__init__(account, vehicle) super().__init__(account, vehicle)
self.entity_description = description
self._attribute = attribute self._attr_name = f"{vehicle.name} {description.key}"
self._attr_name = f"{vehicle.name} {attribute}" self._attr_unique_id = f"{vehicle.vin}-{description.key}"
self._attr_unique_id = f"{vehicle.vin}-{attribute}"
self._sensor_name = sensor_name
self._attr_device_class = device_class
self._attr_icon = icon
def update(self): def update(self):
"""Read new state data from the library.""" """Read new state data from the library."""
sensor_type = self.entity_description.key
vehicle_state = self._vehicle.state vehicle_state = self._vehicle.state
result = self._attrs.copy() result = self._attrs.copy()
# device class opening: On means open, Off means closed # device class opening: On means open, Off means closed
if self._attribute == "lids": if sensor_type == "lids":
_LOGGER.debug("Status of lid: %s", vehicle_state.all_lids_closed) _LOGGER.debug("Status of lid: %s", vehicle_state.all_lids_closed)
self._attr_is_on = not vehicle_state.all_lids_closed self._attr_is_on = not vehicle_state.all_lids_closed
for lid in vehicle_state.lids: for lid in vehicle_state.lids:
result[lid.name] = lid.state.value result[lid.name] = lid.state.value
elif self._attribute == "windows": elif sensor_type == "windows":
self._attr_is_on = not vehicle_state.all_windows_closed self._attr_is_on = not vehicle_state.all_windows_closed
for window in vehicle_state.windows: for window in vehicle_state.windows:
result[window.name] = window.state.value result[window.name] = window.state.value
# device class lock: On means unlocked, Off means locked # device class lock: On means unlocked, Off means locked
elif self._attribute == "door_lock_state": elif sensor_type == "door_lock_state":
# Possible values: LOCKED, SECURED, SELECTIVE_LOCKED, UNLOCKED # Possible values: LOCKED, SECURED, SELECTIVE_LOCKED, UNLOCKED
self._attr_is_on = vehicle_state.door_lock_state not in [ self._attr_is_on = vehicle_state.door_lock_state not in [
LockState.LOCKED, LockState.LOCKED,
@ -107,15 +122,15 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity):
result["door_lock_state"] = vehicle_state.door_lock_state.value result["door_lock_state"] = vehicle_state.door_lock_state.value
result["last_update_reason"] = vehicle_state.last_update_reason result["last_update_reason"] = vehicle_state.last_update_reason
# device class light: On means light detected, Off means no light # device class light: On means light detected, Off means no light
elif self._attribute == "lights_parking": elif sensor_type == "lights_parking":
self._attr_is_on = vehicle_state.are_parking_lights_on self._attr_is_on = vehicle_state.are_parking_lights_on
result["lights_parking"] = vehicle_state.parking_lights.value result["lights_parking"] = vehicle_state.parking_lights.value
# device class problem: On means problem detected, Off means no problem # device class problem: On means problem detected, Off means no problem
elif self._attribute == "condition_based_services": elif sensor_type == "condition_based_services":
self._attr_is_on = not vehicle_state.are_all_cbs_ok self._attr_is_on = not vehicle_state.are_all_cbs_ok
for report in vehicle_state.condition_based_services: for report in vehicle_state.condition_based_services:
result.update(self._format_cbs_report(report)) result.update(self._format_cbs_report(report))
elif self._attribute == "check_control_messages": elif sensor_type == "check_control_messages":
self._attr_is_on = vehicle_state.has_check_control_messages self._attr_is_on = vehicle_state.has_check_control_messages
check_control_messages = vehicle_state.check_control_messages check_control_messages = vehicle_state.check_control_messages
has_check_control_messages = vehicle_state.has_check_control_messages has_check_control_messages = vehicle_state.has_check_control_messages
@ -127,13 +142,13 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity):
else: else:
result["check_control_messages"] = "OK" result["check_control_messages"] = "OK"
# device class power: On means power detected, Off means no power # device class power: On means power detected, Off means no power
elif self._attribute == "charging_status": elif sensor_type == "charging_status":
self._attr_is_on = vehicle_state.charging_status in [ChargingState.CHARGING] self._attr_is_on = vehicle_state.charging_status in [ChargingState.CHARGING]
result["charging_status"] = vehicle_state.charging_status.value result["charging_status"] = vehicle_state.charging_status.value
result["last_charging_end_result"] = vehicle_state.last_charging_end_result result["last_charging_end_result"] = vehicle_state.last_charging_end_result
# device class plug: On means device is plugged in, # device class plug: On means device is plugged in,
# Off means device is unplugged # Off means device is unplugged
elif self._attribute == "connection_status": elif sensor_type == "connection_status":
self._attr_is_on = vehicle_state.connection_status == "CONNECTED" self._attr_is_on = vehicle_state.connection_status == "CONNECTED"
result["connection_status"] = vehicle_state.connection_status result["connection_status"] = vehicle_state.connection_status