From c4f8c52df9efc7e14822d7c40e68f307bed4c627 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 12 Oct 2021 11:46:23 +0200 Subject: [PATCH] Use EntityDescription - bmw_connected_drive (#56861) --- .../bmw_connected_drive/binary_sensor.py | 131 ++++++++++-------- 1 file changed, 73 insertions(+), 58 deletions(-) diff --git a/homeassistant/components/bmw_connected_drive/binary_sensor.py b/homeassistant/components/bmw_connected_drive/binary_sensor.py index 225ec5f7f99..d2d2aa9d42f 100644 --- a/homeassistant/components/bmw_connected_drive/binary_sensor.py +++ b/homeassistant/components/bmw_connected_drive/binary_sensor.py @@ -1,4 +1,6 @@ """Reads vehicle status from BMW connected drive portal.""" +from __future__ import annotations + import logging from bimmer_connected.state import ChargingState, LockState @@ -8,6 +10,7 @@ from homeassistant.components.binary_sensor import ( DEVICE_CLASS_PLUG, DEVICE_CLASS_PROBLEM, BinarySensorEntity, + BinarySensorEntityDescription, ) from homeassistant.const import LENGTH_KILOMETERS @@ -16,89 +19,101 @@ from .const import CONF_ACCOUNT, DATA_ENTRIES _LOGGER = logging.getLogger(__name__) -SENSOR_TYPES = { - "lids": ["Doors", DEVICE_CLASS_OPENING, "mdi:car-door-lock"], - "windows": ["Windows", DEVICE_CLASS_OPENING, "mdi:car-door"], - "door_lock_state": ["Door lock state", "lock", "mdi:car-key"], - "lights_parking": ["Parking lights", "light", "mdi:car-parking-lights"], - "condition_based_services": [ - "Condition based services", - DEVICE_CLASS_PROBLEM, - "mdi:wrench", - ], - "check_control_messages": [ - "Control messages", - DEVICE_CLASS_PROBLEM, - "mdi:car-tire-alert", - ], -} - -SENSOR_TYPES_ELEC = { - "charging_status": ["Charging status", "power", "mdi:ev-station"], - "connection_status": ["Connection status", DEVICE_CLASS_PLUG, "mdi:car-electric"], -} - -SENSOR_TYPES_ELEC.update(SENSOR_TYPES) +SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = ( + BinarySensorEntityDescription( + key="lids", + name="Doors", + device_class=DEVICE_CLASS_OPENING, + icon="mdi:car-door-lock", + ), + BinarySensorEntityDescription( + key="windows", + name="Windows", + device_class=DEVICE_CLASS_OPENING, + icon="mdi:car-door", + ), + BinarySensorEntityDescription( + key="door_lock_state", + name="Door lock state", + device_class="lock", + icon="mdi:car-key", + ), + BinarySensorEntityDescription( + key="lights_parking", + name="Parking lights", + 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): """Set up the BMW ConnectedDrive binary sensors from config entry.""" account = hass.data[BMW_DOMAIN][DATA_ENTRIES][config_entry.entry_id][CONF_ACCOUNT] - entities = [] - for vehicle in account.account.vehicles: - if vehicle.has_hv_battery: - _LOGGER.debug("BMW with a high voltage battery") - for key, value in sorted(SENSOR_TYPES_ELEC.items()): - if 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) + entities = [ + BMWConnectedDriveSensor(account, vehicle, description) + for vehicle in account.account.vehicles + for description in SENSOR_TYPES + if description.key in vehicle.available_attributes + ] async_add_entities(entities, True) class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity): """Representation of a BMW vehicle binary sensor.""" - def __init__( - self, account, vehicle, attribute: str, sensor_name, device_class, icon - ): + def __init__(self, account, vehicle, description: BinarySensorEntityDescription): """Initialize sensor.""" super().__init__(account, vehicle) + self.entity_description = description - self._attribute = attribute - self._attr_name = f"{vehicle.name} {attribute}" - self._attr_unique_id = f"{vehicle.vin}-{attribute}" - self._sensor_name = sensor_name - self._attr_device_class = device_class - self._attr_icon = icon + self._attr_name = f"{vehicle.name} {description.key}" + self._attr_unique_id = f"{vehicle.vin}-{description.key}" def update(self): """Read new state data from the library.""" + sensor_type = self.entity_description.key vehicle_state = self._vehicle.state result = self._attrs.copy() # 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) self._attr_is_on = not vehicle_state.all_lids_closed for lid in vehicle_state.lids: result[lid.name] = lid.state.value - elif self._attribute == "windows": + elif sensor_type == "windows": self._attr_is_on = not vehicle_state.all_windows_closed for window in vehicle_state.windows: result[window.name] = window.state.value # 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 self._attr_is_on = vehicle_state.door_lock_state not in [ LockState.LOCKED, @@ -107,15 +122,15 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity): result["door_lock_state"] = vehicle_state.door_lock_state.value result["last_update_reason"] = vehicle_state.last_update_reason # 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 result["lights_parking"] = vehicle_state.parking_lights.value # 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 for report in vehicle_state.condition_based_services: 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 check_control_messages = vehicle_state.check_control_messages has_check_control_messages = vehicle_state.has_check_control_messages @@ -127,13 +142,13 @@ class BMWConnectedDriveSensor(BMWConnectedDriveBaseEntity, BinarySensorEntity): else: result["check_control_messages"] = "OK" # 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] result["charging_status"] = vehicle_state.charging_status.value result["last_charging_end_result"] = vehicle_state.last_charging_end_result # device class plug: On means device is plugged in, # Off means device is unplugged - elif self._attribute == "connection_status": + elif sensor_type == "connection_status": self._attr_is_on = vehicle_state.connection_status == "CONNECTED" result["connection_status"] = vehicle_state.connection_status