diff --git a/homeassistant/components/xiaomi_miio/air_quality.py b/homeassistant/components/xiaomi_miio/air_quality.py index f5e7e476ac5..50de263fb15 100644 --- a/homeassistant/components/xiaomi_miio/air_quality.py +++ b/homeassistant/components/xiaomi_miio/air_quality.py @@ -1,16 +1,22 @@ """Support for Xiaomi Mi Air Quality Monitor (PM2.5).""" +import logging + from miio import AirQualityMonitor, Device, DeviceException import voluptuous as vol -from homeassistant.components.air_quality import ( - _LOGGER, - PLATFORM_SCHEMA, - AirQualityEntity, -) +from homeassistant.components.air_quality import PLATFORM_SCHEMA, AirQualityEntity from homeassistant.const import CONF_HOST, CONF_NAME, CONF_TOKEN -from homeassistant.exceptions import PlatformNotReady +from homeassistant.exceptions import NoEntitySpecifiedError, PlatformNotReady import homeassistant.helpers.config_validation as cv +from .const import ( + MODEL_AIRQUALITYMONITOR_B1, + MODEL_AIRQUALITYMONITOR_S1, + MODEL_AIRQUALITYMONITOR_V1, +) + +_LOGGER = logging.getLogger(__name__) + DEFAULT_NAME = "Xiaomi Miio Air Quality Monitor" ATTR_CO2E = "carbon_dioxide_equivalent" @@ -54,9 +60,19 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= device_info.firmware_version, device_info.hardware_version, ) - device = AirMonitorB1(name, AirQualityMonitor(host, token, model=model), unique_id) - async_add_entities([device], update_before_add=True) + device = AirQualityMonitor(host, token, model=model) + + if model == MODEL_AIRQUALITYMONITOR_S1: + entity = AirMonitorS1(name, device, unique_id) + elif model == MODEL_AIRQUALITYMONITOR_B1: + entity = AirMonitorB1(name, device, unique_id) + elif model == MODEL_AIRQUALITYMONITOR_V1: + entity = AirMonitorV1(name, device, unique_id) + else: + raise NoEntitySpecifiedError(f"Not support for entity {unique_id}") + + async_add_entities([entity], update_before_add=True) class AirMonitorB1(AirQualityEntity): @@ -69,22 +85,24 @@ class AirMonitorB1(AirQualityEntity): self._unique_id = unique_id self._icon = "mdi:cloud" self._unit_of_measurement = "μg/m3" + self._available = None + self._air_quality_index = None + self._carbon_dioxide = None self._carbon_dioxide_equivalent = None self._particulate_matter_2_5 = None self._total_volatile_organic_compounds = None async def async_update(self): """Fetch state from the miio device.""" - try: state = await self.hass.async_add_executor_job(self._device.status) _LOGGER.debug("Got new state: %s", state) - self._carbon_dioxide_equivalent = state.co2e self._particulate_matter_2_5 = round(state.pm25, 1) self._total_volatile_organic_compounds = round(state.tvoc, 3) - + self._available = True except DeviceException as ex: + self._available = False _LOGGER.error("Got exception while fetching the state: %s", ex) @property @@ -97,11 +115,26 @@ class AirMonitorB1(AirQualityEntity): """Return the icon to use for device if any.""" return self._icon + @property + def available(self): + """Return true when state is known.""" + return self._available + @property def unique_id(self): """Return the unique ID.""" return self._unique_id + @property + def air_quality_index(self): + """Return the Air Quality Index (AQI).""" + return self._air_quality_index + + @property + def carbon_dioxide(self): + """Return the CO2 (carbon dioxide) level.""" + return self._carbon_dioxide + @property def carbon_dioxide_equivalent(self): """Return the CO2e (carbon dioxide equivalent) level.""" @@ -133,3 +166,40 @@ class AirMonitorB1(AirQualityEntity): def unit_of_measurement(self): """Return the unit of measurement.""" return self._unit_of_measurement + + +class AirMonitorS1(AirMonitorB1): + """Air Quality class for Xiaomi cgllc.airmonitor.s1 device.""" + + async def async_update(self): + """Fetch state from the miio device.""" + try: + state = await self.hass.async_add_executor_job(self._device.status) + _LOGGER.debug("Got new state: %s", state) + self._carbon_dioxide = state.co2 + self._particulate_matter_2_5 = state.pm25 + self._total_volatile_organic_compounds = state.tvoc + self._available = True + except DeviceException as ex: + self._available = False + _LOGGER.error("Got exception while fetching the state: %s", ex) + + +class AirMonitorV1(AirMonitorB1): + """Air Quality class for Xiaomi cgllc.airmonitor.s1 device.""" + + async def async_update(self): + """Fetch state from the miio device.""" + try: + state = await self.hass.async_add_executor_job(self._device.status) + _LOGGER.debug("Got new state: %s", state) + self._air_quality_index = state.aqi + self._available = True + except DeviceException as ex: + self._available = False + _LOGGER.error("Got exception while fetching the state: %s", ex) + + @property + def unit_of_measurement(self): + """Return the unit of measurement.""" + return None diff --git a/homeassistant/components/xiaomi_miio/const.py b/homeassistant/components/xiaomi_miio/const.py index f8be37b313c..54dd684f6b1 100644 --- a/homeassistant/components/xiaomi_miio/const.py +++ b/homeassistant/components/xiaomi_miio/const.py @@ -46,3 +46,8 @@ SERVICE_MOVE_REMOTE_CONTROL_STEP = "vacuum_remote_control_move_step" SERVICE_START_REMOTE_CONTROL = "vacuum_remote_control_start" SERVICE_STOP_REMOTE_CONTROL = "vacuum_remote_control_stop" SERVICE_CLEAN_ZONE = "vacuum_clean_zone" + +# AirQuality Model +MODEL_AIRQUALITYMONITOR_V1 = "zhimi.airmonitor.v1" +MODEL_AIRQUALITYMONITOR_B1 = "cgllc.airmonitor.b1" +MODEL_AIRQUALITYMONITOR_S1 = "cgllc.airmonitor.s1"