diff --git a/README.rst b/README.rst index 88ccde2d6..4a929e1ab 100644 --- a/README.rst +++ b/README.rst @@ -106,6 +106,7 @@ Supported devices - Xiaomi Mi Air Purifier 2, 3H, 3C, 4, Pro, Pro H, 4 Pro (zhimi.airpurifier.m2, mb3, mb4, mb5, v7, vb2, va2), 4 Lite - Xiaomi Mi Air (Purifier) Dog X3, X5, X7SM (airdog.airpurifier.x3, airdog.airpurifier.x5, airdog.airpurifier.x7sm) - Xiaomi Mi Air Humidifier +- Smartmi Air Purifier - Xiaomi Aqara Camera - Xiaomi Aqara Gateway (basic implementation, alarm, lights) - Xiaomi Mijia 360 1080p diff --git a/miio/integrations/airpurifier/zhimi/airpurifier_miot.py b/miio/integrations/airpurifier/zhimi/airpurifier_miot.py index 8019782d8..a48868d40 100644 --- a/miio/integrations/airpurifier/zhimi/airpurifier_miot.py +++ b/miio/integrations/airpurifier/zhimi/airpurifier_miot.py @@ -169,6 +169,45 @@ "device-display-unit": {"siid": 14, "piid": 1}, } +# https://miot-spec.org/miot-spec-v2/instance?type=urn:miot-spec-v2:device:air-purifier:0000A007:zhimi-za1:2 +_MAPPING_ZA1 = { + # Air Purifier (siid=2) + "power": {"siid": 2, "piid": 1}, + "fan_level": {"siid": 2, "piid": 4}, + "mode": {"siid": 2, "piid": 5}, + # Environment (siid=3) + "humidity": {"siid": 3, "piid": 7}, + "temperature": {"siid": 3, "piid": 8}, + "aqi": {"siid": 3, "piid": 6}, + "tvoc": {"siid": 3, "piid": 1}, + # Filter (siid=4) + "filter_life_remaining": {"siid": 4, "piid": 3}, + "filter_hours_used": {"siid": 4, "piid": 5}, + # Alarm (siid=5) + "buzzer": {"siid": 5, "piid": 1}, + # Indicator Light (siid=6) + "led_brightness": {"siid": 6, "piid": 1}, + # Physical Control Locked (siid=7) + "child_lock": {"siid": 7, "piid": 1}, + # Motor Speed (siid=10) + "favorite_level": {"siid": 10, "piid": 10}, + "motor_speed": {"siid": 10, "piid": 11}, + # Use time (siid=12) + "use_time": {"siid": 12, "piid": 1}, + # AQI (siid=13) + "purify_volume": {"siid": 13, "piid": 1}, + "average_aqi": {"siid": 13, "piid": 2}, + "aqi_realtime_update_duration": {"siid": 13, "piid": 9}, + # RFID (siid=14) + "filter_rfid_tag": {"siid": 14, "piid": 1}, + "filter_rfid_product_id": {"siid": 14, "piid": 3}, + # Device Display Unit + "device-display-unit": {"siid": 16, "piid": 1}, + # Other + "gestures": {"siid": 15, "piid": 13}, +} + + _MAPPINGS = { "zhimi.airpurifier.ma4": _MAPPING, # airpurifier 3 "zhimi.airpurifier.mb3": _MAPPING, # airpurifier 3h @@ -180,6 +219,7 @@ "zhimi.airp.va2": _MAPPING_VA2, # airpurifier 4 pro "zhimi.airp.vb4": _MAPPING_VB4, # airpurifier 4 pro "zhimi.airp.rmb1": _MAPPING_RMB1, # airpurifier 4 lite + "zhimi.airpurifier.za1": _MAPPING_ZA1, # smartmi air purifier } @@ -302,6 +342,11 @@ def humidity(self) -> Optional[int]: """Current humidity.""" return self.data.get("humidity") + @property + def tvoc(self) -> Optional[int]: + """Current TVOC.""" + return self.data.get("tvoc") + @property def temperature(self) -> Optional[float]: """Current temperature, if available.""" @@ -397,6 +442,11 @@ def filter_left_time(self) -> Optional[int]: """How many days can the filter still be used.""" return self.data.get("filter_left_time") + @property + def gestures(self) -> Optional[bool]: + """Return True if gesture control is on.""" + return self.data.get("gestures") + class AirPurifierMiot(MiotDevice): """Main class representing the air purifier which uses MIoT protocol.""" @@ -409,6 +459,7 @@ class AirPurifierMiot(MiotDevice): "Power: {result.power}\n" "Anion: {result.anion}\n" "AQI: {result.aqi} μg/m³\n" + "TVOC: {result.tvoc}\n" "Average AQI: {result.average_aqi} μg/m³\n" "Humidity: {result.humidity} %\n" "Temperature: {result.temperature} °C\n" @@ -418,6 +469,7 @@ class AirPurifierMiot(MiotDevice): "LED: {result.led}\n" "LED brightness: {result.led_brightness}\n" "LED brightness level: {result.led_brightness_level}\n" + "Gestures: {result.gestures}\n" "Buzzer: {result.buzzer}\n" "Buzzer vol.: {result.buzzer_volume}\n" "Child lock: {result.child_lock}\n" @@ -515,6 +567,23 @@ def set_buzzer(self, buzzer: bool): return self.set_property("buzzer", buzzer) + @command( + click.argument("gestures", type=bool), + default_output=format_output( + lambda gestures: "Turning on gestures" + if gestures + else "Turning off gestures" + ), + ) + def set_gestures(self, gestures: bool): + """Set gestures on/off.""" + if "gestures" not in self._get_mapping(): + raise AirPurifierMiotException( + "Gestures not support for model '%s'" % self.model + ) + + return self.set_property("gestures", gestures) + @command( click.argument("lock", type=bool), default_output=format_output(