mirror of
https://github.com/home-assistant/core.git
synced 2025-07-28 23:57:06 +00:00
Add support for Xiaomi Miio Air Purifier 3C (#55484)
This commit is contained in:
parent
4d98a7e156
commit
08a0377dcb
@ -9,6 +9,7 @@ from miio import (
|
||||
AirHumidifierMiot,
|
||||
AirHumidifierMjjsq,
|
||||
AirPurifier,
|
||||
AirPurifierMB4,
|
||||
AirPurifierMiot,
|
||||
DeviceException,
|
||||
Fan,
|
||||
@ -31,6 +32,7 @@ from .const import (
|
||||
DOMAIN,
|
||||
KEY_COORDINATOR,
|
||||
KEY_DEVICE,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_FAN_P5,
|
||||
MODELS_AIR_MONITOR,
|
||||
MODELS_FAN,
|
||||
@ -139,6 +141,8 @@ async def async_create_miio_device_and_coordinator(
|
||||
device = AirHumidifier(host, token, model=model)
|
||||
migrate = True
|
||||
# Airpurifiers and Airfresh
|
||||
elif model in MODEL_AIRPURIFIER_3C:
|
||||
device = AirPurifierMB4(host, token)
|
||||
elif model in MODELS_PURIFIER_MIOT:
|
||||
device = AirPurifierMiot(host, token)
|
||||
elif model.startswith("zhimi.airpurifier."):
|
||||
|
@ -30,23 +30,24 @@ SERVER_COUNTRY_CODES = ["cn", "de", "i2", "ru", "sg", "us"]
|
||||
DEFAULT_CLOUD_COUNTRY = "cn"
|
||||
|
||||
# Fan Models
|
||||
MODEL_AIRPURIFIER_V1 = "zhimi.airpurifier.v1"
|
||||
MODEL_AIRPURIFIER_V2 = "zhimi.airpurifier.v2"
|
||||
MODEL_AIRPURIFIER_V3 = "zhimi.airpurifier.v3"
|
||||
MODEL_AIRPURIFIER_V5 = "zhimi.airpurifier.v5"
|
||||
MODEL_AIRPURIFIER_PRO = "zhimi.airpurifier.v6"
|
||||
MODEL_AIRPURIFIER_PRO_V7 = "zhimi.airpurifier.v7"
|
||||
MODEL_AIRPURIFIER_2H = "zhimi.airpurifier.mc2"
|
||||
MODEL_AIRPURIFIER_2S = "zhimi.airpurifier.mc1"
|
||||
MODEL_AIRPURIFIER_3 = "zhimi.airpurifier.ma4"
|
||||
MODEL_AIRPURIFIER_3C = "zhimi.airpurifier.mb4"
|
||||
MODEL_AIRPURIFIER_3H = "zhimi.airpurifier.mb3"
|
||||
MODEL_AIRPURIFIER_M1 = "zhimi.airpurifier.m1"
|
||||
MODEL_AIRPURIFIER_M2 = "zhimi.airpurifier.m2"
|
||||
MODEL_AIRPURIFIER_MA1 = "zhimi.airpurifier.ma1"
|
||||
MODEL_AIRPURIFIER_MA2 = "zhimi.airpurifier.ma2"
|
||||
MODEL_AIRPURIFIER_PRO = "zhimi.airpurifier.v6"
|
||||
MODEL_AIRPURIFIER_PROH = "zhimi.airpurifier.va1"
|
||||
MODEL_AIRPURIFIER_PRO_V7 = "zhimi.airpurifier.v7"
|
||||
MODEL_AIRPURIFIER_SA1 = "zhimi.airpurifier.sa1"
|
||||
MODEL_AIRPURIFIER_SA2 = "zhimi.airpurifier.sa2"
|
||||
MODEL_AIRPURIFIER_2S = "zhimi.airpurifier.mc1"
|
||||
MODEL_AIRPURIFIER_2H = "zhimi.airpurifier.mc2"
|
||||
MODEL_AIRPURIFIER_3 = "zhimi.airpurifier.ma4"
|
||||
MODEL_AIRPURIFIER_3H = "zhimi.airpurifier.mb3"
|
||||
MODEL_AIRPURIFIER_PROH = "zhimi.airpurifier.va1"
|
||||
MODEL_AIRPURIFIER_V1 = "zhimi.airpurifier.v1"
|
||||
MODEL_AIRPURIFIER_V2 = "zhimi.airpurifier.v2"
|
||||
MODEL_AIRPURIFIER_V3 = "zhimi.airpurifier.v3"
|
||||
MODEL_AIRPURIFIER_V5 = "zhimi.airpurifier.v5"
|
||||
|
||||
MODEL_AIRHUMIDIFIER_V1 = "zhimi.humidifier.v1"
|
||||
MODEL_AIRHUMIDIFIER_CA1 = "zhimi.humidifier.ca1"
|
||||
@ -78,6 +79,7 @@ MODELS_FAN_MIIO = [
|
||||
|
||||
MODELS_PURIFIER_MIOT = [
|
||||
MODEL_AIRPURIFIER_3,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_3H,
|
||||
MODEL_AIRPURIFIER_PROH,
|
||||
]
|
||||
@ -229,6 +231,8 @@ 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_FLAGS_AIRPURIFIER_MIIO = (
|
||||
FEATURE_SET_BUZZER
|
||||
@ -248,6 +252,13 @@ FEATURE_FLAGS_AIRPURIFIER_MIOT = (
|
||||
| FEATURE_SET_LED_BRIGHTNESS
|
||||
)
|
||||
|
||||
FEATURE_FLAGS_AIRPURIFIER_3C = (
|
||||
FEATURE_SET_BUZZER
|
||||
| FEATURE_SET_CHILD_LOCK
|
||||
| FEATURE_SET_LED_BRIGHTNESS_LEVEL
|
||||
| FEATURE_SET_FAVORITE_RPM
|
||||
)
|
||||
|
||||
FEATURE_FLAGS_AIRPURIFIER_PRO = (
|
||||
FEATURE_SET_CHILD_LOCK
|
||||
| FEATURE_SET_LED
|
||||
|
@ -34,6 +34,7 @@ from .const import (
|
||||
DOMAIN,
|
||||
FEATURE_FLAGS_AIRFRESH,
|
||||
FEATURE_FLAGS_AIRPURIFIER_2S,
|
||||
FEATURE_FLAGS_AIRPURIFIER_3C,
|
||||
FEATURE_FLAGS_AIRPURIFIER_MIIO,
|
||||
FEATURE_FLAGS_AIRPURIFIER_MIOT,
|
||||
FEATURE_FLAGS_AIRPURIFIER_PRO,
|
||||
@ -47,6 +48,7 @@ from .const import (
|
||||
KEY_DEVICE,
|
||||
MODEL_AIRPURIFIER_2H,
|
||||
MODEL_AIRPURIFIER_2S,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_PRO,
|
||||
MODEL_AIRPURIFIER_PRO_V7,
|
||||
MODEL_AIRPURIFIER_V3,
|
||||
@ -193,7 +195,15 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
||||
coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR]
|
||||
device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
|
||||
|
||||
if model in MODELS_PURIFIER_MIOT:
|
||||
if model == MODEL_AIRPURIFIER_3C:
|
||||
entity = XiaomiAirPurifierMB4(
|
||||
name,
|
||||
device,
|
||||
config_entry,
|
||||
unique_id,
|
||||
coordinator,
|
||||
)
|
||||
elif model in MODELS_PURIFIER_MIOT:
|
||||
entity = XiaomiAirPurifierMiot(
|
||||
name,
|
||||
device,
|
||||
@ -567,11 +577,35 @@ class XiaomiAirPurifierMiot(XiaomiAirPurifier):
|
||||
self._fan_level = fan_level
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_set_preset_mode(self, preset_mode: str) -> None:
|
||||
"""Set the preset mode of the fan.
|
||||
|
||||
This method is a coroutine.
|
||||
"""
|
||||
class XiaomiAirPurifierMB4(XiaomiGenericDevice):
|
||||
"""Representation of a Xiaomi Air Purifier MB4."""
|
||||
|
||||
PRESET_MODE_MAPPING = {
|
||||
"Auto": AirpurifierMiotOperationMode.Auto,
|
||||
"Silent": AirpurifierMiotOperationMode.Silent,
|
||||
"Favorite": AirpurifierMiotOperationMode.Favorite,
|
||||
}
|
||||
|
||||
def __init__(self, name, device, entry, unique_id, coordinator):
|
||||
"""Initialize Air Purifier MB4."""
|
||||
super().__init__(name, device, entry, unique_id, coordinator)
|
||||
|
||||
self._device_features = FEATURE_FLAGS_AIRPURIFIER_3C
|
||||
self._preset_modes = list(self.PRESET_MODE_MAPPING)
|
||||
self._supported_features = SUPPORT_PRESET_MODE
|
||||
|
||||
@property
|
||||
def preset_mode(self):
|
||||
"""Get the active preset mode."""
|
||||
if self.coordinator.data.is_on:
|
||||
preset_mode = AirpurifierMiotOperationMode(self._mode).name
|
||||
return preset_mode if preset_mode in self._preset_modes else None
|
||||
|
||||
return None
|
||||
|
||||
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
|
||||
@ -583,6 +617,14 @@ class XiaomiAirPurifierMiot(XiaomiAirPurifier):
|
||||
self._mode = self.PRESET_MODE_MAPPING[preset_mode].value
|
||||
self.async_write_ha_state()
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self):
|
||||
"""Fetch state from the device."""
|
||||
self._available = True
|
||||
self._state = self.coordinator.data.is_on
|
||||
self._mode = self.coordinator.data.mode.value
|
||||
self.async_write_ha_state()
|
||||
|
||||
|
||||
class XiaomiAirFresh(XiaomiGenericDevice):
|
||||
"""Representation of a Xiaomi Air Fresh."""
|
||||
|
@ -17,6 +17,7 @@ from .const import (
|
||||
FEATURE_FLAGS_AIRHUMIDIFIER_CA4,
|
||||
FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB,
|
||||
FEATURE_FLAGS_AIRPURIFIER_2S,
|
||||
FEATURE_FLAGS_AIRPURIFIER_3C,
|
||||
FEATURE_FLAGS_AIRPURIFIER_MIIO,
|
||||
FEATURE_FLAGS_AIRPURIFIER_MIOT,
|
||||
FEATURE_FLAGS_AIRPURIFIER_PRO,
|
||||
@ -28,6 +29,8 @@ from .const import (
|
||||
FEATURE_SET_DELAY_OFF_COUNTDOWN,
|
||||
FEATURE_SET_FAN_LEVEL,
|
||||
FEATURE_SET_FAVORITE_LEVEL,
|
||||
FEATURE_SET_FAVORITE_RPM,
|
||||
FEATURE_SET_LED_BRIGHTNESS_LEVEL,
|
||||
FEATURE_SET_MOTOR_SPEED,
|
||||
FEATURE_SET_OSCILLATION_ANGLE,
|
||||
FEATURE_SET_OSCILLATION_ANGLE_MAX_140,
|
||||
@ -39,6 +42,7 @@ from .const import (
|
||||
MODEL_AIRHUMIDIFIER_CA4,
|
||||
MODEL_AIRHUMIDIFIER_CB1,
|
||||
MODEL_AIRPURIFIER_2S,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_PRO,
|
||||
MODEL_AIRPURIFIER_PRO_V7,
|
||||
MODEL_AIRPURIFIER_V1,
|
||||
@ -58,6 +62,8 @@ from .device import XiaomiCoordinatedMiioEntity
|
||||
ATTR_DELAY_OFF_COUNTDOWN = "delay_off_countdown"
|
||||
ATTR_FAN_LEVEL = "fan_level"
|
||||
ATTR_FAVORITE_LEVEL = "favorite_level"
|
||||
ATTR_FAVORITE_RPM = "favorite_rpm"
|
||||
ATTR_LED_BRIGHTNESS_LEVEL = "led_brightness_level"
|
||||
ATTR_MOTOR_SPEED = "motor_speed"
|
||||
ATTR_OSCILLATION_ANGLE = "angle"
|
||||
ATTR_VOLUME = "volume"
|
||||
@ -143,6 +149,25 @@ NUMBER_TYPES = {
|
||||
step=1,
|
||||
method="async_set_delay_off_countdown",
|
||||
),
|
||||
FEATURE_SET_LED_BRIGHTNESS_LEVEL: XiaomiMiioNumberDescription(
|
||||
key=ATTR_LED_BRIGHTNESS_LEVEL,
|
||||
name="Led Brightness",
|
||||
icon="mdi:brightness-6",
|
||||
min_value=0,
|
||||
max_value=8,
|
||||
step=1,
|
||||
method="async_set_led_brightness_level",
|
||||
),
|
||||
FEATURE_SET_FAVORITE_RPM: XiaomiMiioNumberDescription(
|
||||
key=ATTR_FAVORITE_RPM,
|
||||
name="Favorite Motor Speed",
|
||||
icon="mdi:star-cog",
|
||||
unit_of_measurement="rpm",
|
||||
min_value=300,
|
||||
max_value=2300,
|
||||
step=10,
|
||||
method="async_set_favorite_rpm",
|
||||
),
|
||||
}
|
||||
|
||||
MODEL_TO_FEATURES_MAP = {
|
||||
@ -151,6 +176,7 @@ MODEL_TO_FEATURES_MAP = {
|
||||
MODEL_AIRHUMIDIFIER_CA4: FEATURE_FLAGS_AIRHUMIDIFIER_CA4,
|
||||
MODEL_AIRHUMIDIFIER_CB1: FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB,
|
||||
MODEL_AIRPURIFIER_2S: FEATURE_FLAGS_AIRPURIFIER_2S,
|
||||
MODEL_AIRPURIFIER_3C: FEATURE_FLAGS_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_PRO: FEATURE_FLAGS_AIRPURIFIER_PRO,
|
||||
MODEL_AIRPURIFIER_PRO_V7: FEATURE_FLAGS_AIRPURIFIER_PRO_V7,
|
||||
MODEL_AIRPURIFIER_V1: FEATURE_FLAGS_AIRPURIFIER_V1,
|
||||
@ -293,3 +319,19 @@ class XiaomiNumberEntity(XiaomiCoordinatedMiioEntity, NumberEntity):
|
||||
self._device.delay_off,
|
||||
delay_off_countdown * 60,
|
||||
)
|
||||
|
||||
async def async_set_led_brightness_level(self, level: int):
|
||||
"""Set the led brightness level."""
|
||||
return await self._try_command(
|
||||
"Setting the led brightness level of the miio device failed.",
|
||||
self._device.set_led_brightness_level,
|
||||
level,
|
||||
)
|
||||
|
||||
async def async_set_favorite_rpm(self, rpm: int):
|
||||
"""Set the target motor speed."""
|
||||
return await self._try_command(
|
||||
"Setting the favorite rpm of the miio device failed.",
|
||||
self._device.set_favorite_rpm,
|
||||
rpm,
|
||||
)
|
||||
|
@ -23,6 +23,7 @@ from .const import (
|
||||
KEY_COORDINATOR,
|
||||
KEY_DEVICE,
|
||||
MODEL_AIRFRESH_VA2,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_M1,
|
||||
MODEL_AIRPURIFIER_M2,
|
||||
MODEL_FAN_SA1,
|
||||
@ -75,6 +76,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][KEY_DEVICE]
|
||||
|
||||
if model == MODEL_AIRPURIFIER_3C:
|
||||
return
|
||||
if model in MODELS_HUMIDIFIER_MIIO:
|
||||
entity_class = XiaomiAirHumidifierSelector
|
||||
elif model in MODELS_HUMIDIFIER_MIOT:
|
||||
|
@ -33,6 +33,7 @@ from homeassistant.const import (
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_ILLUMINANCE,
|
||||
DEVICE_CLASS_PM25,
|
||||
DEVICE_CLASS_POWER,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
DEVICE_CLASS_TEMPERATURE,
|
||||
@ -56,6 +57,7 @@ from .const import (
|
||||
MODEL_AIRFRESH_VA2,
|
||||
MODEL_AIRHUMIDIFIER_CA1,
|
||||
MODEL_AIRHUMIDIFIER_CB1,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_PRO,
|
||||
MODEL_AIRPURIFIER_PRO_V7,
|
||||
MODEL_AIRPURIFIER_V2,
|
||||
@ -194,7 +196,7 @@ SENSOR_TYPES = {
|
||||
key=ATTR_AQI,
|
||||
name="PM2.5",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
icon="mdi:blur",
|
||||
device_class=DEVICE_CLASS_PM25,
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
ATTR_FILTER_LIFE_REMAINING: XiaomiMiioSensorDescription(
|
||||
@ -268,6 +270,12 @@ PURIFIER_MIOT_SENSORS = (
|
||||
ATTR_PURIFY_VOLUME,
|
||||
ATTR_TEMPERATURE,
|
||||
)
|
||||
PURIFIER_3C_SENSORS = (
|
||||
ATTR_FILTER_LIFE_REMAINING,
|
||||
ATTR_FILTER_USE,
|
||||
ATTR_MOTOR_SPEED,
|
||||
ATTR_PM25,
|
||||
)
|
||||
PURIFIER_V2_SENSORS = (
|
||||
ATTR_FILTER_LIFE_REMAINING,
|
||||
ATTR_FILTER_USE,
|
||||
@ -326,6 +334,7 @@ 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_3C: PURIFIER_3C_SENSORS,
|
||||
MODEL_AIRPURIFIER_PRO: PURIFIER_PRO_SENSORS,
|
||||
MODEL_AIRPURIFIER_PRO_V7: PURIFIER_PRO_V7_SENSORS,
|
||||
MODEL_AIRPURIFIER_V2: PURIFIER_V2_SENSORS,
|
||||
|
@ -38,6 +38,7 @@ from .const import (
|
||||
FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB,
|
||||
FEATURE_FLAGS_AIRHUMIDIFIER_MJSSQ,
|
||||
FEATURE_FLAGS_AIRPURIFIER_2S,
|
||||
FEATURE_FLAGS_AIRPURIFIER_3C,
|
||||
FEATURE_FLAGS_AIRPURIFIER_MIIO,
|
||||
FEATURE_FLAGS_AIRPURIFIER_MIOT,
|
||||
FEATURE_FLAGS_AIRPURIFIER_PRO,
|
||||
@ -61,6 +62,7 @@ from .const import (
|
||||
MODEL_AIRHUMIDIFIER_CB1,
|
||||
MODEL_AIRPURIFIER_2H,
|
||||
MODEL_AIRPURIFIER_2S,
|
||||
MODEL_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_PRO,
|
||||
MODEL_AIRPURIFIER_PRO_V7,
|
||||
MODEL_AIRPURIFIER_V1,
|
||||
@ -158,6 +160,7 @@ MODEL_TO_FEATURES_MAP = {
|
||||
MODEL_AIRHUMIDIFIER_CB1: FEATURE_FLAGS_AIRHUMIDIFIER_CA_AND_CB,
|
||||
MODEL_AIRPURIFIER_2H: FEATURE_FLAGS_AIRPURIFIER_2S,
|
||||
MODEL_AIRPURIFIER_2S: FEATURE_FLAGS_AIRPURIFIER_2S,
|
||||
MODEL_AIRPURIFIER_3C: FEATURE_FLAGS_AIRPURIFIER_3C,
|
||||
MODEL_AIRPURIFIER_PRO: FEATURE_FLAGS_AIRPURIFIER_PRO,
|
||||
MODEL_AIRPURIFIER_PRO_V7: FEATURE_FLAGS_AIRPURIFIER_PRO_V7,
|
||||
MODEL_AIRPURIFIER_V1: FEATURE_FLAGS_AIRPURIFIER_V1,
|
||||
|
Loading…
x
Reference in New Issue
Block a user