Add support for MJJSQ humidifiers for Xiaomi MIIO integration (#53807)

This commit is contained in:
Maciej Bieniek 2021-08-02 22:08:37 +02:00 committed by GitHub
parent d4cb819e1f
commit 938ec27a86
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 234 additions and 105 deletions

View file

@ -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

View file

@ -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

View file

@ -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()

View file

@ -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,18 +63,15 @@ 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():
selector = SELECTOR_TYPES[FEATURE_SET_LED_BRIGHTNESS]
entities.append(
entity_class(
f"{config_entry.title} {selector.name}",
@ -84,7 +79,7 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
config_entry,
f"{selector.short_name}_{config_entry.unique_id}",
selector,
coordinator,
hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR],
)
)

View file

@ -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

View file

@ -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."""