From ebaae8d2bf9982ab78eb92cb9699338587214738 Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sun, 15 Aug 2021 13:49:29 +0200 Subject: [PATCH] Add sensor platform for Xiaomi Miio fans (#54564) --- .../components/xiaomi_miio/__init__.py | 9 +- homeassistant/components/xiaomi_miio/const.py | 4 +- homeassistant/components/xiaomi_miio/fan.py | 70 ------- .../components/xiaomi_miio/sensor.py | 193 +++++++++++++++--- 4 files changed, 174 insertions(+), 102 deletions(-) diff --git a/homeassistant/components/xiaomi_miio/__init__.py b/homeassistant/components/xiaomi_miio/__init__.py index faff2194948..122c42c6589 100644 --- a/homeassistant/components/xiaomi_miio/__init__.py +++ b/homeassistant/components/xiaomi_miio/__init__.py @@ -31,7 +31,6 @@ from .const import ( KEY_DEVICE, MODELS_AIR_MONITOR, MODELS_FAN, - MODELS_FAN_MIIO, MODELS_HUMIDIFIER, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, @@ -47,7 +46,7 @@ _LOGGER = logging.getLogger(__name__) GATEWAY_PLATFORMS = ["alarm_control_panel", "light", "sensor", "switch"] SWITCH_PLATFORMS = ["switch"] -FAN_PLATFORMS = ["fan"] +FAN_PLATFORMS = ["fan", "sensor"] HUMIDIFIER_PLATFORMS = [ "binary_sensor", "humidifier", @@ -120,11 +119,7 @@ async def async_create_miio_device_and_coordinator( device = None migrate = False - if ( - model not in MODELS_HUMIDIFIER - and model not in MODELS_PURIFIER_MIOT - and model not in MODELS_FAN_MIIO - ): + if model not in MODELS_HUMIDIFIER and model not in MODELS_FAN: return _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5]) diff --git a/homeassistant/components/xiaomi_miio/const.py b/homeassistant/components/xiaomi_miio/const.py index c407e92a6ae..de1c0bcf007 100644 --- a/homeassistant/components/xiaomi_miio/const.py +++ b/homeassistant/components/xiaomi_miio/const.py @@ -63,7 +63,7 @@ MODELS_PURIFIER_MIOT = [ MODEL_AIRPURIFIER_3H, MODEL_AIRPURIFIER_PROH, ] -MODELS_FAN_MIIO = [ +MODELS_PURIFIER_MIIO = [ MODEL_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V2, MODEL_AIRPURIFIER_V3, @@ -124,7 +124,7 @@ MODELS_SWITCH = [ "chuangmi.plug.hmi205", "chuangmi.plug.hmi206", ] -MODELS_FAN = MODELS_FAN_MIIO + MODELS_PURIFIER_MIOT +MODELS_FAN = MODELS_PURIFIER_MIIO + MODELS_PURIFIER_MIOT MODELS_HUMIDIFIER = ( MODELS_HUMIDIFIER_MIOT + MODELS_HUMIDIFIER_MIIO + MODELS_HUMIDIFIER_MJJSQ ) diff --git a/homeassistant/components/xiaomi_miio/fan.py b/homeassistant/components/xiaomi_miio/fan.py index fe4df2cd6d3..5b3418c83f5 100644 --- a/homeassistant/components/xiaomi_miio/fan.py +++ b/homeassistant/components/xiaomi_miio/fan.py @@ -28,7 +28,6 @@ from homeassistant.config_entries import SOURCE_IMPORT from homeassistant.const import ( ATTR_ENTITY_ID, ATTR_MODE, - ATTR_TEMPERATURE, CONF_HOST, CONF_NAME, CONF_TOKEN, @@ -103,26 +102,15 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ATTR_MODEL = "model" # Air Purifier -ATTR_HUMIDITY = "humidity" -ATTR_AIR_QUALITY_INDEX = "aqi" -ATTR_FILTER_HOURS_USED = "filter_hours_used" ATTR_FILTER_LIFE = "filter_life_remaining" ATTR_FAVORITE_LEVEL = "favorite_level" ATTR_BUZZER = "buzzer" ATTR_CHILD_LOCK = "child_lock" ATTR_LED = "led" ATTR_LED_BRIGHTNESS = "led_brightness" -ATTR_MOTOR_SPEED = "motor_speed" -ATTR_AVERAGE_AIR_QUALITY_INDEX = "average_aqi" -ATTR_PURIFY_VOLUME = "purify_volume" ATTR_BRIGHTNESS = "brightness" ATTR_LEVEL = "level" ATTR_FAN_LEVEL = "fan_level" -ATTR_MOTOR2_SPEED = "motor2_speed" -ATTR_ILLUMINANCE = "illuminance" -ATTR_FILTER_RFID_PRODUCT_ID = "filter_rfid_product_id" -ATTR_FILTER_RFID_TAG = "filter_rfid_tag" -ATTR_FILTER_TYPE = "filter_type" ATTR_LEARN_MODE = "learn_mode" ATTR_SLEEP_TIME = "sleep_time" ATTR_SLEEP_LEARN_COUNT = "sleep_mode_learn_count" @@ -135,22 +123,12 @@ ATTR_VOLUME = "volume" ATTR_USE_TIME = "use_time" ATTR_BUTTON_PRESSED = "button_pressed" -# Air Fresh -ATTR_CO2 = "co2" - # Map attributes to properties of the state object AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON = { - ATTR_TEMPERATURE: "temperature", - ATTR_HUMIDITY: "humidity", - ATTR_AIR_QUALITY_INDEX: "aqi", ATTR_MODE: "mode", - ATTR_FILTER_HOURS_USED: "filter_hours_used", - ATTR_FILTER_LIFE: "filter_life_remaining", ATTR_FAVORITE_LEVEL: "favorite_level", ATTR_CHILD_LOCK: "child_lock", ATTR_LED: "led", - ATTR_MOTOR_SPEED: "motor_speed", - ATTR_AVERAGE_AIR_QUALITY_INDEX: "average_aqi", ATTR_LEARN_MODE: "learn_mode", ATTR_EXTRA_FEATURES: "extra_features", ATTR_TURBO_MODE_SUPPORTED: "turbo_mode_supported", @@ -159,7 +137,6 @@ AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON = { AVAILABLE_ATTRIBUTES_AIRPURIFIER = { **AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON, - ATTR_PURIFY_VOLUME: "purify_volume", ATTR_SLEEP_TIME: "sleep_time", ATTR_SLEEP_LEARN_COUNT: "sleep_mode_learn_count", ATTR_AUTO_DETECT: "auto_detect", @@ -171,15 +148,8 @@ AVAILABLE_ATTRIBUTES_AIRPURIFIER = { AVAILABLE_ATTRIBUTES_AIRPURIFIER_PRO = { **AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON, - ATTR_PURIFY_VOLUME: "purify_volume", ATTR_USE_TIME: "use_time", - ATTR_FILTER_RFID_PRODUCT_ID: "filter_rfid_product_id", - ATTR_FILTER_RFID_TAG: "filter_rfid_tag", - ATTR_FILTER_TYPE: "filter_type", - ATTR_ILLUMINANCE: "illuminance", - ATTR_MOTOR2_SPEED: "motor2_speed", ATTR_VOLUME: "volume", - # perhaps supported but unconfirmed ATTR_AUTO_DETECT: "auto_detect", ATTR_SLEEP_TIME: "sleep_time", ATTR_SLEEP_LEARN_COUNT: "sleep_mode_learn_count", @@ -187,64 +157,32 @@ AVAILABLE_ATTRIBUTES_AIRPURIFIER_PRO = { AVAILABLE_ATTRIBUTES_AIRPURIFIER_PRO_V7 = { **AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON, - ATTR_FILTER_RFID_PRODUCT_ID: "filter_rfid_product_id", - ATTR_FILTER_RFID_TAG: "filter_rfid_tag", - ATTR_FILTER_TYPE: "filter_type", - ATTR_ILLUMINANCE: "illuminance", - ATTR_MOTOR2_SPEED: "motor2_speed", ATTR_VOLUME: "volume", } AVAILABLE_ATTRIBUTES_AIRPURIFIER_2S = { **AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON, ATTR_BUZZER: "buzzer", - ATTR_FILTER_RFID_PRODUCT_ID: "filter_rfid_product_id", - ATTR_FILTER_RFID_TAG: "filter_rfid_tag", - ATTR_FILTER_TYPE: "filter_type", - ATTR_ILLUMINANCE: "illuminance", } AVAILABLE_ATTRIBUTES_AIRPURIFIER_3 = { - ATTR_TEMPERATURE: "temperature", - ATTR_HUMIDITY: "humidity", - ATTR_AIR_QUALITY_INDEX: "aqi", ATTR_MODE: "mode", - ATTR_FILTER_HOURS_USED: "filter_hours_used", - ATTR_FILTER_LIFE: "filter_life_remaining", ATTR_FAVORITE_LEVEL: "favorite_level", ATTR_CHILD_LOCK: "child_lock", ATTR_LED: "led", - ATTR_MOTOR_SPEED: "motor_speed", - ATTR_AVERAGE_AIR_QUALITY_INDEX: "average_aqi", - ATTR_PURIFY_VOLUME: "purify_volume", ATTR_USE_TIME: "use_time", ATTR_BUZZER: "buzzer", ATTR_LED_BRIGHTNESS: "led_brightness", - ATTR_FILTER_RFID_PRODUCT_ID: "filter_rfid_product_id", - ATTR_FILTER_RFID_TAG: "filter_rfid_tag", - ATTR_FILTER_TYPE: "filter_type", ATTR_FAN_LEVEL: "fan_level", } AVAILABLE_ATTRIBUTES_AIRPURIFIER_V3 = { # Common set isn't used here. It's a very basic version of the device. - ATTR_AIR_QUALITY_INDEX: "aqi", ATTR_MODE: "mode", ATTR_LED: "led", ATTR_BUZZER: "buzzer", ATTR_CHILD_LOCK: "child_lock", - ATTR_ILLUMINANCE: "illuminance", - ATTR_FILTER_HOURS_USED: "filter_hours_used", - ATTR_FILTER_LIFE: "filter_life_remaining", - ATTR_MOTOR_SPEED: "motor_speed", - # perhaps supported but unconfirmed - ATTR_AVERAGE_AIR_QUALITY_INDEX: "average_aqi", ATTR_VOLUME: "volume", - ATTR_MOTOR2_SPEED: "motor2_speed", - ATTR_FILTER_RFID_PRODUCT_ID: "filter_rfid_product_id", - ATTR_FILTER_RFID_TAG: "filter_rfid_tag", - ATTR_FILTER_TYPE: "filter_type", - ATTR_PURIFY_VOLUME: "purify_volume", ATTR_LEARN_MODE: "learn_mode", ATTR_SLEEP_TIME: "sleep_time", ATTR_SLEEP_LEARN_COUNT: "sleep_mode_learn_count", @@ -255,20 +193,12 @@ AVAILABLE_ATTRIBUTES_AIRPURIFIER_V3 = { } AVAILABLE_ATTRIBUTES_AIRFRESH = { - ATTR_TEMPERATURE: "temperature", - ATTR_AIR_QUALITY_INDEX: "aqi", - ATTR_AVERAGE_AIR_QUALITY_INDEX: "average_aqi", - ATTR_CO2: "co2", - ATTR_HUMIDITY: "humidity", ATTR_MODE: "mode", ATTR_LED: "led", ATTR_LED_BRIGHTNESS: "led_brightness", ATTR_BUZZER: "buzzer", ATTR_CHILD_LOCK: "child_lock", - ATTR_FILTER_LIFE: "filter_life_remaining", - ATTR_FILTER_HOURS_USED: "filter_hours_used", ATTR_USE_TIME: "use_time", - ATTR_MOTOR_SPEED: "motor_speed", ATTR_EXTRA_FEATURES: "extra_features", } diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index aff0b5212f1..26914e1dff8 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -19,6 +19,7 @@ import voluptuous as vol from homeassistant.components.sensor import ( PLATFORM_SCHEMA, STATE_CLASS_MEASUREMENT, + STATE_CLASS_TOTAL_INCREASING, SensorEntity, SensorEntityDescription, ) @@ -26,18 +27,25 @@ from homeassistant.config_entries import SOURCE_IMPORT from homeassistant.const import ( ATTR_BATTERY_LEVEL, ATTR_TEMPERATURE, + CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + CONCENTRATION_PARTS_PER_MILLION, CONF_HOST, CONF_NAME, CONF_TOKEN, + DEVICE_CLASS_CO2, + DEVICE_CLASS_GAS, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, DEVICE_CLASS_POWER, DEVICE_CLASS_PRESSURE, DEVICE_CLASS_TEMPERATURE, + LIGHT_LUX, PERCENTAGE, POWER_WATT, PRESSURE_HPA, TEMP_CELSIUS, + TIME_HOURS, + VOLUME_CUBIC_METERS, ) import homeassistant.helpers.config_validation as cv @@ -49,11 +57,18 @@ from .const import ( DOMAIN, KEY_COORDINATOR, KEY_DEVICE, + MODEL_AIRFRESH_VA2, MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CB1, + MODEL_AIRPURIFIER_PRO, + MODEL_AIRPURIFIER_PRO_V7, + MODEL_AIRPURIFIER_V2, + MODEL_AIRPURIFIER_V3, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, MODELS_HUMIDIFIER_MJJSQ, + MODELS_PURIFIER_MIIO, + MODELS_PURIFIER_MIOT, ) from .device import XiaomiCoordinatedMiioEntity, XiaomiMiioEntity from .gateway import XiaomiGatewayDevice @@ -73,17 +88,26 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( ATTR_ACTUAL_SPEED = "actual_speed" ATTR_AIR_QUALITY = "air_quality" +ATTR_AQI = "aqi" +ATTR_CARBON_DIOXIDE = "co2" ATTR_CHARGING = "charging" ATTR_DISPLAY_CLOCK = "display_clock" +ATTR_FILTER_LIFE_REMAINING = "filter_life_remaining" +ATTR_FILTER_HOURS_USED = "filter_hours_used" +ATTR_FILTER_USE = "filter_use" ATTR_HUMIDITY = "humidity" ATTR_ILLUMINANCE = "illuminance" +ATTR_ILLUMINANCE_LUX = "illuminance_lux" ATTR_LOAD_POWER = "load_power" +ATTR_MOTOR2_SPEED = "motor2_speed" ATTR_MOTOR_SPEED = "motor_speed" ATTR_NIGHT_MODE = "night_mode" ATTR_NIGHT_TIME_BEGIN = "night_time_begin" ATTR_NIGHT_TIME_END = "night_time_end" +ATTR_PM25 = "pm25" ATTR_POWER = "power" ATTR_PRESSURE = "pressure" +ATTR_PURIFY_VOLUME = "purify_volume" ATTR_SENSOR_STATE = "sensor_state" ATTR_WATER_LEVEL = "water_level" @@ -92,8 +116,7 @@ ATTR_WATER_LEVEL = "water_level" class XiaomiMiioSensorDescription(SensorEntityDescription): """Class that holds device specific info for a xiaomi aqara or humidifier sensor.""" - valid_min_value: float | None = None - valid_max_value: float | None = None + attributes: tuple = () SENSOR_TYPES = { @@ -130,8 +153,6 @@ SENSOR_TYPES = { native_unit_of_measurement=PERCENTAGE, icon="mdi:water-check", state_class=STATE_CLASS_MEASUREMENT, - valid_min_value=0.0, - valid_max_value=100.0, ), ATTR_ACTUAL_SPEED: XiaomiMiioSensorDescription( key=ATTR_ACTUAL_SPEED, @@ -147,6 +168,13 @@ SENSOR_TYPES = { icon="mdi:fast-forward", state_class=STATE_CLASS_MEASUREMENT, ), + ATTR_MOTOR2_SPEED: XiaomiMiioSensorDescription( + key=ATTR_MOTOR2_SPEED, + name="Second Motor Speed", + native_unit_of_measurement="rpm", + icon="mdi:fast-forward", + state_class=STATE_CLASS_MEASUREMENT, + ), ATTR_ILLUMINANCE: XiaomiMiioSensorDescription( key=ATTR_ILLUMINANCE, name="Illuminance", @@ -154,24 +182,144 @@ SENSOR_TYPES = { device_class=DEVICE_CLASS_ILLUMINANCE, state_class=STATE_CLASS_MEASUREMENT, ), + ATTR_ILLUMINANCE_LUX: XiaomiMiioSensorDescription( + key=ATTR_ILLUMINANCE, + name="Illuminance", + native_unit_of_measurement=LIGHT_LUX, + device_class=DEVICE_CLASS_ILLUMINANCE, + state_class=STATE_CLASS_MEASUREMENT, + ), ATTR_AIR_QUALITY: XiaomiMiioSensorDescription( key=ATTR_AIR_QUALITY, native_unit_of_measurement="AQI", icon="mdi:cloud", state_class=STATE_CLASS_MEASUREMENT, ), + ATTR_PM25: XiaomiMiioSensorDescription( + key=ATTR_AQI, + name="PM2.5", + native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, + icon="mdi:blur", + state_class=STATE_CLASS_MEASUREMENT, + ), + ATTR_FILTER_LIFE_REMAINING: XiaomiMiioSensorDescription( + key=ATTR_FILTER_LIFE_REMAINING, + name="Filter Life Remaining", + native_unit_of_measurement=PERCENTAGE, + icon="mdi:air-filter", + state_class=STATE_CLASS_MEASUREMENT, + attributes=("filter_type",), + ), + ATTR_FILTER_USE: XiaomiMiioSensorDescription( + key=ATTR_FILTER_HOURS_USED, + name="Filter Use", + native_unit_of_measurement=TIME_HOURS, + icon="mdi:clock-outline", + state_class=STATE_CLASS_MEASUREMENT, + ), + ATTR_CARBON_DIOXIDE: XiaomiMiioSensorDescription( + key=ATTR_CARBON_DIOXIDE, + name="Carbon Dioxide", + native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, + device_class=DEVICE_CLASS_CO2, + state_class=STATE_CLASS_MEASUREMENT, + ), + ATTR_PURIFY_VOLUME: XiaomiMiioSensorDescription( + key=ATTR_PURIFY_VOLUME, + name="Purify Volume", + native_unit_of_measurement=VOLUME_CUBIC_METERS, + device_class=DEVICE_CLASS_GAS, + state_class=STATE_CLASS_TOTAL_INCREASING, + entity_registry_enabled_default=False, + ), } HUMIDIFIER_MIIO_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE) HUMIDIFIER_CA1_CB1_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE, ATTR_MOTOR_SPEED) HUMIDIFIER_MIOT_SENSORS = ( + ATTR_ACTUAL_SPEED, ATTR_HUMIDITY, ATTR_TEMPERATURE, ATTR_WATER_LEVEL, - ATTR_ACTUAL_SPEED, ) HUMIDIFIER_MJJSQ_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE) +PURIFIER_MIIO_SENSORS = ( + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_HUMIDITY, + ATTR_MOTOR_SPEED, + ATTR_PM25, + ATTR_TEMPERATURE, +) +PURIFIER_MIOT_SENSORS = ( + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_HUMIDITY, + ATTR_MOTOR_SPEED, + ATTR_PM25, + ATTR_PURIFY_VOLUME, + ATTR_TEMPERATURE, +) +PURIFIER_V2_SENSORS = ( + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_HUMIDITY, + ATTR_MOTOR_SPEED, + ATTR_PM25, + ATTR_PURIFY_VOLUME, + ATTR_TEMPERATURE, +) +PURIFIER_V3_SENSORS = ( + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_ILLUMINANCE_LUX, + ATTR_MOTOR2_SPEED, + ATTR_MOTOR_SPEED, + ATTR_PM25, + ATTR_PURIFY_VOLUME, +) +PURIFIER_PRO_SENSORS = ( + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_HUMIDITY, + ATTR_ILLUMINANCE_LUX, + ATTR_MOTOR2_SPEED, + ATTR_MOTOR_SPEED, + ATTR_PM25, + ATTR_PURIFY_VOLUME, + ATTR_TEMPERATURE, +) +PURIFIER_PRO_V7_SENSORS = ( + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_HUMIDITY, + ATTR_ILLUMINANCE_LUX, + ATTR_MOTOR2_SPEED, + ATTR_MOTOR_SPEED, + ATTR_PM25, + ATTR_TEMPERATURE, +) +AIRFRESH_SENSORS = ( + ATTR_CARBON_DIOXIDE, + ATTR_FILTER_LIFE_REMAINING, + ATTR_FILTER_USE, + ATTR_HUMIDITY, + ATTR_ILLUMINANCE_LUX, + ATTR_PM25, + ATTR_TEMPERATURE, +) + +MODEL_TO_SENSORS_MAP = { + MODEL_AIRHUMIDIFIER_CA1: HUMIDIFIER_CA1_CB1_SENSORS, + MODEL_AIRHUMIDIFIER_CB1: HUMIDIFIER_CA1_CB1_SENSORS, + MODEL_AIRPURIFIER_V2: PURIFIER_V2_SENSORS, + MODEL_AIRPURIFIER_V3: PURIFIER_V3_SENSORS, + MODEL_AIRPURIFIER_PRO_V7: PURIFIER_PRO_V7_SENSORS, + MODEL_AIRPURIFIER_PRO: PURIFIER_PRO_SENSORS, + MODEL_AIRFRESH_VA2: AIRFRESH_SENSORS, +} + async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Import Miio configuration from YAML.""" @@ -224,20 +372,20 @@ async def async_setup_entry(hass, config_entry, async_add_entities): host = config_entry.data[CONF_HOST] token = config_entry.data[CONF_TOKEN] model = config_entry.data[CONF_MODEL] - device = None + device = hass.data[DOMAIN][config_entry.entry_id].get(KEY_DEVICE) sensors = [] - if model in (MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CB1): - device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] - sensors = HUMIDIFIER_CA1_CB1_SENSORS + if model in MODEL_TO_SENSORS_MAP: + sensors = MODEL_TO_SENSORS_MAP[model] elif model in MODELS_HUMIDIFIER_MIOT: - device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] sensors = HUMIDIFIER_MIOT_SENSORS elif model in MODELS_HUMIDIFIER_MJJSQ: - device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] sensors = HUMIDIFIER_MJJSQ_SENSORS elif model in MODELS_HUMIDIFIER_MIIO: - device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] sensors = HUMIDIFIER_MIIO_SENSORS + elif model in MODELS_PURIFIER_MIIO: + sensors = PURIFIER_MIIO_SENSORS + elif model in MODELS_PURIFIER_MIOT: + sensors = PURIFIER_MIOT_SENSORS else: unique_id = config_entry.unique_id name = config_entry.title @@ -276,24 +424,23 @@ class XiaomiGenericSensor(XiaomiCoordinatedMiioEntity, SensorEntity): self._attr_name = name self._attr_unique_id = unique_id - self._state = None self.entity_description = description @property def native_value(self): """Return the state of the device.""" - self._state = self._extract_value_from_attribute( + return self._extract_value_from_attribute( self.coordinator.data, self.entity_description.key ) - if ( - self.entity_description.valid_min_value - and self._state < self.entity_description.valid_min_value - ) or ( - self.entity_description.valid_max_value - and self._state > self.entity_description.valid_max_value - ): - return None - return self._state + + @property + def extra_state_attributes(self): + """Return the state attributes.""" + return { + attr: self._extract_value_from_attribute(self.coordinator.data, attr) + for attr in self.entity_description.attributes + if hasattr(self.coordinator.data, attr) + } @staticmethod def _extract_value_from_attribute(state, attribute):