diff --git a/CHANGELOG.md b/CHANGELOG.md index c3c026286..be69e5a2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,80 @@ # Change Log +This release adds support for the following new devices: + +* Xiaomi Air Quality Monitor S1 \(cgllc.airmonitor.s1\) +* Xiaomi Mi Dehumidifier V1 \(nwt.derh.wdh318efw1\) +* Xiaomi Mi Roborock M1S and Mi Robot S1 +* Xiaomi Mijia 360 1080p camera \(chuangmi.camera.ipc009\) +* Xiaomi Mi Smart Fan \(zhimi.fan.za3, zhimi.fan.za4, dmaker.fan.p5\) +* Xiaomi Smartmi Pure Evaporative Air Humidifier \(zhimi.humidifier.cb1\) +* Xiaomi Tinymu Smart Toilet Cover +* Xiaomi 16 Relays Module + +Fixes & Enhancements: + +* Air Conditioning Companion: Add particular swing mode values of a chigo air conditioner +* Air Humidifier: Handle poweroff exception on set\_mode +* Chuangmi IR controller: Add indicator led support +* Chuangmi IR controller: Add discovery of the Xiaomi IR remote 2gen \(chuangmi.remote.h102a03\) +* Chuangmi Plug: Fix set\_wifi\_led cli command +* Vacuum: Add state 18 as "segment cleaning" +* Device: Add easily accessible properties to DeviceError exception +* Always import DeviceError exception +* Require click version \>=7 +* Remove pretty\_cron and typing dependencies from requirements.txt + +## [0.4.6](https://github.com/rytilahti/python-miio/tree/0.4.6) + +[Full Changelog](https://github.com/rytilahti/python-miio/compare/0.4.5...0.4.6) + +**Closed issues:** + +- Roborock Vacuum Bin full [\#546](https://github.com/rytilahti/python-miio/issues/546) +- Add support for Xiao AI Smart Alarm Clock [\#538](https://github.com/rytilahti/python-miio/issues/538) +- rockrobo.vacuum.v1 Error: No response from the device [\#536](https://github.com/rytilahti/python-miio/issues/536) +- Assistance [\#532](https://github.com/rytilahti/python-miio/issues/532) +- Unsupported device found - roborock.vacuum.s5 [\#527](https://github.com/rytilahti/python-miio/issues/527) +- Discovery mode to chuangmi\_camera. [\#522](https://github.com/rytilahti/python-miio/issues/522) +- 新款小米1X电风扇不支持 [\#520](https://github.com/rytilahti/python-miio/issues/520) +- Add swing mode of a Chigo Air Conditioner [\#518](https://github.com/rytilahti/python-miio/issues/518) +- Discover not working with Mi AirHumidifier CA1 [\#514](https://github.com/rytilahti/python-miio/issues/514) +- Question about vacuum errors\_codes duration [\#511](https://github.com/rytilahti/python-miio/issues/511) +- Support device model dmaker.fan.p5 [\#510](https://github.com/rytilahti/python-miio/issues/510) +- Roborock S50: ERROR:miio.updater:No request was made.. [\#508](https://github.com/rytilahti/python-miio/issues/508) +- Roborock S50: losing connection with mirobo [\#507](https://github.com/rytilahti/python-miio/issues/507) +- Support for Xiaomi IR Remote \(chuangmi.remote.v2\) [\#506](https://github.com/rytilahti/python-miio/issues/506) +- Support for Humidifier new model: zhimi.humidifier.cb1 [\#492](https://github.com/rytilahti/python-miio/issues/492) +- impossible to get the last version \(0.4.5\) or even the 0.4.4 [\#489](https://github.com/rytilahti/python-miio/issues/489) +- Getting the token of Air Purifier Pro v7 [\#461](https://github.com/rytilahti/python-miio/issues/461) +- Moonlight sync with HA [\#452](https://github.com/rytilahti/python-miio/issues/452) +- Replace pretty-cron dependency with cron\_descriptor [\#423](https://github.com/rytilahti/python-miio/issues/423) + +**Merged pull requests:** + +- remove pretty\_cron and typing dependencies from requirements.txt [\#548](https://github.com/rytilahti/python-miio/pull/548) ([rytilahti](https://github.com/rytilahti)) +- Add tinymu smart toiletlid [\#544](https://github.com/rytilahti/python-miio/pull/544) ([scp10011](https://github.com/scp10011)) +- Add support for Air Quality Monitor S1 \(cgllc.airmonitor.s1\) [\#539](https://github.com/rytilahti/python-miio/pull/539) ([zhumuht](https://github.com/zhumuht)) +- Add pwzn relay [\#537](https://github.com/rytilahti/python-miio/pull/537) ([SchumyHao](https://github.com/SchumyHao)) +- add mi dehumidifier v1 \(nwt.derh.wdh318efw1\) [\#535](https://github.com/rytilahti/python-miio/pull/535) ([stkang](https://github.com/stkang)) +- add mi robot s1 \(m1s\) to discovery [\#531](https://github.com/rytilahti/python-miio/pull/531) ([rytilahti](https://github.com/rytilahti)) +- Add preliminary Roborock M1S / Mi Robot S1 support [\#526](https://github.com/rytilahti/python-miio/pull/526) ([syssi](https://github.com/syssi)) +- Add state 18 as "segment cleaning" [\#525](https://github.com/rytilahti/python-miio/pull/525) ([syssi](https://github.com/syssi)) +- Add particular swing mode values of a chigo air conditioner [\#519](https://github.com/rytilahti/python-miio/pull/519) ([syssi](https://github.com/syssi)) +- Add chuangmi.camera.ipc009 support [\#516](https://github.com/rytilahti/python-miio/pull/516) ([impankratov](https://github.com/impankratov)) +- Add zhimi.fan.za3 support [\#515](https://github.com/rytilahti/python-miio/pull/515) ([syssi](https://github.com/syssi)) +- Add dmaker.fan.p5 support [\#513](https://github.com/rytilahti/python-miio/pull/513) ([syssi](https://github.com/syssi)) +- Add zhimi.fan.za4 support [\#512](https://github.com/rytilahti/python-miio/pull/512) ([syssi](https://github.com/syssi)) +- Require click version \>=7 [\#503](https://github.com/rytilahti/python-miio/pull/503) ([fvollmer](https://github.com/fvollmer)) +- Add indicator led support of the chuangmi.remote.h102a03 and chuangmi.remote.v2 [\#500](https://github.com/rytilahti/python-miio/pull/500) ([syssi](https://github.com/syssi)) +- Chuangmi Plug: Fix set\_wifi\_led cli command [\#499](https://github.com/rytilahti/python-miio/pull/499) ([syssi](https://github.com/syssi)) +- Add discovery of the Xiaomi IR remote 2gen \(chuangmi.remote.h102a03\) [\#497](https://github.com/rytilahti/python-miio/pull/497) ([syssi](https://github.com/syssi)) +- Air Humidifier: Handle poweroff exception on set\_mode [\#496](https://github.com/rytilahti/python-miio/pull/496) ([syssi](https://github.com/syssi)) +- Add zhimi.humidifier.cb1 support [\#493](https://github.com/rytilahti/python-miio/pull/493) ([antylama](https://github.com/antylama)) +- Add easily accessible properties to DeviceError exception [\#488](https://github.com/rytilahti/python-miio/pull/488) ([syssi](https://github.com/syssi)) +- Always import DeviceError exception [\#487](https://github.com/rytilahti/python-miio/pull/487) ([syssi](https://github.com/syssi)) + + ## [0.4.5](https://github.com/rytilahti/python-miio/tree/0.4.5) This release adds support for the following new devices: diff --git a/README.rst b/README.rst index 2d7270df1..2e79aa921 100644 --- a/README.rst +++ b/README.rst @@ -1,7 +1,7 @@ python-miio =========== -|PyPI version| |Build Status| |Code Health| |Coverage Status| |Docs| |Hound| +|PyPI version| |Build Status| |Coverage Status| |Docs| |Hound| This library (and its accompanying cli tool) is used to interface with devices using Xiaomi's `miIO protocol `__. @@ -9,7 +9,7 @@ This library (and its accompanying cli tool) is used to interface with devices u Supported devices ----------------- -- :doc:`Xiaomi Mi Robot Vacuum ` (:class:`miio.vacuum`) +- :doc:`Xiaomi Mi Robot Vacuum ` V1, S5, M1S (:class:`miio.vacuum`) - Xiaomi Mi Home Air Conditioner Companion (:class:`miio.airconditioningcompanion`) - Xiaomi Mi Air Purifier (:class:`miio.airpurifier`) - Xiaomi Aqara Camera (:class:`miia.aqaracamera`) @@ -24,10 +24,10 @@ Supported devices - Xiaomi Philips Zhirui Smart LED Bulb E14 Candle Lamp (:class:`miio.philips_bulb`) - Xiaomi Philips Zhirui Bedroom Smart Lamp (:class:`miio.philips_moonlight`) - Xiaomi Universal IR Remote Controller (Chuangmi IR) (:class:`miio.chuangmi_ir`) -- Xiaomi Mi Smart Pedestal Fan V2, V3, SA1, ZA1, ZA3, ZA4 (:class:`miio.fan`) -- Xiaomi Mi Air Humidifier (:class:`miio.airhumidifier`) +- Xiaomi Mi Smart Pedestal Fan V2, V3, SA1, ZA1, ZA3, ZA4, P5 (:class:`miio.fan`) +- Xiaomi Mi Air Humidifier V1, CA1, CB1 (:class:`miio.airhumidifier`) - Xiaomi Mi Water Purifier (Basic support: Turn on & off) (:class:`miio.waterpurifier`) -- Xiaomi PM2.5 Air Quality Monitor (:class:`miio.airqualitymonitor`) +- Xiaomi PM2.5 Air Quality Monitor V1, B1, S1 (:class:`miio.airqualitymonitor`) - Xiaomi Smart WiFi Speaker (:class:`miio.wifispeaker`) - Xiaomi Mi WiFi Repeater 2 (:class:`miio.wifirepeater`) - Xiaomi Mi Smart Rice Cooker (:class:`miio.cooker`) diff --git a/miio/airdehumidifier.py b/miio/airdehumidifier.py index fd22c0270..2764d6479 100755 --- a/miio/airdehumidifier.py +++ b/miio/airdehumidifier.py @@ -126,7 +126,7 @@ def fan_speed(self) -> Optional[FanSpeed]: @property def tank_full(self) -> bool: """The remaining amount of water in percent.""" - return self.data["tank_full"] + return self.data["tank_full"] == "on" @property def compressor_status(self) -> bool: diff --git a/miio/airqualitymonitor.py b/miio/airqualitymonitor.py index 85439f521..0a1df6566 100644 --- a/miio/airqualitymonitor.py +++ b/miio/airqualitymonitor.py @@ -1,5 +1,6 @@ import logging from collections import defaultdict +from typing import Optional import click @@ -54,9 +55,11 @@ def __init__(self, data): self.data = data @property - def power(self) -> str: + def power(self) -> Optional[str]: """Current power state.""" - return self.data["power"] + if "power" in self.data and self.data["power"] is not None: + return self.data["power"] + return None @property def is_on(self) -> bool: @@ -64,14 +67,18 @@ def is_on(self) -> bool: return self.power == "on" @property - def usb_power(self) -> bool: + def usb_power(self) -> Optional[bool]: """Return True if the device's usb is on.""" - return self.data["usb_state"] == "on" + if "usb_state" in self.data and self.data["usb_state"] is not None: + return self.data["usb_state"] == "on" + return None @property - def aqi(self) -> int: + def aqi(self) -> Optional[int]: """Air quality index value. (0...600).""" - return self.data["aqi"] + if "aqi" in self.data and self.data["aqi"] is not None: + return self.data["aqi"] + return None @property def battery(self) -> int: @@ -79,54 +86,74 @@ def battery(self) -> int: return self.data["battery"] @property - def display_clock(self) -> bool: + def display_clock(self) -> Optional[bool]: """Display a clock instead the AQI.""" - return self.data["time_state"] == "on" + if "time_state" in self.data and self.data["time_state"] is not None: + return self.data["time_state"] == "on" + return None @property - def night_mode(self) -> bool: + def night_mode(self) -> Optional[bool]: """Return True if the night mode is on.""" - return self.data["night_state"] == "on" + if "night_state" in self.data and self.data["night_state"] is not None: + return self.data["night_state"] == "on" + return None @property - def night_time_begin(self) -> str: + def night_time_begin(self) -> Optional[str]: """Return the begin of the night time.""" - return self.data["night_beg_time"] + if "night_beg_time" in self.data and self.data["night_beg_time"] is not None: + return self.data["night_beg_time"] + return None @property - def night_time_end(self) -> str: + def night_time_end(self) -> Optional[str]: """Return the end of the night time.""" - return self.data["night_end_time"] + if "night_end_time" in self.data and self.data["night_end_time"] is not None: + return self.data["night_end_time"] + return None @property - def sensor_state(self) -> str: + def sensor_state(self) -> Optional[str]: """Sensor state.""" - return self.data["sensor_state"] + if "sensor_state" in self.data and self.data["sensor_state"] is not None: + return self.data["sensor_state"] + return None @property - def co2(self) -> int: + def co2(self) -> Optional[int]: """Return co2 value (400...9999)ppm for MODEL_AIRQUALITYMONITOR_S1.""" - return self.data["co2"] + if "co2" in self.data and self.data["co2"] is not None: + return self.data["co2"] + return None @property - def humidity(self) -> float: + def humidity(self) -> Optional[float]: """Return humidity value (0...100)% for MODEL_AIRQUALITYMONITOR_S1.""" - return self.data["humidity"] + if "humidity" in self.data and self.data["humidity"] is not None: + return self.data["humidity"] + return None @property - def pm25(self) -> float: + def pm25(self) -> Optional[float]: """Return pm2.5 value (0...999)μg/m³ for MODEL_AIRQUALITYMONITOR_S1.""" - return self.data["pm25"] + if "pm25" in self.data and self.data["pm25"] is not None: + return self.data["pm25"] + return None @property - def temperature(self) -> float: + def temperature(self) -> Optional[float]: """Return temperature value (-10...50)°C for MODEL_AIRQUALITYMONITOR_S1.""" - return self.data["temperature"] + if "temperature" in self.data and self.data["temperature"] is not None: + return self.data["temperature"] + return None @property - def tvoc(self) -> int: + def tvoc(self) -> Optional[int]: """Return tvoc value for MODEL_AIRQUALITYMONITOR_S1.""" - return self.data["tvoc"] + if "tvoc" in self.data and self.data["tvoc"] is not None: + return self.data["tvoc"] + return None def __repr__(self) -> str: s = "