diff --git a/CODEOWNERS b/CODEOWNERS index d3c1dc4d33d..121d1875202 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -585,7 +585,7 @@ homeassistant/components/worldclock/* @fabaff homeassistant/components/xbox/* @hunterjm homeassistant/components/xbox_live/* @MartinHjelmare homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi -homeassistant/components/xiaomi_miio/* @rytilahti @syssi @starkillerOG +homeassistant/components/xiaomi_miio/* @rytilahti @syssi @starkillerOG @bieniu homeassistant/components/xiaomi_tv/* @simse homeassistant/components/xmpp/* @fabaff @flowolf homeassistant/components/yale_smart_alarm/* @gjohansson-ST diff --git a/homeassistant/components/xiaomi_miio/__init__.py b/homeassistant/components/xiaomi_miio/__init__.py index 0559cab9461..cde597432df 100644 --- a/homeassistant/components/xiaomi_miio/__init__.py +++ b/homeassistant/components/xiaomi_miio/__init__.py @@ -11,6 +11,8 @@ from miio import ( AirPurifier, AirPurifierMiot, DeviceException, + Fan, + FanP5, ) from miio.gateway.gateway import GatewayException @@ -29,8 +31,10 @@ from .const import ( DOMAIN, KEY_COORDINATOR, KEY_DEVICE, + MODEL_FAN_P5, MODELS_AIR_MONITOR, MODELS_FAN, + MODELS_FAN_MIIO, MODELS_HUMIDIFIER, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, @@ -141,6 +145,11 @@ async def async_create_miio_device_and_coordinator( device = AirPurifier(host, token) elif model.startswith("zhimi.airfresh."): device = AirFresh(host, token) + # Pedestal fans + elif model == MODEL_FAN_P5: + device = FanP5(host, token) + elif model in MODELS_FAN_MIIO: + device = Fan(host, token, model=model) else: _LOGGER.error( "Unsupported device found! Please create an issue at " diff --git a/homeassistant/components/xiaomi_miio/const.py b/homeassistant/components/xiaomi_miio/const.py index af32e8daafa..b670582c069 100644 --- a/homeassistant/components/xiaomi_miio/const.py +++ b/homeassistant/components/xiaomi_miio/const.py @@ -58,6 +58,24 @@ MODEL_AIRHUMIDIFIER_MJJSQ = "deerma.humidifier.mjjsq" MODEL_AIRFRESH_VA2 = "zhimi.airfresh.va2" +MODEL_FAN_P5 = "dmaker.fan.p5" +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" + +MODELS_FAN_MIIO = [ + MODEL_FAN_P5, + MODEL_FAN_SA1, + MODEL_FAN_V2, + MODEL_FAN_V3, + MODEL_FAN_ZA1, + MODEL_FAN_ZA3, + MODEL_FAN_ZA4, +] + MODELS_PURIFIER_MIOT = [ MODEL_AIRPURIFIER_3, MODEL_AIRPURIFIER_3H, @@ -124,7 +142,7 @@ MODELS_SWITCH = [ "chuangmi.plug.hmi205", "chuangmi.plug.hmi206", ] -MODELS_FAN = MODELS_PURIFIER_MIIO + MODELS_PURIFIER_MIOT +MODELS_FAN = MODELS_PURIFIER_MIIO + MODELS_PURIFIER_MIOT + MODELS_FAN_MIIO MODELS_HUMIDIFIER = ( MODELS_HUMIDIFIER_MIOT + MODELS_HUMIDIFIER_MIIO + MODELS_HUMIDIFIER_MJJSQ ) @@ -208,6 +226,9 @@ FEATURE_SET_DRY = 2048 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_FLAGS_AIRPURIFIER_MIIO = ( FEATURE_SET_BUZZER @@ -281,3 +302,19 @@ FEATURE_FLAGS_AIRFRESH = ( | FEATURE_RESET_FILTER | FEATURE_SET_EXTRA_FEATURES ) + +FEATURE_FLAGS_FAN_P5 = ( + FEATURE_SET_BUZZER + | FEATURE_SET_CHILD_LOCK + | FEATURE_SET_OSCILLATION_ANGLE_MAX_140 + | FEATURE_SET_LED + | FEATURE_SET_DELAY_OFF_COUNTDOWN +) + +FEATURE_FLAGS_FAN = ( + FEATURE_SET_BUZZER + | FEATURE_SET_CHILD_LOCK + | FEATURE_SET_OSCILLATION_ANGLE + | FEATURE_SET_LED_BRIGHTNESS + | FEATURE_SET_DELAY_OFF_COUNTDOWN +) diff --git a/homeassistant/components/xiaomi_miio/fan.py b/homeassistant/components/xiaomi_miio/fan.py index 0d22dad32ea..19d85ced2dc 100644 --- a/homeassistant/components/xiaomi_miio/fan.py +++ b/homeassistant/components/xiaomi_miio/fan.py @@ -7,9 +7,15 @@ import math from miio.airfresh import OperationMode as AirfreshOperationMode from miio.airpurifier import OperationMode as AirpurifierOperationMode from miio.airpurifier_miot import OperationMode as AirpurifierMiotOperationMode +from miio.fan import ( + MoveDirection as FanMoveDirection, + OperationMode as FanOperationMode, +) import voluptuous as vol from homeassistant.components.fan import ( + SUPPORT_DIRECTION, + SUPPORT_OSCILLATE, SUPPORT_PRESET_MODE, SUPPORT_SET_SPEED, FanEntity, @@ -33,6 +39,8 @@ from .const import ( FEATURE_FLAGS_AIRPURIFIER_PRO, FEATURE_FLAGS_AIRPURIFIER_PRO_V7, FEATURE_FLAGS_AIRPURIFIER_V3, + FEATURE_FLAGS_FAN, + FEATURE_FLAGS_FAN_P5, FEATURE_RESET_FILTER, FEATURE_SET_EXTRA_FEATURES, KEY_COORDINATOR, @@ -42,6 +50,8 @@ from .const import ( MODEL_AIRPURIFIER_PRO, MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V3, + MODEL_FAN_P5, + MODELS_FAN_MIIO, MODELS_PURIFIER_MIOT, SERVICE_RESET_FILTER, SERVICE_SET_EXTRA_FEATURES, @@ -57,6 +67,9 @@ CONF_MODEL = "model" ATTR_MODEL = "model" +ATTR_MODE_NATURE = "Nature" +ATTR_MODE_NORMAL = "Normal" + # Air Purifier ATTR_BRIGHTNESS = "brightness" ATTR_FAN_LEVEL = "fan_level" @@ -159,6 +172,11 @@ SERVICE_TO_METHOD = { }, } +FAN_DIRECTIONS_MAP = { + "forward": "right", + "reverse": "left", +} + async def async_setup_entry(hass, config_entry, async_add_entities): """Set up the Fan from a config entry.""" @@ -187,6 +205,10 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entity = XiaomiAirPurifier(name, device, config_entry, unique_id, coordinator) elif model.startswith("zhimi.airfresh."): entity = XiaomiAirFresh(name, device, config_entry, unique_id, coordinator) + elif model == MODEL_FAN_P5: + entity = XiaomiFanP5(name, device, config_entry, unique_id, coordinator) + elif model in MODELS_FAN_MIIO: + entity = XiaomiFan(name, device, config_entry, unique_id, coordinator) else: return @@ -669,3 +691,184 @@ class XiaomiAirFresh(XiaomiGenericDevice): "Resetting the filter lifetime of the miio device failed.", self._device.reset_filter, ) + + +class XiaomiFan(XiaomiGenericDevice): + """Representation of a Xiaomi Fan.""" + + def __init__(self, name, device, entry, unique_id, coordinator): + """Initialize the plug switch.""" + super().__init__(name, device, entry, unique_id, coordinator) + + if self._model == MODEL_FAN_P5: + self._device_features = FEATURE_FLAGS_FAN_P5 + self._preset_modes = [mode.name for mode in FanOperationMode] + else: + self._device_features = FEATURE_FLAGS_FAN + self._preset_modes = [ATTR_MODE_NATURE, ATTR_MODE_NORMAL] + self._nature_mode = False + self._supported_features = ( + SUPPORT_SET_SPEED + | SUPPORT_OSCILLATE + | SUPPORT_PRESET_MODE + | SUPPORT_DIRECTION + ) + self._preset_mode = None + self._oscillating = None + self._percentage = None + + @property + def preset_mode(self): + """Get the active preset mode.""" + return ATTR_MODE_NATURE if self._nature_mode else ATTR_MODE_NORMAL + + @property + def percentage(self): + """Return the current speed as a percentage.""" + return self._percentage + + @property + def oscillating(self): + """Return whether or not the fan is currently oscillating.""" + return self._oscillating + + @callback + def _handle_coordinator_update(self): + """Fetch state from the device.""" + self._available = True + self._state = self.coordinator.data.is_on + self._oscillating = self.coordinator.data.oscillate + self._nature_mode = self.coordinator.data.natural_speed != 0 + if self.coordinator.data.is_on: + if self._nature_mode: + self._percentage = self.coordinator.data.natural_speed + else: + self._percentage = self.coordinator.data.direct_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 + + if preset_mode == ATTR_MODE_NATURE: + await self._try_command( + "Setting natural fan speed percentage of the miio device failed.", + self._device.set_natural_speed, + self._percentage, + ) + else: + await self._try_command( + "Setting direct fan speed percentage of the miio device failed.", + self._device.set_direct_speed, + self._percentage, + ) + + 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 + + if self._nature_mode: + await self._try_command( + "Setting fan speed percentage of the miio device failed.", + self._device.set_natural_speed, + percentage, + ) + else: + await self._try_command( + "Setting fan speed percentage of the miio device failed.", + self._device.set_direct_speed, + percentage, + ) + self._percentage = percentage + + if not self.is_on: + await self.async_turn_on() + else: + self.async_write_ha_state() + + async def async_oscillate(self, oscillating: bool) -> None: + """Set oscillation.""" + await self._try_command( + "Setting oscillate on/off of the miio device failed.", + self._device.set_oscillate, + oscillating, + ) + self._oscillating = oscillating + self.async_write_ha_state() + + async def async_set_direction(self, direction: str) -> None: + """Set the direction of the fan.""" + if self._oscillating: + await self.async_oscillate(oscillating=False) + + await self._try_command( + "Setting move direction of the miio device failed.", + self._device.set_rotate, + FanMoveDirection(FAN_DIRECTIONS_MAP[direction]), + ) + + +class XiaomiFanP5(XiaomiFan): + """Representation of a Xiaomi Fan P5.""" + + @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._available = True + 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.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, + FanOperationMode[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() diff --git a/homeassistant/components/xiaomi_miio/manifest.json b/homeassistant/components/xiaomi_miio/manifest.json index 6d3c5e50be8..18aa7f75ce1 100644 --- a/homeassistant/components/xiaomi_miio/manifest.json +++ b/homeassistant/components/xiaomi_miio/manifest.json @@ -4,7 +4,7 @@ "config_flow": true, "documentation": "https://www.home-assistant.io/integrations/xiaomi_miio", "requirements": ["construct==2.10.56", "micloud==0.3", "python-miio==0.5.7"], - "codeowners": ["@rytilahti", "@syssi", "@starkillerOG"], + "codeowners": ["@rytilahti", "@syssi", "@starkillerOG", "@bieniu"], "zeroconf": ["_miio._udp.local."], "iot_class": "local_polling" } diff --git a/homeassistant/components/xiaomi_miio/number.py b/homeassistant/components/xiaomi_miio/number.py index e2043be4886..af5f29306a0 100644 --- a/homeassistant/components/xiaomi_miio/number.py +++ b/homeassistant/components/xiaomi_miio/number.py @@ -5,6 +5,7 @@ from dataclasses import dataclass from enum import Enum from homeassistant.components.number import NumberEntity, NumberEntityDescription +from homeassistant.const import DEGREE, TIME_MINUTES from homeassistant.core import callback from .const import ( @@ -22,9 +23,14 @@ from .const import ( FEATURE_FLAGS_AIRPURIFIER_PRO_V7, FEATURE_FLAGS_AIRPURIFIER_V1, FEATURE_FLAGS_AIRPURIFIER_V3, + FEATURE_FLAGS_FAN, + FEATURE_FLAGS_FAN_P5, + FEATURE_SET_DELAY_OFF_COUNTDOWN, FEATURE_SET_FAN_LEVEL, FEATURE_SET_FAVORITE_LEVEL, FEATURE_SET_MOTOR_SPEED, + FEATURE_SET_OSCILLATION_ANGLE, + FEATURE_SET_OSCILLATION_ANGLE_MAX_140, FEATURE_SET_VOLUME, KEY_COORDINATOR, KEY_DEVICE, @@ -37,14 +43,23 @@ from .const import ( MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V3, + MODEL_FAN_P5, + MODEL_FAN_SA1, + MODEL_FAN_V2, + MODEL_FAN_V3, + MODEL_FAN_ZA1, + MODEL_FAN_ZA3, + MODEL_FAN_ZA4, MODELS_PURIFIER_MIIO, MODELS_PURIFIER_MIOT, ) from .device import XiaomiCoordinatedMiioEntity +ATTR_DELAY_OFF_COUNTDOWN = "delay_off_countdown" ATTR_FAN_LEVEL = "fan_level" ATTR_FAVORITE_LEVEL = "favorite_level" ATTR_MOTOR_SPEED = "motor_speed" +ATTR_OSCILLATION_ANGLE = "angle" ATTR_VOLUME = "volume" @@ -98,9 +113,40 @@ NUMBER_TYPES = { step=1, method="async_set_volume", ), + FEATURE_SET_OSCILLATION_ANGLE: XiaomiMiioNumberDescription( + key=ATTR_OSCILLATION_ANGLE, + name="Oscillation Angle", + icon="mdi:angle-acute", + unit_of_measurement=DEGREE, + min_value=1, + max_value=120, + 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", + icon="mdi:fan-off", + unit_of_measurement=TIME_MINUTES, + min_value=0, + max_value=480, + step=1, + method="async_set_delay_off_countdown", + ), } MODEL_TO_FEATURES_MAP = { + MODEL_AIRFRESH_VA2: FEATURE_FLAGS_AIRFRESH, MODEL_AIRHUMIDIFIER_CA1: FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB, MODEL_AIRHUMIDIFIER_CA4: FEATURE_FLAGS_AIRHUMIDIFIER_CA4, MODEL_AIRHUMIDIFIER_CB1: FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB, @@ -109,7 +155,13 @@ 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_AIRFRESH_VA2: FEATURE_FLAGS_AIRFRESH, + MODEL_FAN_P5: FEATURE_FLAGS_FAN_P5, + 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, } @@ -227,3 +279,17 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity): self._device.set_volume, volume, ) + + async def async_set_oscillation_angle(self, angle: int): + """Set the volume.""" + return await self._try_command( + "Setting angle of the miio device failed.", self._device.set_angle, angle + ) + + async def async_set_delay_off_countdown(self, delay_off_countdown: int): + """Set the delay off countdown.""" + return await self._try_command( + "Setting delay off miio device failed.", + self._device.delay_off, + delay_off_countdown * 60, + ) diff --git a/homeassistant/components/xiaomi_miio/select.py b/homeassistant/components/xiaomi_miio/select.py index 9cb57e5d3d8..b43291dfeef 100644 --- a/homeassistant/components/xiaomi_miio/select.py +++ b/homeassistant/components/xiaomi_miio/select.py @@ -9,6 +9,7 @@ from miio.airhumidifier import LedBrightness as AirhumidifierLedBrightness from miio.airhumidifier_miot import LedBrightness as AirhumidifierMiotLedBrightness from miio.airpurifier import LedBrightness as AirpurifierLedBrightness from miio.airpurifier_miot import LedBrightness as AirpurifierMiotLedBrightness +from miio.fan import LedBrightness as FanLedBrightness from homeassistant.components.select import SelectEntity, SelectEntityDescription from homeassistant.core import callback @@ -24,6 +25,12 @@ from .const import ( MODEL_AIRFRESH_VA2, MODEL_AIRPURIFIER_M1, MODEL_AIRPURIFIER_M2, + MODEL_FAN_SA1, + MODEL_FAN_V2, + MODEL_FAN_V3, + MODEL_FAN_ZA1, + MODEL_FAN_ZA3, + MODEL_FAN_ZA4, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, MODELS_PURIFIER_MIOT, @@ -78,6 +85,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities): entity_class = XiaomiAirPurifierMiotSelector elif model == MODEL_AIRFRESH_VA2: entity_class = XiaomiAirFreshSelector + elif model in ( + MODEL_FAN_ZA1, + MODEL_FAN_ZA3, + MODEL_FAN_ZA4, + MODEL_FAN_SA1, + MODEL_FAN_V2, + MODEL_FAN_V3, + ): + entity_class = XiaomiFanSelector else: return @@ -210,6 +226,20 @@ class XiaomiAirPurifierMiotSelector(XiaomiAirHumidifierSelector): self.async_write_ha_state() +class XiaomiFanSelector(XiaomiAirHumidifierSelector): + """Representation of a Xiaomi Fan (MIIO protocol) selector.""" + + async def async_set_led_brightness(self, brightness: str) -> None: + """Set the led brightness.""" + if await self._try_command( + "Setting the led brightness of the miio device failed.", + self._device.set_led_brightness, + FanLedBrightness(LED_BRIGHTNESS_MAP[brightness]), + ): + self._current_led_brightness = LED_BRIGHTNESS_MAP[brightness] + self.async_write_ha_state() + + class XiaomiAirFreshSelector(XiaomiAirHumidifierSelector): """Representation of a Xiaomi Air Fresh selector.""" diff --git a/homeassistant/components/xiaomi_miio/sensor.py b/homeassistant/components/xiaomi_miio/sensor.py index a505c23498c..63535e88a2d 100644 --- a/homeassistant/components/xiaomi_miio/sensor.py +++ b/homeassistant/components/xiaomi_miio/sensor.py @@ -28,6 +28,7 @@ from homeassistant.const import ( CONCENTRATION_PARTS_PER_MILLION, CONF_HOST, CONF_TOKEN, + DEVICE_CLASS_BATTERY, DEVICE_CLASS_CO2, DEVICE_CLASS_GAS, DEVICE_CLASS_HUMIDITY, @@ -59,6 +60,12 @@ from .const import ( MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V2, MODEL_AIRPURIFIER_V3, + MODEL_FAN_P5, + MODEL_FAN_V2, + MODEL_FAN_V3, + MODEL_FAN_ZA1, + MODEL_FAN_ZA3, + MODEL_FAN_ZA4, MODELS_HUMIDIFIER_MIIO, MODELS_HUMIDIFIER_MIOT, MODELS_HUMIDIFIER_MJJSQ, @@ -76,6 +83,7 @@ UNIT_LUMEN = "lm" ATTR_ACTUAL_SPEED = "actual_speed" ATTR_AIR_QUALITY = "air_quality" ATTR_AQI = "aqi" +ATTR_BATTERY = "battery" ATTR_CARBON_DIOXIDE = "co2" ATTR_CHARGING = "charging" ATTR_DISPLAY_CLOCK = "display_clock" @@ -219,6 +227,13 @@ SENSOR_TYPES = { state_class=STATE_CLASS_TOTAL_INCREASING, entity_registry_enabled_default=False, ), + ATTR_BATTERY: XiaomiMiioSensorDescription( + key=ATTR_BATTERY, + name="Battery", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_BATTERY, + state_class=STATE_CLASS_MEASUREMENT, + ), } HUMIDIFIER_MIIO_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE, ATTR_WATER_LEVEL) @@ -301,15 +316,22 @@ AIRFRESH_SENSORS = ( ATTR_PM25, ATTR_TEMPERATURE, ) +FAN_V2_V3_SENSORS = ( + ATTR_BATTERY, + ATTR_HUMIDITY, + ATTR_TEMPERATURE, +) MODEL_TO_SENSORS_MAP = { + MODEL_AIRFRESH_VA2: AIRFRESH_SENSORS, MODEL_AIRHUMIDIFIER_CA1: HUMIDIFIER_CA1_CB1_SENSORS, MODEL_AIRHUMIDIFIER_CB1: HUMIDIFIER_CA1_CB1_SENSORS, + MODEL_AIRPURIFIER_PRO: PURIFIER_PRO_SENSORS, + MODEL_AIRPURIFIER_PRO_V7: PURIFIER_PRO_V7_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, + MODEL_FAN_V2: FAN_V2_V3_SENSORS, + MODEL_FAN_V3: FAN_V2_V3_SENSORS, } @@ -351,6 +373,8 @@ async def async_setup_entry(hass, config_entry, async_add_entities): model = config_entry.data[CONF_MODEL] device = hass.data[DOMAIN][config_entry.entry_id].get(KEY_DEVICE) sensors = [] + if model in (MODEL_FAN_ZA1, MODEL_FAN_ZA3, MODEL_FAN_ZA4, MODEL_FAN_P5): + return if model in MODEL_TO_SENSORS_MAP: sensors = MODEL_TO_SENSORS_MAP[model] elif model in MODELS_HUMIDIFIER_MIOT: diff --git a/homeassistant/components/xiaomi_miio/switch.py b/homeassistant/components/xiaomi_miio/switch.py index 84503664498..c40711f5266 100644 --- a/homeassistant/components/xiaomi_miio/switch.py +++ b/homeassistant/components/xiaomi_miio/switch.py @@ -44,6 +44,8 @@ from .const import ( FEATURE_FLAGS_AIRPURIFIER_PRO_V7, FEATURE_FLAGS_AIRPURIFIER_V1, FEATURE_FLAGS_AIRPURIFIER_V3, + FEATURE_FLAGS_FAN, + FEATURE_FLAGS_FAN_P5, FEATURE_SET_AUTO_DETECT, FEATURE_SET_BUZZER, FEATURE_SET_CHILD_LOCK, @@ -63,6 +65,10 @@ from .const import ( MODEL_AIRPURIFIER_PRO_V7, MODEL_AIRPURIFIER_V1, MODEL_AIRPURIFIER_V3, + MODEL_FAN_P5, + MODEL_FAN_ZA1, + MODEL_FAN_ZA3, + MODEL_FAN_ZA4, MODELS_FAN, MODELS_HUMIDIFIER, MODELS_HUMIDIFIER_MJJSQ, @@ -156,6 +162,10 @@ 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_P5: FEATURE_FLAGS_FAN_P5, + MODEL_FAN_ZA1: FEATURE_FLAGS_FAN, + MODEL_FAN_ZA3: FEATURE_FLAGS_FAN, + MODEL_FAN_ZA4: FEATURE_FLAGS_FAN, }