diff --git a/homeassistant/components/xiaomi_miio/__init__.py b/homeassistant/components/xiaomi_miio/__init__.py index a1ea7565dab..157199e977a 100644 --- a/homeassistant/components/xiaomi_miio/__init__.py +++ b/homeassistant/components/xiaomi_miio/__init__.py @@ -13,7 +13,12 @@ from miio import ( AirPurifierMiot, DeviceException, Fan, + Fan1C, FanP5, + FanP9, + FanP10, + FanP11, + FanZA5, ) from miio.gateway.gateway import GatewayException @@ -33,7 +38,12 @@ from .const import ( KEY_COORDINATOR, KEY_DEVICE, MODEL_AIRPURIFIER_3C, + MODEL_FAN_1C, MODEL_FAN_P5, + MODEL_FAN_P9, + MODEL_FAN_P10, + MODEL_FAN_P11, + MODEL_FAN_ZA5, MODELS_AIR_MONITOR, MODELS_FAN, MODELS_FAN_MIIO, @@ -52,7 +62,7 @@ _LOGGER = logging.getLogger(__name__) GATEWAY_PLATFORMS = ["alarm_control_panel", "light", "sensor", "switch"] SWITCH_PLATFORMS = ["switch"] -FAN_PLATFORMS = ["fan", "number", "select", "sensor", "switch"] +FAN_PLATFORMS = ["binary_sensor", "fan", "number", "select", "sensor", "switch"] HUMIDIFIER_PLATFORMS = [ "binary_sensor", "humidifier", @@ -65,6 +75,15 @@ LIGHT_PLATFORMS = ["light"] VACUUM_PLATFORMS = ["vacuum"] AIR_MONITOR_PLATFORMS = ["air_quality", "sensor"] +MODEL_TO_CLASS_MAP = { + MODEL_FAN_1C: Fan1C, + MODEL_FAN_P10: FanP10, + MODEL_FAN_P11: FanP11, + MODEL_FAN_P5: FanP5, + MODEL_FAN_P9: FanP9, + MODEL_FAN_ZA5: FanZA5, +} + async def async_setup_entry( hass: core.HomeAssistant, entry: config_entries.ConfigEntry @@ -150,8 +169,8 @@ async def async_create_miio_device_and_coordinator( elif model.startswith("zhimi.airfresh."): device = AirFresh(host, token) # Pedestal fans - elif model == MODEL_FAN_P5: - device = FanP5(host, token) + elif model in MODEL_TO_CLASS_MAP: + device = MODEL_TO_CLASS_MAP[model](host, token) elif model in MODELS_FAN_MIIO: device = Fan(host, token, model=model) else: diff --git a/homeassistant/components/xiaomi_miio/binary_sensor.py b/homeassistant/components/xiaomi_miio/binary_sensor.py index 6254c00916e..a91f06d1194 100644 --- a/homeassistant/components/xiaomi_miio/binary_sensor.py +++ b/homeassistant/components/xiaomi_miio/binary_sensor.py @@ -7,6 +7,7 @@ from typing import Callable from homeassistant.components.binary_sensor import ( DEVICE_CLASS_CONNECTIVITY, + DEVICE_CLASS_PLUG, BinarySensorEntity, BinarySensorEntityDescription, ) @@ -18,6 +19,7 @@ from .const import ( DOMAIN, KEY_COORDINATOR, KEY_DEVICE, + MODEL_FAN_ZA5, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, MODELS_HUMIDIFIER_MJJSQ, @@ -25,6 +27,7 @@ from .const import ( from .device import XiaomiCoordinatedMiioEntity ATTR_NO_WATER = "no_water" +ATTR_POWERSUPPLY_ATTACHED = "powersupply_attached" ATTR_WATER_TANK_DETACHED = "water_tank_detached" @@ -48,8 +51,14 @@ BINARY_SENSOR_TYPES = ( device_class=DEVICE_CLASS_CONNECTIVITY, value=lambda value: not value, ), + XiaomiMiioBinarySensorDescription( + key=ATTR_POWERSUPPLY_ATTACHED, + name="Power Supply", + device_class=DEVICE_CLASS_PLUG, + ), ) +FAN_ZA5_BINARY_SENSORS = (ATTR_POWERSUPPLY_ATTACHED,) HUMIDIFIER_MIIO_BINARY_SENSORS = (ATTR_WATER_TANK_DETACHED,) HUMIDIFIER_MIOT_BINARY_SENSORS = (ATTR_WATER_TANK_DETACHED,) HUMIDIFIER_MJJSQ_BINARY_SENSORS = (ATTR_NO_WATER, ATTR_WATER_TANK_DETACHED) @@ -62,7 +71,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities): if config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE: model = config_entry.data[CONF_MODEL] sensors = [] - if model in MODELS_HUMIDIFIER_MIIO: + if model in MODEL_FAN_ZA5: + sensors = FAN_ZA5_BINARY_SENSORS + elif model in MODELS_HUMIDIFIER_MIIO: sensors = HUMIDIFIER_MIIO_BINARY_SENSORS elif model in MODELS_HUMIDIFIER_MIOT: sensors = HUMIDIFIER_MIOT_BINARY_SENSORS diff --git a/homeassistant/components/xiaomi_miio/const.py b/homeassistant/components/xiaomi_miio/const.py index 29c740cf800..cda65bdf0aa 100644 --- a/homeassistant/components/xiaomi_miio/const.py +++ b/homeassistant/components/xiaomi_miio/const.py @@ -59,13 +59,18 @@ MODEL_AIRHUMIDIFIER_MJJSQ = "deerma.humidifier.mjjsq" MODEL_AIRFRESH_VA2 = "zhimi.airfresh.va2" +MODEL_FAN_1C = "dmaker.fan.1c" +MODEL_FAN_P10 = "dmaker.fan.p10" +MODEL_FAN_P11 = "dmaker.fan.p11" MODEL_FAN_P5 = "dmaker.fan.p5" +MODEL_FAN_P9 = "dmaker.fan.p9" MODEL_FAN_SA1 = "zhimi.fan.sa1" MODEL_FAN_V2 = "zhimi.fan.v2" MODEL_FAN_V3 = "zhimi.fan.v3" MODEL_FAN_ZA1 = "zhimi.fan.za1" MODEL_FAN_ZA3 = "zhimi.fan.za3" MODEL_FAN_ZA4 = "zhimi.fan.za4" +MODEL_FAN_ZA5 = "zhimi.fan.za5" MODELS_FAN_MIIO = [ MODEL_FAN_P5, @@ -77,6 +82,14 @@ MODELS_FAN_MIIO = [ MODEL_FAN_ZA4, ] +MODELS_FAN_MIOT = [ + MODEL_FAN_1C, + MODEL_FAN_P10, + MODEL_FAN_P11, + MODEL_FAN_P9, + MODEL_FAN_ZA5, +] + MODELS_PURIFIER_MIOT = [ MODEL_AIRPURIFIER_3, MODEL_AIRPURIFIER_3C, @@ -151,7 +164,9 @@ MODELS_SWITCH = [ "chuangmi.plug.hmi205", "chuangmi.plug.hmi206", ] -MODELS_FAN = MODELS_PURIFIER_MIIO + MODELS_PURIFIER_MIOT + MODELS_FAN_MIIO +MODELS_FAN = ( + MODELS_PURIFIER_MIIO + MODELS_PURIFIER_MIOT + MODELS_FAN_MIIO + MODELS_FAN_MIOT +) MODELS_HUMIDIFIER = ( MODELS_HUMIDIFIER_MIOT + MODELS_HUMIDIFIER_MIIO + MODELS_HUMIDIFIER_MJJSQ ) @@ -236,10 +251,10 @@ FEATURE_SET_FAN_LEVEL = 4096 FEATURE_SET_MOTOR_SPEED = 8192 FEATURE_SET_CLEAN = 16384 FEATURE_SET_OSCILLATION_ANGLE = 32768 -FEATURE_SET_OSCILLATION_ANGLE_MAX_140 = 65536 -FEATURE_SET_DELAY_OFF_COUNTDOWN = 131072 -FEATURE_SET_LED_BRIGHTNESS_LEVEL = 262144 -FEATURE_SET_FAVORITE_RPM = 524288 +FEATURE_SET_DELAY_OFF_COUNTDOWN = 65536 +FEATURE_SET_LED_BRIGHTNESS_LEVEL = 131072 +FEATURE_SET_FAVORITE_RPM = 262144 +FEATURE_SET_IONIZER = 524288 FEATURE_FLAGS_AIRPURIFIER_MIIO = ( FEATURE_SET_BUZZER @@ -324,7 +339,7 @@ FEATURE_FLAGS_AIRFRESH = ( FEATURE_FLAGS_FAN_P5 = ( FEATURE_SET_BUZZER | FEATURE_SET_CHILD_LOCK - | FEATURE_SET_OSCILLATION_ANGLE_MAX_140 + | FEATURE_SET_OSCILLATION_ANGLE | FEATURE_SET_LED | FEATURE_SET_DELAY_OFF_COUNTDOWN ) @@ -336,3 +351,35 @@ FEATURE_FLAGS_FAN = ( | FEATURE_SET_LED_BRIGHTNESS | FEATURE_SET_DELAY_OFF_COUNTDOWN ) + +FEATURE_FLAGS_FAN_ZA5 = ( + FEATURE_SET_BUZZER + | FEATURE_SET_CHILD_LOCK + | FEATURE_SET_OSCILLATION_ANGLE + | FEATURE_SET_LED_BRIGHTNESS + | FEATURE_SET_DELAY_OFF_COUNTDOWN + | FEATURE_SET_IONIZER +) + +FEATURE_FLAGS_FAN_1C = ( + FEATURE_SET_BUZZER + | FEATURE_SET_CHILD_LOCK + | FEATURE_SET_LED + | FEATURE_SET_DELAY_OFF_COUNTDOWN +) + +FEATURE_FLAGS_FAN_P9 = ( + FEATURE_SET_BUZZER + | FEATURE_SET_CHILD_LOCK + | FEATURE_SET_OSCILLATION_ANGLE + | FEATURE_SET_LED + | FEATURE_SET_DELAY_OFF_COUNTDOWN +) + +FEATURE_FLAGS_FAN_P10_P11 = ( + FEATURE_SET_BUZZER + | FEATURE_SET_CHILD_LOCK + | FEATURE_SET_OSCILLATION_ANGLE + | FEATURE_SET_LED + | FEATURE_SET_DELAY_OFF_COUNTDOWN +) diff --git a/homeassistant/components/xiaomi_miio/fan.py b/homeassistant/components/xiaomi_miio/fan.py index b5aa0cce780..1b275ea2d6e 100644 --- a/homeassistant/components/xiaomi_miio/fan.py +++ b/homeassistant/components/xiaomi_miio/fan.py @@ -11,6 +11,10 @@ from miio.fan import ( MoveDirection as FanMoveDirection, OperationMode as FanOperationMode, ) +from miio.fan_miot import ( + OperationMode as FanMiotOperationMode, + OperationModeFanZA5 as FanZA5OperationMode, +) import voluptuous as vol from homeassistant.components.fan import ( @@ -41,7 +45,11 @@ from .const import ( FEATURE_FLAGS_AIRPURIFIER_PRO_V7, FEATURE_FLAGS_AIRPURIFIER_V3, FEATURE_FLAGS_FAN, + FEATURE_FLAGS_FAN_1C, FEATURE_FLAGS_FAN_P5, + FEATURE_FLAGS_FAN_P9, + FEATURE_FLAGS_FAN_P10_P11, + FEATURE_FLAGS_FAN_ZA5, FEATURE_RESET_FILTER, FEATURE_SET_EXTRA_FEATURES, KEY_COORDINATOR, @@ -52,8 +60,14 @@ from .const import ( MODEL_AIRPURIFIER_PRO, MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V3, + MODEL_FAN_1C, MODEL_FAN_P5, + MODEL_FAN_P9, + MODEL_FAN_P10, + MODEL_FAN_P11, + MODEL_FAN_ZA5, MODELS_FAN_MIIO, + MODELS_FAN_MIOT, MODELS_PURIFIER_MIOT, SERVICE_RESET_FILTER, SERVICE_SET_EXTRA_FEATURES, @@ -197,6 +211,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entity = XiaomiFanP5(name, device, config_entry, unique_id, coordinator) elif model in MODELS_FAN_MIIO: entity = XiaomiFan(name, device, config_entry, unique_id, coordinator) + elif model == MODEL_FAN_ZA5: + entity = XiaomiFanZA5(name, device, config_entry, unique_id, coordinator) + elif model in MODELS_FAN_MIOT: + entity = XiaomiFanMiot(name, device, config_entry, unique_id, coordinator) else: return @@ -264,6 +282,11 @@ class XiaomiGenericDevice(XiaomiCoordinatedMiioEntity, FanEntity): """Flag supported features.""" return self._supported_features + @property + @abstractmethod + def operation_mode_class(self): + """Hold operation mode class.""" + @property def preset_modes(self) -> list: """Get the list of available preset modes.""" @@ -326,11 +349,6 @@ class XiaomiGenericAirPurifier(XiaomiGenericDevice): self._speed_count = 100 - @property - @abstractmethod - def operation_mode_class(self): - """Hold operation mode class.""" - @property def speed_count(self): """Return the number of speeds of the fan supported.""" @@ -695,16 +713,21 @@ class XiaomiGenericFan(XiaomiGenericDevice): if self._model == MODEL_FAN_P5: self._device_features = FEATURE_FLAGS_FAN_P5 - self._preset_modes = [mode.name for mode in FanOperationMode] + elif self._model == MODEL_FAN_ZA5: + self._device_features = FEATURE_FLAGS_FAN_ZA5 + elif self._model == MODEL_FAN_1C: + self._device_features = FEATURE_FLAGS_FAN_1C + elif self._model == MODEL_FAN_P9: + self._device_features = FEATURE_FLAGS_FAN_P9 + elif self._model in (MODEL_FAN_P10, MODEL_FAN_P11): + self._device_features = FEATURE_FLAGS_FAN_P10_P11 else: self._device_features = FEATURE_FLAGS_FAN - self._preset_modes = [ATTR_MODE_NATURE, ATTR_MODE_NORMAL] self._supported_features = ( - SUPPORT_SET_SPEED - | SUPPORT_OSCILLATE - | SUPPORT_PRESET_MODE - | SUPPORT_DIRECTION + SUPPORT_SET_SPEED | SUPPORT_OSCILLATE | SUPPORT_PRESET_MODE ) + if self._model != MODEL_FAN_1C: + self._supported_features |= SUPPORT_DIRECTION self._preset_mode = None self._oscillating = None self._percentage = None @@ -714,6 +737,11 @@ class XiaomiGenericFan(XiaomiGenericDevice): """Get the active preset mode.""" return self._preset_mode + @property + def preset_modes(self) -> list: + """Get the list of available preset modes.""" + return [mode.name for mode in self.operation_mode_class] + @property def percentage(self): """Return the current speed as a percentage.""" @@ -764,11 +792,20 @@ class XiaomiFan(XiaomiGenericFan): else: self._percentage = self.coordinator.data.direct_speed + @property + def operation_mode_class(self): + """Hold operation mode class.""" + @property def preset_mode(self): """Get the active preset mode.""" return ATTR_MODE_NATURE if self._nature_mode else ATTR_MODE_NORMAL + @property + def preset_modes(self) -> list: + """Get the list of available preset modes.""" + return [ATTR_MODE_NATURE, ATTR_MODE_NORMAL] + @callback def _handle_coordinator_update(self): """Fetch state from the device.""" @@ -843,6 +880,11 @@ class XiaomiFanP5(XiaomiGenericFan): self._oscillating = self.coordinator.data.oscillate self._percentage = self.coordinator.data.speed + @property + def operation_mode_class(self): + """Hold operation mode class.""" + return FanOperationMode + @callback def _handle_coordinator_update(self): """Fetch state from the device.""" @@ -861,7 +903,7 @@ class XiaomiFanP5(XiaomiGenericFan): await self._try_command( "Setting operation mode of the miio device failed.", self._device.set_mode, - FanOperationMode[preset_mode], + self.operation_mode_class[preset_mode], ) self._preset_mode = preset_mode self.async_write_ha_state() @@ -884,3 +926,71 @@ class XiaomiFanP5(XiaomiGenericFan): await self.async_turn_on() else: self.async_write_ha_state() + + +class XiaomiFanMiot(XiaomiGenericFan): + """Representation of a Xiaomi Fan Miot.""" + + @property + def operation_mode_class(self): + """Hold operation mode class.""" + return FanMiotOperationMode + + @property + def preset_mode(self): + """Get the active preset mode.""" + return self._preset_mode + + @callback + def _handle_coordinator_update(self): + """Fetch state from the device.""" + self._state = self.coordinator.data.is_on + self._preset_mode = self.coordinator.data.mode.name + self._oscillating = self.coordinator.data.oscillate + if self.coordinator.data.is_on: + self._percentage = self.coordinator.data.fan_speed + else: + self._percentage = 0 + + self.async_write_ha_state() + + async def async_set_preset_mode(self, preset_mode: str) -> None: + """Set the preset mode of the fan.""" + if preset_mode not in self.preset_modes: + _LOGGER.warning("'%s'is not a valid preset mode", preset_mode) + return + await self._try_command( + "Setting operation mode of the miio device failed.", + self._device.set_mode, + self.operation_mode_class[preset_mode], + ) + self._preset_mode = preset_mode + self.async_write_ha_state() + + async def async_set_percentage(self, percentage: int) -> None: + """Set the percentage of the fan.""" + if percentage == 0: + self._percentage = 0 + await self.async_turn_off() + return + + await self._try_command( + "Setting fan speed percentage of the miio device failed.", + self._device.set_speed, + percentage, + ) + self._percentage = percentage + + if not self.is_on: + await self.async_turn_on() + else: + self.async_write_ha_state() + + +class XiaomiFanZA5(XiaomiFanMiot): + """Representation of a Xiaomi Fan ZA5.""" + + @property + def operation_mode_class(self): + """Hold operation mode class.""" + return FanZA5OperationMode diff --git a/homeassistant/components/xiaomi_miio/number.py b/homeassistant/components/xiaomi_miio/number.py index 2547c33bbfa..a915ce57847 100644 --- a/homeassistant/components/xiaomi_miio/number.py +++ b/homeassistant/components/xiaomi_miio/number.py @@ -25,7 +25,11 @@ from .const import ( FEATURE_FLAGS_AIRPURIFIER_V1, FEATURE_FLAGS_AIRPURIFIER_V3, FEATURE_FLAGS_FAN, + FEATURE_FLAGS_FAN_1C, FEATURE_FLAGS_FAN_P5, + FEATURE_FLAGS_FAN_P9, + FEATURE_FLAGS_FAN_P10_P11, + FEATURE_FLAGS_FAN_ZA5, FEATURE_SET_DELAY_OFF_COUNTDOWN, FEATURE_SET_FAN_LEVEL, FEATURE_SET_FAVORITE_LEVEL, @@ -33,7 +37,6 @@ from .const import ( FEATURE_SET_LED_BRIGHTNESS_LEVEL, FEATURE_SET_MOTOR_SPEED, FEATURE_SET_OSCILLATION_ANGLE, - FEATURE_SET_OSCILLATION_ANGLE_MAX_140, FEATURE_SET_VOLUME, KEY_COORDINATOR, KEY_DEVICE, @@ -47,13 +50,18 @@ from .const import ( MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V3, + MODEL_FAN_1C, MODEL_FAN_P5, + MODEL_FAN_P9, + MODEL_FAN_P10, + MODEL_FAN_P11, MODEL_FAN_SA1, MODEL_FAN_V2, MODEL_FAN_V3, MODEL_FAN_ZA1, MODEL_FAN_ZA3, MODEL_FAN_ZA4, + MODEL_FAN_ZA5, MODELS_PURIFIER_MIIO, MODELS_PURIFIER_MIOT, ) @@ -80,6 +88,15 @@ class XiaomiMiioNumberDescription(NumberEntityDescription): method: str | None = None +@dataclass +class OscillationAngleValues: + """A class that describes oscillation angle values.""" + + max_value: float | None = None + min_value: float | None = None + step: float | None = None + + NUMBER_TYPES = { FEATURE_SET_MOTOR_SPEED: XiaomiMiioNumberDescription( key=ATTR_MOTOR_SPEED, @@ -129,16 +146,6 @@ NUMBER_TYPES = { step=1, method="async_set_oscillation_angle", ), - FEATURE_SET_OSCILLATION_ANGLE_MAX_140: XiaomiMiioNumberDescription( - key=ATTR_OSCILLATION_ANGLE, - name="Oscillation Angle", - icon="mdi:angle-acute", - unit_of_measurement=DEGREE, - min_value=30, - max_value=140, - step=30, - method="async_set_oscillation_angle", - ), FEATURE_SET_DELAY_OFF_COUNTDOWN: XiaomiMiioNumberDescription( key=ATTR_DELAY_OFF_COUNTDOWN, name="Delay Off Countdown", @@ -181,13 +188,26 @@ MODEL_TO_FEATURES_MAP = { MODEL_AIRPURIFIER_PRO_V7: FEATURE_FLAGS_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V1: FEATURE_FLAGS_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V3: FEATURE_FLAGS_AIRPURIFIER_V3, + MODEL_FAN_1C: FEATURE_FLAGS_FAN_1C, + MODEL_FAN_P10: FEATURE_FLAGS_FAN_P10_P11, + MODEL_FAN_P11: FEATURE_FLAGS_FAN_P10_P11, MODEL_FAN_P5: FEATURE_FLAGS_FAN_P5, + MODEL_FAN_P9: FEATURE_FLAGS_FAN_P9, MODEL_FAN_SA1: FEATURE_FLAGS_FAN, MODEL_FAN_V2: FEATURE_FLAGS_FAN, MODEL_FAN_V3: FEATURE_FLAGS_FAN, MODEL_FAN_ZA1: FEATURE_FLAGS_FAN, MODEL_FAN_ZA3: FEATURE_FLAGS_FAN, MODEL_FAN_ZA4: FEATURE_FLAGS_FAN, + MODEL_FAN_ZA5: FEATURE_FLAGS_FAN_ZA5, +} + +OSCILLATION_ANGLE_VALUES = { + MODEL_FAN_P5: OscillationAngleValues(max_value=140, min_value=30, step=30), + MODEL_FAN_ZA5: OscillationAngleValues(max_value=120, min_value=30, step=30), + MODEL_FAN_P9: OscillationAngleValues(max_value=150, min_value=30, step=30), + MODEL_FAN_P10: OscillationAngleValues(max_value=140, min_value=30, step=30), + MODEL_FAN_P11: OscillationAngleValues(max_value=140, min_value=30, step=30), } @@ -210,6 +230,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities): for feature, description in NUMBER_TYPES.items(): if feature & features: + if ( + description.key == ATTR_OSCILLATION_ANGLE + and model in OSCILLATION_ANGLE_VALUES + ): + description.max_value = OSCILLATION_ANGLE_VALUES[model].max_value + description.min_value = OSCILLATION_ANGLE_VALUES[model].min_value + description.step = OSCILLATION_ANGLE_VALUES[model].step entities.append( XiaomiNumberEntity( f"{config_entry.title} {description.name}", diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index 7e2a5d230cd..d199c051eae 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -68,6 +68,7 @@ from .const import ( MODEL_FAN_ZA1, MODEL_FAN_ZA3, MODEL_FAN_ZA4, + MODEL_FAN_ZA5, MODELS_AIR_QUALITY_MONITOR, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, @@ -331,6 +332,8 @@ FAN_V2_V3_SENSORS = ( ATTR_TEMPERATURE, ) +FAN_ZA5_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE) + MODEL_TO_SENSORS_MAP = { MODEL_AIRFRESH_VA2: AIRFRESH_SENSORS, MODEL_AIRHUMIDIFIER_CA1: HUMIDIFIER_CA1_CB1_SENSORS, @@ -342,6 +345,7 @@ MODEL_TO_SENSORS_MAP = { MODEL_AIRPURIFIER_V3: PURIFIER_V3_SENSORS, MODEL_FAN_V2: FAN_V2_V3_SENSORS, MODEL_FAN_V3: FAN_V2_V3_SENSORS, + MODEL_FAN_ZA5: FAN_ZA5_SENSORS, } diff --git a/homeassistant/components/xiaomi_miio/switch.py b/homeassistant/components/xiaomi_miio/switch.py index 30854d65101..fd9d4053313 100644 --- a/homeassistant/components/xiaomi_miio/switch.py +++ b/homeassistant/components/xiaomi_miio/switch.py @@ -46,12 +46,17 @@ from .const import ( FEATURE_FLAGS_AIRPURIFIER_V1, FEATURE_FLAGS_AIRPURIFIER_V3, FEATURE_FLAGS_FAN, + FEATURE_FLAGS_FAN_1C, FEATURE_FLAGS_FAN_P5, + FEATURE_FLAGS_FAN_P9, + FEATURE_FLAGS_FAN_P10_P11, + FEATURE_FLAGS_FAN_ZA5, FEATURE_SET_AUTO_DETECT, FEATURE_SET_BUZZER, FEATURE_SET_CHILD_LOCK, FEATURE_SET_CLEAN, FEATURE_SET_DRY, + FEATURE_SET_IONIZER, FEATURE_SET_LEARN_MODE, FEATURE_SET_LED, KEY_COORDINATOR, @@ -67,10 +72,15 @@ from .const import ( MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V3, + MODEL_FAN_1C, MODEL_FAN_P5, + MODEL_FAN_P9, + MODEL_FAN_P10, + MODEL_FAN_P11, MODEL_FAN_ZA1, MODEL_FAN_ZA3, MODEL_FAN_ZA4, + MODEL_FAN_ZA5, MODELS_FAN, MODELS_HUMIDIFIER, MODELS_HUMIDIFIER_MJJSQ, @@ -108,6 +118,7 @@ ATTR_CLEAN = "clean_mode" ATTR_DRY = "dry" ATTR_LEARN_MODE = "learn_mode" ATTR_LED = "led" +ATTR_IONIZER = "ionizer" ATTR_LOAD_POWER = "load_power" ATTR_MODEL = "model" ATTR_POWER = "power" @@ -165,10 +176,15 @@ MODEL_TO_FEATURES_MAP = { MODEL_AIRPURIFIER_PRO_V7: FEATURE_FLAGS_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V1: FEATURE_FLAGS_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V3: FEATURE_FLAGS_AIRPURIFIER_V3, + MODEL_FAN_1C: FEATURE_FLAGS_FAN_1C, + MODEL_FAN_P10: FEATURE_FLAGS_FAN_P10_P11, + MODEL_FAN_P11: FEATURE_FLAGS_FAN_P10_P11, MODEL_FAN_P5: FEATURE_FLAGS_FAN_P5, + MODEL_FAN_P9: FEATURE_FLAGS_FAN_P9, MODEL_FAN_ZA1: FEATURE_FLAGS_FAN, MODEL_FAN_ZA3: FEATURE_FLAGS_FAN, MODEL_FAN_ZA4: FEATURE_FLAGS_FAN, + MODEL_FAN_ZA5: FEATURE_FLAGS_FAN_ZA5, } @@ -239,6 +255,14 @@ SWITCH_TYPES = ( method_on="async_set_auto_detect_on", method_off="async_set_auto_detect_off", ), + XiaomiMiioSwitchDescription( + key=ATTR_IONIZER, + feature=FEATURE_SET_IONIZER, + name="Ionizer", + icon="mdi:shimmer", + method_on="async_set_ionizer_on", + method_off="async_set_ionizer_off", + ), ) @@ -578,6 +602,22 @@ class XiaomiGenericCoordinatedSwitch(XiaomiCoordinatedMiioEntity, SwitchEntity): False, ) + async def async_set_ionizer_on(self) -> bool: + """Turn ionizer on.""" + return await self._try_command( + "Turning ionizer of the miio device on failed.", + self._device.set_ionizer, + True, + ) + + async def async_set_ionizer_off(self) -> bool: + """Turn ionizer off.""" + return await self._try_command( + "Turning ionizer of the miio device off failed.", + self._device.set_ionizer, + False, + ) + class XiaomiGatewaySwitch(XiaomiGatewayDevice, SwitchEntity): """Representation of a XiaomiGatewaySwitch."""