From a6b1dbefd4a3296d7cabee3c616f49c1e948c7fc Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Tue, 17 Aug 2021 00:21:06 +0200 Subject: [PATCH] Use EntityDescription - mitemp_bt (#54503) --- homeassistant/components/mitemp_bt/sensor.py | 124 +++++++++---------- 1 file changed, 57 insertions(+), 67 deletions(-) diff --git a/homeassistant/components/mitemp_bt/sensor.py b/homeassistant/components/mitemp_bt/sensor.py index 732beb11b3a..ed6c7f27b94 100644 --- a/homeassistant/components/mitemp_bt/sensor.py +++ b/homeassistant/components/mitemp_bt/sensor.py @@ -1,12 +1,19 @@ """Support for Xiaomi Mi Temp BLE environmental sensor.""" +from __future__ import annotations + import logging +from typing import Any import btlewrap from btlewrap.base import BluetoothBackendException from mitemp_bt import mitemp_bt_poller import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity +from homeassistant.components.sensor import ( + PLATFORM_SCHEMA, + SensorEntity, + SensorEntityDescription, +) from homeassistant.const import ( CONF_FORCE_UPDATE, CONF_MAC, @@ -44,18 +51,34 @@ DEFAULT_RETRIES = 2 DEFAULT_TIMEOUT = 10 -# Sensor types are defined like: Name, units -SENSOR_TYPES = { - "temperature": [DEVICE_CLASS_TEMPERATURE, "Temperature", TEMP_CELSIUS], - "humidity": [DEVICE_CLASS_HUMIDITY, "Humidity", PERCENTAGE], - "battery": [DEVICE_CLASS_BATTERY, "Battery", PERCENTAGE], -} +SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key="temperature", + name="Temperature", + device_class=DEVICE_CLASS_TEMPERATURE, + native_unit_of_measurement=TEMP_CELSIUS, + ), + SensorEntityDescription( + key="humidity", + name="Humidity", + device_class=DEVICE_CLASS_HUMIDITY, + native_unit_of_measurement=PERCENTAGE, + ), + SensorEntityDescription( + key="battery", + name="Battery", + device_class=DEVICE_CLASS_BATTERY, + native_unit_of_measurement=PERCENTAGE, + ), +) + +SENSOR_KEYS = [desc.key for desc in SENSOR_TYPES] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_MAC): cv.string, - vol.Optional(CONF_MONITORED_CONDITIONS, default=list(SENSOR_TYPES)): vol.All( - cv.ensure_list, [vol.In(SENSOR_TYPES)] + vol.Optional(CONF_MONITORED_CONDITIONS, default=SENSOR_KEYS): vol.All( + cv.ensure_list, [vol.In(SENSOR_KEYS)] ), vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_MEDIAN, default=DEFAULT_MEDIAN): cv.positive_int, @@ -73,79 +96,46 @@ def setup_platform(hass, config, add_entities, discovery_info=None): backend = BACKEND _LOGGER.debug("MiTempBt is using %s backend", backend.__name__) - cache = config.get(CONF_CACHE) + cache = config[CONF_CACHE] poller = mitemp_bt_poller.MiTempBtPoller( - config.get(CONF_MAC), + config[CONF_MAC], cache_timeout=cache, - adapter=config.get(CONF_ADAPTER), + adapter=config[CONF_ADAPTER], backend=backend, ) - force_update = config.get(CONF_FORCE_UPDATE) - median = config.get(CONF_MEDIAN) - poller.ble_timeout = config.get(CONF_TIMEOUT) - poller.retries = config.get(CONF_RETRIES) + prefix = config[CONF_NAME] + force_update = config[CONF_FORCE_UPDATE] + median = config[CONF_MEDIAN] + poller.ble_timeout = config[CONF_TIMEOUT] + poller.retries = config[CONF_RETRIES] - devs = [] + monitored_conditions = config[CONF_MONITORED_CONDITIONS] + entities = [ + MiTempBtSensor(poller, prefix, force_update, median, description) + for description in SENSOR_TYPES + if description.key in monitored_conditions + ] - for parameter in config[CONF_MONITORED_CONDITIONS]: - device = SENSOR_TYPES[parameter][0] - name = SENSOR_TYPES[parameter][1] - unit = SENSOR_TYPES[parameter][2] - - prefix = config.get(CONF_NAME) - if prefix: - name = f"{prefix} {name}" - - devs.append( - MiTempBtSensor(poller, parameter, device, name, unit, force_update, median) - ) - - add_entities(devs) + add_entities(entities) class MiTempBtSensor(SensorEntity): """Implementing the MiTempBt sensor.""" - def __init__(self, poller, parameter, device, name, unit, force_update, median): + def __init__( + self, poller, prefix, force_update, median, description: SensorEntityDescription + ): """Initialize the sensor.""" + self.entity_description = description self.poller = poller - self.parameter = parameter - self._device = device - self._unit = unit - self._name = name - self._state = None - self.data = [] - self._force_update = force_update + self.data: list[Any] = [] + self._attr_name = f"{prefix} {description.name}" + self._attr_force_update = force_update # Median is used to filter out outliers. median of 3 will filter # single outliers, while median of 5 will filter double outliers # Use median_count = 1 if no filtering is required. self.median_count = median - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def native_value(self): - """Return the state of the sensor.""" - return self._state - - @property - def native_unit_of_measurement(self): - """Return the units of measurement.""" - return self._unit - - @property - def device_class(self): - """Device class of this entity.""" - return self._device - - @property - def force_update(self): - """Force update.""" - return self._force_update - def update(self): """ Update current conditions. @@ -154,7 +144,7 @@ class MiTempBtSensor(SensorEntity): """ try: _LOGGER.debug("Polling data for %s", self.name) - data = self.poller.parameter_value(self.parameter) + data = self.poller.parameter_value(self.entity_description.key) except OSError as ioerr: _LOGGER.warning("Polling error %s", ioerr) return @@ -174,7 +164,7 @@ class MiTempBtSensor(SensorEntity): if self.data: self.data = self.data[1:] else: - self._state = None + self._attr_native_value = None return if len(self.data) > self.median_count: @@ -183,6 +173,6 @@ class MiTempBtSensor(SensorEntity): if len(self.data) == self.median_count: median = sorted(self.data)[int((self.median_count - 1) / 2)] _LOGGER.debug("Median is: %s", median) - self._state = median + self._attr_native_value = median else: _LOGGER.debug("Not yet enough data for median calculation")