Add Xiaomi Smartmi Fresh Air System support (#18097)
* Add Xiaomi Air Fresh VA2 support * Add LED property again (available now)pull/18250/head
parent
3366d2c1ad
commit
d951ed4d68
|
@ -11,10 +11,10 @@ import logging
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.fan import (
|
||||
DOMAIN, PLATFORM_SCHEMA, SUPPORT_SET_SPEED, FanEntity)
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, CONF_HOST, CONF_NAME, CONF_TOKEN)
|
||||
from homeassistant.components.fan import (FanEntity, PLATFORM_SCHEMA,
|
||||
SUPPORT_SET_SPEED, DOMAIN, )
|
||||
from homeassistant.const import (CONF_NAME, CONF_HOST, CONF_TOKEN,
|
||||
ATTR_ENTITY_ID, )
|
||||
from homeassistant.exceptions import PlatformNotReady
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
|
@ -30,6 +30,7 @@ MODEL_AIRPURIFIER_PRO = 'zhimi.airpurifier.v6'
|
|||
MODEL_AIRPURIFIER_V3 = 'zhimi.airpurifier.v3'
|
||||
MODEL_AIRHUMIDIFIER_V1 = 'zhimi.humidifier.v1'
|
||||
MODEL_AIRHUMIDIFIER_CA = 'zhimi.humidifier.ca1'
|
||||
MODEL_AIRFRESH_VA2 = 'zhimi.airfresh.va2'
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
|
@ -48,7 +49,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
|||
'zhimi.airpurifier.v5',
|
||||
'zhimi.airpurifier.v6',
|
||||
'zhimi.humidifier.v1',
|
||||
'zhimi.humidifier.ca1']),
|
||||
'zhimi.humidifier.ca1',
|
||||
'zhimi.airfresh.va2']),
|
||||
})
|
||||
|
||||
ATTR_MODEL = 'model'
|
||||
|
@ -97,6 +99,9 @@ ATTR_SPEED = 'speed'
|
|||
ATTR_DEPTH = 'depth'
|
||||
ATTR_DRY = 'dry'
|
||||
|
||||
# Air Fresh
|
||||
ATTR_CO2 = 'co2'
|
||||
|
||||
# Map attributes to properties of the state object
|
||||
AVAILABLE_ATTRIBUTES_AIRPURIFIER_COMMON = {
|
||||
ATTR_TEMPERATURE: 'temperature',
|
||||
|
@ -166,31 +171,55 @@ AVAILABLE_ATTRIBUTES_AIRPURIFIER_V3 = {
|
|||
ATTR_BUTTON_PRESSED: 'button_pressed',
|
||||
}
|
||||
|
||||
AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER = {
|
||||
AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER_COMMON = {
|
||||
ATTR_TEMPERATURE: 'temperature',
|
||||
ATTR_HUMIDITY: 'humidity',
|
||||
ATTR_MODE: 'mode',
|
||||
ATTR_BUZZER: 'buzzer',
|
||||
ATTR_CHILD_LOCK: 'child_lock',
|
||||
ATTR_TRANS_LEVEL: 'trans_level',
|
||||
ATTR_TARGET_HUMIDITY: 'target_humidity',
|
||||
ATTR_LED_BRIGHTNESS: 'led_brightness',
|
||||
ATTR_BUTTON_PRESSED: 'button_pressed',
|
||||
ATTR_USE_TIME: 'use_time',
|
||||
ATTR_HARDWARE_VERSION: 'hardware_version',
|
||||
}
|
||||
|
||||
AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER = {
|
||||
**AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER_COMMON,
|
||||
ATTR_TRANS_LEVEL: 'trans_level',
|
||||
ATTR_BUTTON_PRESSED: 'button_pressed',
|
||||
}
|
||||
|
||||
AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER_CA = {
|
||||
**AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER,
|
||||
**AVAILABLE_ATTRIBUTES_AIRHUMIDIFIER_COMMON,
|
||||
ATTR_SPEED: 'speed',
|
||||
ATTR_DEPTH: 'depth',
|
||||
ATTR_DRY: 'dry',
|
||||
}
|
||||
|
||||
AVAILABLE_ATTRIBUTES_AIRFRESH = {
|
||||
ATTR_TEMPERATURE: 'temperature',
|
||||
ATTR_AIR_QUALITY_INDEX: 'aqi',
|
||||
ATTR_AVERAGE_AIR_QUALITY_INDEX: 'average_aqi',
|
||||
ATTR_CO2: 'co2',
|
||||
ATTR_HUMIDITY: 'humidity',
|
||||
ATTR_MODE: 'mode',
|
||||
ATTR_LED: 'led',
|
||||
ATTR_LED_BRIGHTNESS: 'led_brightness',
|
||||
ATTR_BUZZER: 'buzzer',
|
||||
ATTR_CHILD_LOCK: 'child_lock',
|
||||
ATTR_FILTER_LIFE: 'filter_life_remaining',
|
||||
ATTR_FILTER_HOURS_USED: 'filter_hours_used',
|
||||
ATTR_USE_TIME: 'use_time',
|
||||
ATTR_MOTOR_SPEED: 'motor_speed',
|
||||
ATTR_EXTRA_FEATURES: 'extra_features',
|
||||
}
|
||||
|
||||
OPERATION_MODES_AIRPURIFIER = ['Auto', 'Silent', 'Favorite', 'Idle']
|
||||
OPERATION_MODES_AIRPURIFIER_PRO = ['Auto', 'Silent', 'Favorite']
|
||||
OPERATION_MODES_AIRPURIFIER_V3 = ['Auto', 'Silent', 'Favorite', 'Idle',
|
||||
'Medium', 'High', 'Strong']
|
||||
OPERATION_MODES_AIRFRESH = ['Auto', 'Silent', 'Interval', 'Low',
|
||||
'Middle', 'Strong']
|
||||
|
||||
SUCCESS = ['ok']
|
||||
|
||||
|
@ -234,6 +263,12 @@ FEATURE_FLAGS_AIRHUMIDIFIER = (FEATURE_FLAGS_GENERIC |
|
|||
FEATURE_FLAGS_AIRHUMIDIFIER_CA = (FEATURE_FLAGS_AIRHUMIDIFIER |
|
||||
FEATURE_SET_DRY)
|
||||
|
||||
FEATURE_FLAGS_AIRFRESH = (FEATURE_FLAGS_GENERIC |
|
||||
FEATURE_SET_LED |
|
||||
FEATURE_SET_LED_BRIGHTNESS |
|
||||
FEATURE_RESET_FILTER |
|
||||
FEATURE_SET_EXTRA_FEATURES)
|
||||
|
||||
SERVICE_SET_BUZZER_ON = 'xiaomi_miio_set_buzzer_on'
|
||||
SERVICE_SET_BUZZER_OFF = 'xiaomi_miio_set_buzzer_off'
|
||||
SERVICE_SET_LED_ON = 'xiaomi_miio_set_led_on'
|
||||
|
@ -350,6 +385,10 @@ async def async_setup_platform(hass, config, async_add_entities,
|
|||
from miio import AirHumidifier
|
||||
air_humidifier = AirHumidifier(host, token, model=model)
|
||||
device = XiaomiAirHumidifier(name, air_humidifier, model, unique_id)
|
||||
elif model.startswith('zhimi.airfresh.'):
|
||||
from miio import AirFresh
|
||||
air_fresh = AirFresh(host, token)
|
||||
device = XiaomiAirFresh(name, air_fresh, model, unique_id)
|
||||
else:
|
||||
_LOGGER.error(
|
||||
'Unsupported device found! Please create an issue at '
|
||||
|
@ -812,3 +851,116 @@ class XiaomiAirHumidifier(XiaomiGenericDevice):
|
|||
await self._try_command(
|
||||
"Turning the dry mode of the miio device off failed.",
|
||||
self._device.set_dry, False)
|
||||
|
||||
|
||||
class XiaomiAirFresh(XiaomiGenericDevice):
|
||||
"""Representation of a Xiaomi Air Fresh."""
|
||||
|
||||
def __init__(self, name, device, model, unique_id):
|
||||
"""Initialize the miio device."""
|
||||
super().__init__(name, device, model, unique_id)
|
||||
|
||||
self._device_features = FEATURE_FLAGS_AIRFRESH
|
||||
self._available_attributes = AVAILABLE_ATTRIBUTES_AIRFRESH
|
||||
self._speed_list = OPERATION_MODES_AIRFRESH
|
||||
self._state_attrs.update(
|
||||
{attribute: None for attribute in self._available_attributes})
|
||||
|
||||
async def async_update(self):
|
||||
"""Fetch state from the device."""
|
||||
from miio import DeviceException
|
||||
|
||||
# On state change the device doesn't provide the new state immediately.
|
||||
if self._skip_update:
|
||||
self._skip_update = False
|
||||
return
|
||||
|
||||
try:
|
||||
state = await self.hass.async_add_job(
|
||||
self._device.status)
|
||||
_LOGGER.debug("Got new state: %s", state)
|
||||
|
||||
self._available = True
|
||||
self._state = state.is_on
|
||||
self._state_attrs.update(
|
||||
{key: self._extract_value_from_attribute(state, value) for
|
||||
key, value in self._available_attributes.items()})
|
||||
|
||||
except DeviceException as ex:
|
||||
self._available = False
|
||||
_LOGGER.error("Got exception while fetching the state: %s", ex)
|
||||
|
||||
@property
|
||||
def speed_list(self) -> list:
|
||||
"""Get the list of available speeds."""
|
||||
return self._speed_list
|
||||
|
||||
@property
|
||||
def speed(self):
|
||||
"""Return the current speed."""
|
||||
if self._state:
|
||||
from miio.airfresh import OperationMode
|
||||
|
||||
return OperationMode(self._state_attrs[ATTR_MODE]).name
|
||||
|
||||
return None
|
||||
|
||||
async def async_set_speed(self, speed: str) -> None:
|
||||
"""Set the speed of the fan."""
|
||||
if self.supported_features & SUPPORT_SET_SPEED == 0:
|
||||
return
|
||||
|
||||
from miio.airfresh import OperationMode
|
||||
|
||||
_LOGGER.debug("Setting the operation mode to: %s", speed)
|
||||
|
||||
await self._try_command(
|
||||
"Setting operation mode of the miio device failed.",
|
||||
self._device.set_mode, OperationMode[speed.title()])
|
||||
|
||||
async def async_set_led_on(self):
|
||||
"""Turn the led on."""
|
||||
if self._device_features & FEATURE_SET_LED == 0:
|
||||
return
|
||||
|
||||
await self._try_command(
|
||||
"Turning the led of the miio device off failed.",
|
||||
self._device.set_led, True)
|
||||
|
||||
async def async_set_led_off(self):
|
||||
"""Turn the led off."""
|
||||
if self._device_features & FEATURE_SET_LED == 0:
|
||||
return
|
||||
|
||||
await self._try_command(
|
||||
"Turning the led of the miio device off failed.",
|
||||
self._device.set_led, False)
|
||||
|
||||
async def async_set_led_brightness(self, brightness: int = 2):
|
||||
"""Set the led brightness."""
|
||||
if self._device_features & FEATURE_SET_LED_BRIGHTNESS == 0:
|
||||
return
|
||||
|
||||
from miio.airfresh import LedBrightness
|
||||
|
||||
await self._try_command(
|
||||
"Setting the led brightness of the miio device failed.",
|
||||
self._device.set_led_brightness, LedBrightness(brightness))
|
||||
|
||||
async def async_set_extra_features(self, features: int = 1):
|
||||
"""Set the extra features."""
|
||||
if self._device_features & FEATURE_SET_EXTRA_FEATURES == 0:
|
||||
return
|
||||
|
||||
await self._try_command(
|
||||
"Setting the extra features of the miio device failed.",
|
||||
self._device.set_extra_features, features)
|
||||
|
||||
async def async_reset_filter(self):
|
||||
"""Reset the filter lifetime and usage."""
|
||||
if self._device_features & FEATURE_RESET_FILTER == 0:
|
||||
return
|
||||
|
||||
await self._try_command(
|
||||
"Resetting the filter lifetime of the miio device failed.",
|
||||
self._device.reset_filter)
|
||||
|
|
Loading…
Reference in New Issue