diff --git a/homeassistant/components/xiaomi_miio/__init__.py b/homeassistant/components/xiaomi_miio/__init__.py index 36ee89ba7a0..89355ae309e 100644 --- a/homeassistant/components/xiaomi_miio/__init__.py +++ b/homeassistant/components/xiaomi_miio/__init__.py @@ -3,7 +3,7 @@ from datetime import timedelta import logging import async_timeout -from miio import AirHumidifier, AirHumidifierMiot, DeviceException +from miio import AirHumidifier, AirHumidifierMiot, AirHumidifierMjjsq, DeviceException from miio.gateway.gateway import GatewayException from homeassistant import config_entries, core @@ -25,6 +25,7 @@ from .const import ( MODELS_FAN, MODELS_HUMIDIFIER, MODELS_HUMIDIFIER_MIOT, + MODELS_HUMIDIFIER_MJJSQ, MODELS_LIGHT, MODELS_SWITCH, MODELS_VACUUM, @@ -107,6 +108,8 @@ async def async_create_miio_device_and_coordinator( if model in MODELS_HUMIDIFIER_MIOT: device = AirHumidifierMiot(host, token) + elif model in MODELS_HUMIDIFIER_MJJSQ: + device = AirHumidifierMjjsq(host, token, model=model) else: device = AirHumidifier(host, token, model=model) @@ -123,7 +126,9 @@ async def async_create_miio_device_and_coordinator( """Fetch data from the device using async_add_executor_job.""" try: async with async_timeout.timeout(10): - return await hass.async_add_executor_job(device.status) + state = await hass.async_add_executor_job(device.status) + _LOGGER.debug("Got new state: %s", state) + return state except DeviceException as ex: raise UpdateFailed(ex) from ex diff --git a/homeassistant/components/xiaomi_miio/const.py b/homeassistant/components/xiaomi_miio/const.py index a2f7679bf1b..c407e92a6ae 100644 --- a/homeassistant/components/xiaomi_miio/const.py +++ b/homeassistant/components/xiaomi_miio/const.py @@ -52,6 +52,9 @@ MODEL_AIRHUMIDIFIER_V1 = "zhimi.humidifier.v1" MODEL_AIRHUMIDIFIER_CA1 = "zhimi.humidifier.ca1" MODEL_AIRHUMIDIFIER_CA4 = "zhimi.humidifier.ca4" MODEL_AIRHUMIDIFIER_CB1 = "zhimi.humidifier.cb1" +MODEL_AIRHUMIDIFIER_JSQ = "deerma.humidifier.jsq" +MODEL_AIRHUMIDIFIER_JSQ1 = "deerma.humidifier.jsq1" +MODEL_AIRHUMIDIFIER_MJJSQ = "deerma.humidifier.mjjsq" MODEL_AIRFRESH_VA2 = "zhimi.airfresh.va2" @@ -60,7 +63,6 @@ MODELS_PURIFIER_MIOT = [ MODEL_AIRPURIFIER_3H, MODEL_AIRPURIFIER_PROH, ] -MODELS_HUMIDIFIER_MIOT = [MODEL_AIRHUMIDIFIER_CA4] MODELS_FAN_MIIO = [ MODEL_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V2, @@ -83,6 +85,12 @@ MODELS_HUMIDIFIER_MIIO = [ MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CB1, ] +MODELS_HUMIDIFIER_MIOT = [MODEL_AIRHUMIDIFIER_CA4] +MODELS_HUMIDIFIER_MJJSQ = [ + MODEL_AIRHUMIDIFIER_JSQ, + MODEL_AIRHUMIDIFIER_JSQ1, + MODEL_AIRHUMIDIFIER_MJJSQ, +] # AirQuality Models MODEL_AIRQUALITYMONITOR_V1 = "zhimi.airmonitor.v1" @@ -117,7 +125,9 @@ MODELS_SWITCH = [ "chuangmi.plug.hmi206", ] MODELS_FAN = MODELS_FAN_MIIO + MODELS_PURIFIER_MIOT -MODELS_HUMIDIFIER = MODELS_HUMIDIFIER_MIOT + MODELS_HUMIDIFIER_MIIO +MODELS_HUMIDIFIER = ( + MODELS_HUMIDIFIER_MIOT + MODELS_HUMIDIFIER_MIIO + MODELS_HUMIDIFIER_MJJSQ +) MODELS_LIGHT = ( MODELS_LIGHT_EYECARE + MODELS_LIGHT_CEILING @@ -146,15 +156,12 @@ MODELS_ALL = MODELS_ALL_DEVICES + MODELS_GATEWAY # Fan/Humidifier Services SERVICE_SET_BUZZER_ON = "fan_set_buzzer_on" SERVICE_SET_BUZZER_OFF = "fan_set_buzzer_off" -SERVICE_SET_BUZZER = "set_buzzer" -SERVICE_SET_CLEAN = "set_clean" SERVICE_SET_FAN_LED_ON = "fan_set_led_on" SERVICE_SET_FAN_LED_OFF = "fan_set_led_off" SERVICE_SET_FAN_LED = "fan_set_led" SERVICE_SET_LED_BRIGHTNESS = "set_led_brightness" SERVICE_SET_CHILD_LOCK_ON = "fan_set_child_lock_on" SERVICE_SET_CHILD_LOCK_OFF = "fan_set_child_lock_off" -SERVICE_SET_CHILD_LOCK = "set_child_lock" SERVICE_SET_LED_BRIGHTNESS = "fan_set_led_brightness" SERVICE_SET_FAVORITE_LEVEL = "fan_set_favorite_level" SERVICE_SET_FAN_LEVEL = "fan_set_fan_level" @@ -270,6 +277,10 @@ FEATURE_FLAGS_AIRHUMIDIFIER = ( FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB = FEATURE_FLAGS_AIRHUMIDIFIER | FEATURE_SET_DRY +FEATURE_FLAGS_AIRHUMIDIFIER_MJSSQ = ( + FEATURE_SET_BUZZER | FEATURE_SET_LED | FEATURE_SET_TARGET_HUMIDITY +) + FEATURE_FLAGS_AIRHUMIDIFIER_CA4 = ( FEATURE_SET_BUZZER | FEATURE_SET_CHILD_LOCK diff --git a/homeassistant/components/xiaomi_miio/humidifier.py b/homeassistant/components/xiaomi_miio/humidifier.py index aee2c237066..aa26faae2b3 100644 --- a/homeassistant/components/xiaomi_miio/humidifier.py +++ b/homeassistant/components/xiaomi_miio/humidifier.py @@ -5,6 +5,7 @@ import math from miio.airhumidifier import OperationMode as AirhumidifierOperationMode from miio.airhumidifier_miot import OperationMode as AirhumidifierMiotOperationMode +from miio.airhumidifier_mjjsq import OperationMode as AirhumidifierMjjsqOperationMode from homeassistant.components.humidifier import HumidifierEntity from homeassistant.components.humidifier.const import ( @@ -28,6 +29,7 @@ from .const import ( MODEL_AIRHUMIDIFIER_CA4, MODEL_AIRHUMIDIFIER_CB1, MODELS_HUMIDIFIER_MIOT, + MODELS_HUMIDIFIER_MJJSQ, ) from .device import XiaomiCoordinatedMiioEntity @@ -41,6 +43,23 @@ AVAILABLE_ATTRIBUTES = { ATTR_TARGET_HUMIDITY: "target_humidity", } +AVAILABLE_MODES_CA1_CB1 = [ + mode.name + for mode in AirhumidifierOperationMode + if mode is not AirhumidifierOperationMode.Strong +] +AVAILABLE_MODES_CA4 = [mode.name for mode in AirhumidifierMiotOperationMode] +AVAILABLE_MODES_MJJSQ = [ + mode.name + for mode in AirhumidifierMjjsqOperationMode + if mode is not AirhumidifierMjjsqOperationMode.WetAndProtect +] +AVAILABLE_MODES_OTHER = [ + mode.name + for mode in AirhumidifierOperationMode + if mode is not AirhumidifierOperationMode.Auto +] + async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Humidifier from a config entry.""" @@ -62,6 +81,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities): unique_id, coordinator, ) + elif model in MODELS_HUMIDIFIER_MJJSQ: + air_humidifier = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] + entity = XiaomiAirHumidifierMjjsq( + name, + air_humidifier, + config_entry, + unique_id, + coordinator, + ) else: air_humidifier = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] entity = XiaomiAirHumidifier( @@ -169,28 +197,22 @@ class XiaomiAirHumidifier(XiaomiGenericHumidifier, HumidifierEntity): """Initialize the plug switch.""" super().__init__(name, device, entry, unique_id, coordinator) if self._model in [MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CB1]: - self._available_modes = [] - self._available_modes = [ - mode.name - for mode in AirhumidifierOperationMode - if mode is not AirhumidifierOperationMode.Strong - ] + self._available_modes = AVAILABLE_MODES_CA1_CB1 self._min_humidity = 30 self._max_humidity = 80 self._humidity_steps = 10 elif self._model in [MODEL_AIRHUMIDIFIER_CA4]: - self._available_modes = [ - mode.name for mode in AirhumidifierMiotOperationMode - ] + self._available_modes = AVAILABLE_MODES_CA4 self._min_humidity = 30 self._max_humidity = 80 self._humidity_steps = 100 + elif self._model in MODELS_HUMIDIFIER_MJJSQ: + self._available_modes = AVAILABLE_MODES_MJJSQ + self._min_humidity = 30 + self._max_humidity = 80 + self._humidity_steps = 10 else: - self._available_modes = [ - mode.name - for mode in AirhumidifierOperationMode - if mode is not AirhumidifierOperationMode.Auto - ] + self._available_modes = AVAILABLE_MODES_OTHER self._min_humidity = 30 self._max_humidity = 80 self._humidity_steps = 10 @@ -364,3 +386,75 @@ class XiaomiAirHumidifierMiot(XiaomiAirHumidifier): ): self._mode = self.REVERSE_MODE_MAPPING[mode].value self.async_write_ha_state() + + +class XiaomiAirHumidifierMjjsq(XiaomiAirHumidifier): + """Representation of a Xiaomi Air MJJSQ Humidifier.""" + + MODE_MAPPING = { + "Low": AirhumidifierMjjsqOperationMode.Low, + "Medium": AirhumidifierMjjsqOperationMode.Medium, + "High": AirhumidifierMjjsqOperationMode.High, + "Humidity": AirhumidifierMjjsqOperationMode.Humidity, + } + + @property + def mode(self): + """Return the current mode.""" + return AirhumidifierMjjsqOperationMode(self._mode).name + + @property + def target_humidity(self): + """Return the target humidity.""" + if self._state: + if ( + AirhumidifierMjjsqOperationMode(self._mode) + == AirhumidifierMjjsqOperationMode.Humidity + ): + return self._target_humidity + return None + + async def async_set_humidity(self, humidity: int) -> None: + """Set the target humidity of the humidifier and set the mode to Humidity.""" + target_humidity = self.translate_humidity(humidity) + if not target_humidity: + return + + _LOGGER.debug("Setting the humidity to: %s", target_humidity) + if await self._try_command( + "Setting operation mode of the miio device failed.", + self._device.set_target_humidity, + target_humidity, + ): + self._target_humidity = target_humidity + if ( + self.supported_features & SUPPORT_MODES == 0 + or AirhumidifierMjjsqOperationMode(self._attributes[ATTR_MODE]) + == AirhumidifierMjjsqOperationMode.Humidity + ): + self.async_write_ha_state() + return + _LOGGER.debug("Setting the operation mode to: Humidity") + if await self._try_command( + "Setting operation mode of the miio device to MODE_HUMIDITY failed.", + self._device.set_mode, + AirhumidifierMjjsqOperationMode.Humidity, + ): + self._mode = 3 + self.async_write_ha_state() + + async def async_set_mode(self, mode: str) -> None: + """Set the mode of the fan.""" + if mode not in self.MODE_MAPPING: + _LOGGER.warning("Mode %s is not a valid operation mode", mode) + return + + _LOGGER.debug("Setting the operation mode to: %s", mode) + if self._state: + if await self._try_command( + "Setting operation mode of the miio device failed.", + self._device.set_mode, + self.MODE_MAPPING[mode], + ): + self._mode = self.MODE_MAPPING[mode].value + self.async_write_ha_state() diff --git a/homeassistant/components/xiaomi_miio/select.py b/homeassistant/components/xiaomi_miio/select.py index 77aba961244..23e43e4dbbd 100644 --- a/homeassistant/components/xiaomi_miio/select.py +++ b/homeassistant/components/xiaomi_miio/select.py @@ -16,10 +16,8 @@ from .const import ( FEATURE_SET_LED_BRIGHTNESS, KEY_COORDINATOR, KEY_DEVICE, - MODEL_AIRHUMIDIFIER_CA1, - MODEL_AIRHUMIDIFIER_CA4, - MODEL_AIRHUMIDIFIER_CB1, - MODELS_HUMIDIFIER, + MODELS_HUMIDIFIER_MIIO, + MODELS_HUMIDIFIER_MIOT, SERVICE_SET_LED_BRIGHTNESS, ) from .device import XiaomiCoordinatedMiioEntity @@ -65,28 +63,25 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entities = [] model = config_entry.data[CONF_MODEL] device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] - coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] - if model in [MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CB1]: + if model in MODELS_HUMIDIFIER_MIIO: entity_class = XiaomiAirHumidifierSelector - elif model in [MODEL_AIRHUMIDIFIER_CA4]: + elif model in MODELS_HUMIDIFIER_MIOT: entity_class = XiaomiAirHumidifierMiotSelector - elif model in MODELS_HUMIDIFIER: - entity_class = XiaomiAirHumidifierSelector else: return - for selector in SELECTOR_TYPES.values(): - entities.append( - entity_class( - f"{config_entry.title} {selector.name}", - device, - config_entry, - f"{selector.short_name}_{config_entry.unique_id}", - selector, - coordinator, - ) + selector = SELECTOR_TYPES[FEATURE_SET_LED_BRIGHTNESS] + entities.append( + entity_class( + f"{config_entry.title} {selector.name}", + device, + config_entry, + f"{selector.short_name}_{config_entry.unique_id}", + selector, + hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR], ) + ) async_add_entities(entities) diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index 413971aa880..4663813ab7c 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -46,6 +46,7 @@ from .const import ( KEY_COORDINATOR, KEY_DEVICE, MODELS_HUMIDIFIER_MIOT, + MODELS_HUMIDIFIER_MJJSQ, ) from .device import XiaomiCoordinatedMiioEntity, XiaomiMiioEntity from .gateway import XiaomiGatewayDevice @@ -135,6 +136,11 @@ HUMIDIFIER_SENSORS_MIOT = { ATTR_ACTUAL_MOTOR_SPEED: "actual_speed", } +HUMIDIFIER_SENSORS_MJJSQ = { + ATTR_HUMIDITY: "humidity", + ATTR_TEMPERATURE: "temperature", +} + async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): """Import Miio configuration from YAML.""" @@ -191,11 +197,12 @@ async def async_setup_entry(hass, config_entry, async_add_entities): sensors = [] if model in MODELS_HUMIDIFIER_MIOT: device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] - coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] sensors = HUMIDIFIER_SENSORS_MIOT + elif model in MODELS_HUMIDIFIER_MJJSQ: + device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] + sensors = HUMIDIFIER_SENSORS_MJJSQ elif model.startswith("zhimi.humidifier."): device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE] - coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR] sensors = HUMIDIFIER_SENSORS else: unique_id = config_entry.unique_id diff --git a/homeassistant/components/xiaomi_miio/switch.py b/homeassistant/components/xiaomi_miio/switch.py index bdf3085f236..a82d091dee8 100644 --- a/homeassistant/components/xiaomi_miio/switch.py +++ b/homeassistant/components/xiaomi_miio/switch.py @@ -1,4 +1,6 @@ """Support for Xiaomi Smart WiFi Socket and Smart Power Strip.""" +from __future__ import annotations + import asyncio from dataclasses import dataclass from enum import Enum @@ -13,6 +15,7 @@ from homeassistant.components.switch import ( DEVICE_CLASS_SWITCH, PLATFORM_SCHEMA, SwitchEntity, + SwitchEntityDescription, ) from homeassistant.config_entries import SOURCE_IMPORT from homeassistant.const import ( @@ -35,20 +38,19 @@ from .const import ( FEATURE_FLAGS_AIRHUMIDIFIER, FEATURE_FLAGS_AIRHUMIDIFIER_CA4, FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB, + FEATURE_FLAGS_AIRHUMIDIFIER_MJSSQ, FEATURE_SET_BUZZER, FEATURE_SET_CHILD_LOCK, FEATURE_SET_CLEAN, FEATURE_SET_DRY, + FEATURE_SET_LED, KEY_COORDINATOR, KEY_DEVICE, MODEL_AIRHUMIDIFIER_CA1, MODEL_AIRHUMIDIFIER_CA4, MODEL_AIRHUMIDIFIER_CB1, MODELS_HUMIDIFIER, - SERVICE_SET_BUZZER, - SERVICE_SET_CHILD_LOCK, - SERVICE_SET_CLEAN, - SERVICE_SET_DRY, + MODELS_HUMIDIFIER_MJJSQ, SERVICE_SET_POWER_MODE, SERVICE_SET_POWER_PRICE, SERVICE_SET_WIFI_LED_OFF, @@ -96,17 +98,18 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( } ) -ATTR_POWER = "power" -ATTR_LOAD_POWER = "load_power" -ATTR_MODEL = "model" -ATTR_POWER_MODE = "power_mode" -ATTR_WIFI_LED = "wifi_led" -ATTR_POWER_PRICE = "power_price" -ATTR_PRICE = "price" ATTR_BUZZER = "buzzer" ATTR_CHILD_LOCK = "child_lock" -ATTR_DRY = "dry" ATTR_CLEAN = "clean_mode" +ATTR_DRY = "dry" +ATTR_LED = "led" +ATTR_LOAD_POWER = "load_power" +ATTR_MODEL = "model" +ATTR_POWER = "power" +ATTR_POWER_MODE = "power_mode" +ATTR_POWER_PRICE = "power_price" +ATTR_PRICE = "price" +ATTR_WIFI_LED = "wifi_led" FEATURE_SET_POWER_MODE = 1 FEATURE_SET_WIFI_LED = 2 @@ -143,63 +146,62 @@ SERVICE_TO_METHOD = { "method": "async_set_power_price", "schema": SERVICE_SCHEMA_POWER_PRICE, }, - SERVICE_SET_BUZZER: { - "method_on": "async_set_buzzer_on", - "method_off": "async_set_buzzer_off", - }, - SERVICE_SET_CHILD_LOCK: { - "method_on": "async_set_child_lock_on", - "method_off": "async_set_child_lock_off", - }, - SERVICE_SET_DRY: { - "method_on": "async_set_dry_on", - "method_off": "async_set_dry_off", - }, - SERVICE_SET_CLEAN: { - "method_on": "async_set_clean_on", - "method_off": "async_set_clean_off", - }, } @dataclass -class SwitchType: - """Class that holds device specific info for a xiaomi aqara or humidifiers.""" +class XiaomiMiioSwitchDescription(SwitchEntityDescription): + """A class that describes switch entities.""" - name: str = None - short_name: str = None - icon: str = None - service: str = None + feature: int | None = None + method_on: str | None = None + method_off: str | None = None available_with_device_off: bool = True -SWITCH_TYPES = { - FEATURE_SET_BUZZER: SwitchType( +SWITCH_TYPES = ( + XiaomiMiioSwitchDescription( + key=ATTR_BUZZER, + feature=FEATURE_SET_BUZZER, name="Buzzer", icon="mdi:volume-high", - short_name=ATTR_BUZZER, - service=SERVICE_SET_BUZZER, + method_on="async_set_buzzer_on", + method_off="async_set_buzzer_off", ), - FEATURE_SET_CHILD_LOCK: SwitchType( + XiaomiMiioSwitchDescription( + key=ATTR_CHILD_LOCK, + feature=FEATURE_SET_CHILD_LOCK, name="Child Lock", icon="mdi:lock", - short_name=ATTR_CHILD_LOCK, - service=SERVICE_SET_CHILD_LOCK, + method_on="async_set_child_lock_on", + method_off="async_set_child_lock_off", ), - FEATURE_SET_DRY: SwitchType( + XiaomiMiioSwitchDescription( + key=ATTR_DRY, + feature=FEATURE_SET_DRY, name="Dry Mode", icon="mdi:hair-dryer", - short_name=ATTR_DRY, - service=SERVICE_SET_DRY, + method_on="async_set_dry_on", + method_off="async_set_dry_off", ), - FEATURE_SET_CLEAN: SwitchType( + XiaomiMiioSwitchDescription( + key=ATTR_CLEAN, + feature=FEATURE_SET_CLEAN, name="Clean Mode", icon="mdi:sparkles", - short_name=ATTR_CLEAN, - service=SERVICE_SET_CLEAN, + method_on="async_set_clean_on", + method_off="async_set_clean_off", available_with_device_off=False, ), -} + XiaomiMiioSwitchDescription( + key=ATTR_LED, + feature=FEATURE_SET_LED, + name="Led", + icon="mdi:led-outline", + method_on="async_set_led_on", + method_off="async_set_led_off", + ), +) async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): @@ -241,19 +243,21 @@ async def async_setup_coordinated_entry(hass, config_entry, async_add_entities): device_features = FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB elif model in [MODEL_AIRHUMIDIFIER_CA4]: device_features = FEATURE_FLAGS_AIRHUMIDIFIER_CA4 + elif model in MODELS_HUMIDIFIER_MJJSQ: + device_features = FEATURE_FLAGS_AIRHUMIDIFIER_MJSSQ elif model in MODELS_HUMIDIFIER: device_features = FEATURE_FLAGS_AIRHUMIDIFIER - for feature, switch in SWITCH_TYPES.items(): - if feature & device_features: + for description in SWITCH_TYPES: + if description.feature & device_features: entities.append( XiaomiGenericCoordinatedSwitch( - f"{config_entry.title} {switch.name}", + f"{config_entry.title} {description.name}", device, config_entry, - f"{switch.short_name}_{unique_id}", - switch, + f"{description.key}_{unique_id}", coordinator, + description, ) ) @@ -382,22 +386,21 @@ async def async_setup_other_entry(hass, config_entry, async_add_entities): class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): """Representation of a Xiaomi Plug Generic.""" - def __init__(self, name, device, entry, unique_id, switch, coordinator): + def __init__(self, name, device, entry, unique_id, coordinator, description): """Initialize the plug switch.""" super().__init__(name, device, entry, unique_id, coordinator) - self._attr_icon = switch.icon - self._controller = switch self._attr_is_on = self._extract_value_from_attribute( - self.coordinator.data, self._controller.short_name + self.coordinator.data, description.key ) + self.entity_description = description @callback def _handle_coordinator_update(self): """Fetch state from the device.""" # On state change the device doesn't provide the new state immediately. self._attr_is_on = self._extract_value_from_attribute( - self.coordinator.data, self._controller.short_name + self.coordinator.data, self.entity_description.key ) self.async_write_ha_state() @@ -407,7 +410,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): if ( super().available and not self.coordinator.data.is_on - and not self._controller.available_with_device_off + and not self.entity_description.available_with_device_off ): return False return super().available @@ -422,7 +425,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): async def async_turn_on(self, **kwargs) -> None: """Turn on an option of the miio device.""" - method = getattr(self, SERVICE_TO_METHOD[self._controller.service]["method_on"]) + method = getattr(self, self.entity_description.method_on) if await method(): # Write state back to avoid switch flips with a slow response self._attr_is_on = True @@ -430,9 +433,7 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): async def async_turn_off(self, **kwargs) -> None: """Turn off an option of the miio device.""" - method = getattr( - self, SERVICE_TO_METHOD[self._controller.service]["method_off"] - ) + method = getattr(self, self.entity_description.method_off) if await method(): # Write state back to avoid switch flips with a slow response self._attr_is_on = False @@ -502,6 +503,22 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): False, ) + async def async_set_led_on(self) -> bool: + """Turn the led on.""" + return await self._try_command( + "Turning the led of the miio device on failed.", + self._device.set_led, + True, + ) + + async def async_set_led_off(self) -> bool: + """Turn the led off.""" + return await self._try_command( + "Turning the led of the miio device off failed.", + self._device.set_led, + False, + ) + class XiaomiGatewaySwitch(XiaomiGatewayDevice, SwitchEntity): """Representation of a XiaomiGatewaySwitch."""