From 6e083cc0a1dd0adc1c7a05423dbbaa1567767fe0 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Mon, 22 Jan 2018 22:11:06 +0100 Subject: [PATCH 01/16] New properties added: child_lock, limit_hum, trans_level --- miio/airhumidifier.py | 61 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index cc45645e7..02fa194fc 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -7,6 +7,10 @@ _LOGGER = logging.getLogger(__name__) +class AirHumidifierException(Exception): + pass + + class OperationMode(enum.Enum): Silent = 'silent' Medium = 'medium' @@ -27,7 +31,8 @@ def __init__(self, data: Dict[str, Any]) -> None: Response of a Air Humidifier (zhimi.humidifier.v1): {'power': 'off', 'mode': 'high', 'temp_dec': 294, - 'humidity': 33, 'buzzer': 'on', 'led_b': 0} + 'humidity': 33, 'buzzer': 'on', 'led_b': 0, + 'child_lock': 'on', 'limit_hum': 40} """ self.data = data @@ -71,11 +76,40 @@ def led_brightness(self) -> Optional[LedBrightness]: return LedBrightness(self.data["led_b"]) return None + @property + def child_lock(self) -> bool: + """Return True if child lock is on.""" + return self.data["child_lock"] == "on" + + @property + def target_humidity(self) -> int: + """Target humiditiy. Can be either 40, 50, 60, 70, 80 percent.""" + return self.data["limit_hum"] + + @property + def trans_level(self) -> int: + """Meaning unknown.""" + return self.data["trans_level"] + def __str__(self) -> str: - s = "" % \ - (self.power, self.mode, self.temperature, - self.humidity, self.led_brightness, self.buzzer) + s = "" % \ + (self.power, + self.mode, + self.temperature, + self.humidity, + self.led_brightness, + self.buzzer, + self.child_lock, + self.target_humidity, + self.trans_level) return s @@ -86,7 +120,7 @@ def status(self) -> AirHumidifierStatus: """Retrieve properties.""" properties = ['power', 'mode', 'temp_dec', 'humidity', 'buzzer', - 'led_b', ] + 'led_b', 'child_lock', 'limit_hum', 'trans_level', ] values = self.send( "get_prop", @@ -126,3 +160,18 @@ def set_buzzer(self, buzzer: bool): return self.send("set_buzzer", ["on"]) else: return self.send("set_buzzer", ["off"]) + + def set_child_lock(self, lock: bool): + """Set child lock on/off.""" + if lock: + return self.send("set_child_lock", ["on"]) + else: + return self.send("set_child_lock", ["off"]) + + def set_target_humidity(self, humidity: int): + """Set the target humidity.""" + if humidity not in [40, 50, 60, 70, 80]: + raise AirHumidifierException( + "Invalid target humidity: %s" % humidity) + + return self.send("set_limit_hum", [humidity]) From 204d0d3fee484e6946cd0f47488017b87371bb1d Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 05:52:40 +0100 Subject: [PATCH 02/16] trans_level renamed: It's called favorite_level now. --- miio/airhumidifier.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index 02fa194fc..895c43d9f 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -32,7 +32,7 @@ def __init__(self, data: Dict[str, Any]) -> None: {'power': 'off', 'mode': 'high', 'temp_dec': 294, 'humidity': 33, 'buzzer': 'on', 'led_b': 0, - 'child_lock': 'on', 'limit_hum': 40} + 'child_lock': 'on', 'limit_hum': 40, 'trans_level': 85} """ self.data = data @@ -87,8 +87,9 @@ def target_humidity(self) -> int: return self.data["limit_hum"] @property - def trans_level(self) -> int: - """Meaning unknown.""" + def favorite_level(self) -> int: + """Return favorite level, which is used if the mode is ``favorite``.""" + # Favorite level used when the mode is `favorite`. return self.data["trans_level"] def __str__(self) -> str: @@ -175,3 +176,12 @@ def set_target_humidity(self, humidity: int): "Invalid target humidity: %s" % humidity) return self.send("set_limit_hum", [humidity]) + + def set_favorite_level(self, level: int): + """Set favorite level.""" + if level < 30 or level > 85: + raise AirHumidifierException("Invalid favorite level: %s" % level) + + # Set the favorite level used when the mode is `favorite`, + # should be between 30 and 85. + return self.send("set_trans_level", [level]) # 30 ... 85 From 552327af65dff3f5492ec0600ccfd4ea86e154e5 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:16:12 +0100 Subject: [PATCH 03/16] Tests extended. --- miio/tests/test_airhumidifier.py | 68 ++++++++++++++++++++++++++++++-- miio/tests/test_airpurifier.py | 15 ++----- 2 files changed, 68 insertions(+), 15 deletions(-) diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 317f4c85d..71a534882 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -1,6 +1,6 @@ from unittest import TestCase from miio import AirHumidifier -from miio.airhumidifier import OperationMode, LedBrightness +from miio.airhumidifier import OperationMode, LedBrightness, AirHumidifierException from .dummies import DummyDevice import pytest @@ -10,10 +10,13 @@ def __init__(self, *args, **kwargs): self.state = { 'power': 'on', 'mode': 'medium', - 'temp_dec': 186, - 'humidity': 62, + 'temp_dec': 294, + 'humidity': 33, 'buzzer': 'off', 'led_b': 2, + 'child_lock': 'on', + 'limit_hum': 40, + 'trans_level': 85, } self.return_values = { 'get_prop': self._get_state, @@ -21,6 +24,8 @@ def __init__(self, *args, **kwargs): 'set_mode': lambda x: self._set_state("mode", x), 'set_led_b': lambda x: self._set_state("led_b", x), 'set_buzzer': lambda x: self._set_state("buzzer", x), + 'set_child_lock': lambda x: self._set_state("child_lock", x), + 'set_trans_level': lambda x: self._set_state("trans_level", x), } super().__init__(args, kwargs) @@ -64,6 +69,9 @@ def test_status(self): assert self.state().mode == OperationMode(self.device.start_state["mode"]) assert self.state().led_brightness == LedBrightness(self.device.start_state["led_b"]) assert self.state().buzzer == (self.device.start_state["buzzer"] == 'on') + assert self.state().child_lock == (self.device.start_state["child_lock"] == 'on') + assert self.state().target_humidity == self.device.start_state["limit_hum"] + assert self.state().favorite_level == self.device.start_state["trans_level"] def test_set_mode(self): def mode(): @@ -112,3 +120,57 @@ def test_status_without_led_brightness(self): self.device.state["led_b"] = None assert self.state().led_brightness is None + + def test_set_target_humidity(self): + def target_humidity(): + return self.device.status().target_humidity + + self.device.set_target_humidity(40) + assert target_humidity() == 40 + self.device.set_target_humidity(60) + assert target_humidity() == 60 + self.device.set_target_humidity(80) + assert target_humidity() == 80 + + with pytest.raises(AirHumidifierException): + self.device.set_target_humidity(-1) + + with pytest.raises(AirHumidifierException): + self.device.set_target_humidity(30) + + with pytest.raises(AirHumidifierException): + self.device.set_target_humidity(90) + + with pytest.raises(AirHumidifierException): + self.device.set_target_humidity(110) + + def test_set_favorite_level(self): + def favorite_level(): + return self.device.status().favorite_level + + self.device.set_favorite_level(30) + assert favorite_level() == 30 + self.device.set_favorite_level(55) + assert favorite_level() == 55 + self.device.set_favorite_level(85) + assert favorite_level() == 85 + + with pytest.raises(AirHumidifierException): + self.device.set_favorite_level(-1) + + with pytest.raises(AirHumidifierException): + self.device.set_favorite_level(29) + + with pytest.raises(AirHumidifierException): + self.device.set_favorite_level(86) + + def test_set_child_lock(self): + def child_lock(): + return self.device.status().child_lock + + self.device.set_child_lock(True) + assert child_lock() is True + + self.device.set_child_lock(False) + assert child_lock() is False + diff --git a/miio/tests/test_airpurifier.py b/miio/tests/test_airpurifier.py index 48069b110..39d4bd688 100644 --- a/miio/tests/test_airpurifier.py +++ b/miio/tests/test_airpurifier.py @@ -117,6 +117,7 @@ def favorite_level(): self.device.set_favorite_level(6) assert favorite_level() == 6 self.device.set_favorite_level(10) + assert favorite_level() == 10 with pytest.raises(AirPurifierException): self.device.set_favorite_level(-1) @@ -141,7 +142,6 @@ def test_set_led(self): def led(): return self.device.status().led - # The LED brightness of a Air Purifier Pro cannot be set so far. self.device.set_led(True) assert led() is True @@ -168,20 +168,11 @@ def child_lock(): self.device.set_child_lock(False) assert child_lock() is False - def test_status_without_led_b_and_with_bright(self): - self.device._reset_state() - - self.device.state["bright"] = self.device.state["led_b"] - del self.device.state["led_b"] - - assert self.state().led_brightness == LedBrightness( - self.device.start_state["led_b"]) - - def test_status_without_led_brightness_at_all(self): + def test_status_without_led_brightness(self): self.device._reset_state() + # The Air Purifier Pro doesn't support LED brightness self.device.state["led_b"] = None - self.device.state["bright"] = None assert self.state().led_brightness is None def test_status_without_temperature(self): From 0d2b4e8b6a92e5df431073d66f7eb8110bf99ea5 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:24:25 +0100 Subject: [PATCH 04/16] Missing lambda function added. --- miio/tests/test_airhumidifier.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 71a534882..3720184fe 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -25,6 +25,7 @@ def __init__(self, *args, **kwargs): 'set_led_b': lambda x: self._set_state("led_b", x), 'set_buzzer': lambda x: self._set_state("buzzer", x), 'set_child_lock': lambda x: self._set_state("child_lock", x), + 'set_limit_hum': lambda x: self._set_state("limit_hum", x), 'set_trans_level': lambda x: self._set_state("trans_level", x), } super().__init__(args, kwargs) @@ -172,5 +173,4 @@ def child_lock(): assert child_lock() is True self.device.set_child_lock(False) - assert child_lock() is False - + assert child_lock() is False \ No newline at end of file From aaa7c4e0e776de7a652ca63eeb1181feddf5d94d Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:38:11 +0100 Subject: [PATCH 05/16] Tests of the air purifier improved. --- miio/airpurifier.py | 3 +++ miio/tests/test_airpurifier.py | 44 +++++++++++++++++++++++++++++++--- 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/miio/airpurifier.py b/miio/airpurifier.py index b6b9a35f5..2082cfc0e 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -279,4 +279,7 @@ def set_child_lock(self, lock: bool): def set_volume(self, volume: int): """Set volume of sound notifications [0-100].""" + if volume < 0 or volume > 100: + raise AirPurifierException("Invalid volume: %s" % volume) + return self.send("set_volume", [volume]) diff --git a/miio/tests/test_airpurifier.py b/miio/tests/test_airpurifier.py index 39d4bd688..4ee485d64 100644 --- a/miio/tests/test_airpurifier.py +++ b/miio/tests/test_airpurifier.py @@ -23,9 +23,10 @@ def __init__(self, *args, **kwargs): 'f1_hour': 3500, 'led': 'off', 'led_b': 2, - 'bright': None, + 'bright': 83, 'buzzer': 'off', - 'child_lock': 'off' + 'child_lock': 'off', + 'volumne': 50, } self.return_values = { 'get_prop': self._get_state, @@ -37,6 +38,7 @@ def __init__(self, *args, **kwargs): 'set_level_favorite': lambda x: self._set_state("favorite_level", x), 'set_led_b': lambda x: self._set_state("led_b", x), + 'set_volume': lambda x: self._set_state("volume", x), } super().__init__(args, kwargs) @@ -91,6 +93,7 @@ def test_status(self): assert self.state().led_brightness == LedBrightness(self.device.start_state["led_b"]) assert self.state().buzzer == (self.device.start_state["buzzer"] == 'on') assert self.state().child_lock == (self.device.start_state["child_lock"] == 'on') + assert self.state().illuminance == self.device.start_state["bright"] def test_set_mode(self): def mode(): @@ -168,6 +171,30 @@ def child_lock(): self.device.set_child_lock(False) assert child_lock() is False + def test_set_volume(self): + def volume(): + return self.device.status().volume + + self.device.set_volume(0) + assert volume() == 0 + self.device.set_volume(35) + assert volume() == 35 + self.device.set_volume(100) + assert volume() == 100 + + with pytest.raises(AirPurifierException): + self.device.set_volume(-1) + + with pytest.raises(AirPurifierException): + self.device.set_volume(101) + + def test_status_without_volume(self): + self.device._reset_state() + + # The Air Purifier 2 doesn't support volume + self.device.state["volume"] = None + assert self.state().volume is None + def test_status_without_led_brightness(self): self.device._reset_state() @@ -178,5 +205,16 @@ def test_status_without_led_brightness(self): def test_status_without_temperature(self): self.device._reset_state() self.device.state["temp_dec"] = None - assert self.state().temperature is None + + def test_status_without_illuminance(self): + self.device._reset_state() + # The Air Purifier 2 doesn't provide illuminance + self.device.state["bright"] = None + assert self.state().illuminance is None + + def test_status_without_buzzer(self): + self.device._reset_state() + # The Air Purifier Pro doesn't provide the buzzer property + self.device.state["buzzer"] = None + assert self.state().buzzer is None From 15586f7cc46597babf6688c4de2a42663f237461 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:39:04 +0100 Subject: [PATCH 06/16] New line added. --- miio/tests/test_airhumidifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 3720184fe..b7a56319d 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -173,4 +173,4 @@ def child_lock(): assert child_lock() is True self.device.set_child_lock(False) - assert child_lock() is False \ No newline at end of file + assert child_lock() is False From 51d381b192d5d05288b350ea6c8cf0ca613d932a Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:44:18 +0100 Subject: [PATCH 07/16] Provide no buzzer state (true/false) if there is no buzzer available. --- miio/airpurifier.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/miio/airpurifier.py b/miio/airpurifier.py index 2082cfc0e..42a3a100d 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -109,9 +109,12 @@ def illuminance(self) -> Optional[int]: return self.data["bright"] @property - def buzzer(self) -> bool: + def buzzer(self) -> Optional[bool]: """Return True if buzzer is on.""" - return self.data["buzzer"] == "on" + if self.data["buzzer"] is not None: + return self.data["buzzer"] == "on" + + return None @property def child_lock(self) -> bool: From cdfe82c69f2fbc2ad40f19aafc9ce51a9fd75ae1 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:49:19 +0100 Subject: [PATCH 08/16] Typo fixed and volume assertion added to the status call. --- miio/tests/test_airpurifier.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miio/tests/test_airpurifier.py b/miio/tests/test_airpurifier.py index 4ee485d64..94c2a55aa 100644 --- a/miio/tests/test_airpurifier.py +++ b/miio/tests/test_airpurifier.py @@ -26,7 +26,7 @@ def __init__(self, *args, **kwargs): 'bright': 83, 'buzzer': 'off', 'child_lock': 'off', - 'volumne': 50, + 'volume': 50, } self.return_values = { 'get_prop': self._get_state, @@ -94,6 +94,7 @@ def test_status(self): assert self.state().buzzer == (self.device.start_state["buzzer"] == 'on') assert self.state().child_lock == (self.device.start_state["child_lock"] == 'on') assert self.state().illuminance == self.device.start_state["bright"] + assert self.state().volume == self.device.start_state["volume"] def test_set_mode(self): def mode(): From 3eb5c88c7f5e629a4fe5b7f7b57d54f6a07e6277 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 23 Jan 2018 06:52:56 +0100 Subject: [PATCH 09/16] Updates of the air purifier moved to a second pull request. --- miio/airpurifier.py | 10 ++----- miio/tests/test_airpurifier.py | 54 ++++++++-------------------------- 2 files changed, 14 insertions(+), 50 deletions(-) diff --git a/miio/airpurifier.py b/miio/airpurifier.py index 42a3a100d..b6b9a35f5 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -109,12 +109,9 @@ def illuminance(self) -> Optional[int]: return self.data["bright"] @property - def buzzer(self) -> Optional[bool]: + def buzzer(self) -> bool: """Return True if buzzer is on.""" - if self.data["buzzer"] is not None: - return self.data["buzzer"] == "on" - - return None + return self.data["buzzer"] == "on" @property def child_lock(self) -> bool: @@ -282,7 +279,4 @@ def set_child_lock(self, lock: bool): def set_volume(self, volume: int): """Set volume of sound notifications [0-100].""" - if volume < 0 or volume > 100: - raise AirPurifierException("Invalid volume: %s" % volume) - return self.send("set_volume", [volume]) diff --git a/miio/tests/test_airpurifier.py b/miio/tests/test_airpurifier.py index 94c2a55aa..48069b110 100644 --- a/miio/tests/test_airpurifier.py +++ b/miio/tests/test_airpurifier.py @@ -23,10 +23,9 @@ def __init__(self, *args, **kwargs): 'f1_hour': 3500, 'led': 'off', 'led_b': 2, - 'bright': 83, + 'bright': None, 'buzzer': 'off', - 'child_lock': 'off', - 'volume': 50, + 'child_lock': 'off' } self.return_values = { 'get_prop': self._get_state, @@ -38,7 +37,6 @@ def __init__(self, *args, **kwargs): 'set_level_favorite': lambda x: self._set_state("favorite_level", x), 'set_led_b': lambda x: self._set_state("led_b", x), - 'set_volume': lambda x: self._set_state("volume", x), } super().__init__(args, kwargs) @@ -93,8 +91,6 @@ def test_status(self): assert self.state().led_brightness == LedBrightness(self.device.start_state["led_b"]) assert self.state().buzzer == (self.device.start_state["buzzer"] == 'on') assert self.state().child_lock == (self.device.start_state["child_lock"] == 'on') - assert self.state().illuminance == self.device.start_state["bright"] - assert self.state().volume == self.device.start_state["volume"] def test_set_mode(self): def mode(): @@ -121,7 +117,6 @@ def favorite_level(): self.device.set_favorite_level(6) assert favorite_level() == 6 self.device.set_favorite_level(10) - assert favorite_level() == 10 with pytest.raises(AirPurifierException): self.device.set_favorite_level(-1) @@ -146,6 +141,7 @@ def test_set_led(self): def led(): return self.device.status().led + # The LED brightness of a Air Purifier Pro cannot be set so far. self.device.set_led(True) assert led() is True @@ -172,50 +168,24 @@ def child_lock(): self.device.set_child_lock(False) assert child_lock() is False - def test_set_volume(self): - def volume(): - return self.device.status().volume - - self.device.set_volume(0) - assert volume() == 0 - self.device.set_volume(35) - assert volume() == 35 - self.device.set_volume(100) - assert volume() == 100 - - with pytest.raises(AirPurifierException): - self.device.set_volume(-1) - - with pytest.raises(AirPurifierException): - self.device.set_volume(101) - - def test_status_without_volume(self): + def test_status_without_led_b_and_with_bright(self): self.device._reset_state() - # The Air Purifier 2 doesn't support volume - self.device.state["volume"] = None - assert self.state().volume is None + self.device.state["bright"] = self.device.state["led_b"] + del self.device.state["led_b"] + + assert self.state().led_brightness == LedBrightness( + self.device.start_state["led_b"]) - def test_status_without_led_brightness(self): + def test_status_without_led_brightness_at_all(self): self.device._reset_state() - # The Air Purifier Pro doesn't support LED brightness self.device.state["led_b"] = None + self.device.state["bright"] = None assert self.state().led_brightness is None def test_status_without_temperature(self): self.device._reset_state() self.device.state["temp_dec"] = None - assert self.state().temperature is None - def test_status_without_illuminance(self): - self.device._reset_state() - # The Air Purifier 2 doesn't provide illuminance - self.device.state["bright"] = None - assert self.state().illuminance is None - - def test_status_without_buzzer(self): - self.device._reset_state() - # The Air Purifier Pro doesn't provide the buzzer property - self.device.state["buzzer"] = None - assert self.state().buzzer is None + assert self.state().temperature is None From 000d06e3a9448550ae5588a74e29c2d7bcf9028c Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 24 Jan 2018 08:50:19 +0100 Subject: [PATCH 10/16] All device specific exceptions derives from DeviceException now. --- miio/airconditioningcompanion.py | 2 +- miio/airhumidifier.py | 4 ++-- miio/airpurifier.py | 4 ++-- miio/ceil.py | 4 ++-- miio/chuangmi_ir.py | 6 +++++- miio/fan.py | 2 +- miio/philips_bulb.py | 4 ++-- miio/philips_eyecare.py | 4 ++-- miio/yeelight.py | 4 ++-- 9 files changed, 19 insertions(+), 15 deletions(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index 410a8ada4..753392311 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -1,6 +1,6 @@ -from .device import Device import enum from typing import Optional +from .device import Device class OperationMode(enum.Enum): diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index 895c43d9f..cf695193a 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -2,12 +2,12 @@ import enum from typing import Any, Dict, Optional from collections import defaultdict -from .device import Device +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class AirHumidifierException(Exception): +class AirHumidifierException(DeviceException): pass diff --git a/miio/airpurifier.py b/miio/airpurifier.py index b6b9a35f5..03611f33f 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -2,12 +2,12 @@ import enum from typing import Any, Dict, Optional from collections import defaultdict -from .device import Device +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class AirPurifierException(Exception): +class AirPurifierException(DeviceException): pass diff --git a/miio/ceil.py b/miio/ceil.py index 04dc38771..46004fbb4 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -1,12 +1,12 @@ import logging -from .device import Device from typing import Any, Dict from collections import defaultdict +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class CeilException(Exception): +class CeilException(DeviceException): pass diff --git a/miio/chuangmi_ir.py b/miio/chuangmi_ir.py index fc5cb911c..ad1efb95d 100644 --- a/miio/chuangmi_ir.py +++ b/miio/chuangmi_ir.py @@ -1,6 +1,10 @@ from .device import Device, DeviceException +class ChuangmiIrException(DeviceException): + pass + + class ChuangmiIr(Device): """Main class representing Chuangmi IR Remote Controller.""" @@ -10,7 +14,7 @@ def learn(self, key: int): :param int key: Storage slot, must be between 1 and 1000000""" if key < 1 or key > 1000000: - raise DeviceException("Invalid parameter FIXME wrong exception") + raise ChuangmiIrException("Invalid storage slot.") return self.send("miIO.ir_learn", {'key': str(key)}) def read(self, key: int): diff --git a/miio/fan.py b/miio/fan.py index 61e074687..8296d92cb 100644 --- a/miio/fan.py +++ b/miio/fan.py @@ -1,7 +1,7 @@ import logging -from .device import Device from typing import Any, Dict, Optional import enum +from .device import Device _LOGGER = logging.getLogger(__name__) diff --git a/miio/philips_bulb.py b/miio/philips_bulb.py index cd36cd918..84938d7e7 100644 --- a/miio/philips_bulb.py +++ b/miio/philips_bulb.py @@ -1,12 +1,12 @@ import logging -from .device import Device from typing import Any, Dict from collections import defaultdict +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class PhilipsBulbException(Exception): +class PhilipsBulbException(DeviceException): pass diff --git a/miio/philips_eyecare.py b/miio/philips_eyecare.py index dd8468d31..72eda0e25 100644 --- a/miio/philips_eyecare.py +++ b/miio/philips_eyecare.py @@ -1,12 +1,12 @@ import logging -from .device import Device from typing import Any, Dict from collections import defaultdict +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class PhilipsEyecareException(Exception): +class PhilipsEyecareException(DeviceException): pass diff --git a/miio/yeelight.py b/miio/yeelight.py index 05d78fe9a..ed3315a3c 100644 --- a/miio/yeelight.py +++ b/miio/yeelight.py @@ -1,10 +1,10 @@ -from .device import Device from typing import Tuple, Optional from enum import IntEnum import warnings +from .device import Device, DeviceException -class YeelightException(Exception): +class YeelightException(DeviceException): pass From 02e1e53bc0b08d83b70507193fed7667b5c11227 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 24 Jan 2018 08:55:25 +0100 Subject: [PATCH 11/16] Flake8 configuration updated: max-line-length = 100 --- tox.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/tox.ini b/tox.ini index 93fe3c90e..0af1a1059 100644 --- a/tox.ini +++ b/tox.ini @@ -35,6 +35,7 @@ commands=flake8 miio [flake8] exclude = .git,.tox,__pycache__ +max-line-length = 100 [testenv:typing] deps=mypy From 55b2f0a67eb0126c2dbb20fdd85bebdc4e849f1e Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 24 Jan 2018 22:06:10 +0100 Subject: [PATCH 12/16] trans_level is a read-only property and depends on the operation mode. --- miio/airhumidifier.py | 14 ++------------ miio/tests/test_airhumidifier.py | 21 --------------------- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index cf695193a..7205640d9 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -87,9 +87,8 @@ def target_humidity(self) -> int: return self.data["limit_hum"] @property - def favorite_level(self) -> int: - """Return favorite level, which is used if the mode is ``favorite``.""" - # Favorite level used when the mode is `favorite`. + def trans_level(self) -> int: + """The meaning of the property is unknown.""" return self.data["trans_level"] def __str__(self) -> str: @@ -176,12 +175,3 @@ def set_target_humidity(self, humidity: int): "Invalid target humidity: %s" % humidity) return self.send("set_limit_hum", [humidity]) - - def set_favorite_level(self, level: int): - """Set favorite level.""" - if level < 30 or level > 85: - raise AirHumidifierException("Invalid favorite level: %s" % level) - - # Set the favorite level used when the mode is `favorite`, - # should be between 30 and 85. - return self.send("set_trans_level", [level]) # 30 ... 85 diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index b7a56319d..02693cff7 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -26,7 +26,6 @@ def __init__(self, *args, **kwargs): 'set_buzzer': lambda x: self._set_state("buzzer", x), 'set_child_lock': lambda x: self._set_state("child_lock", x), 'set_limit_hum': lambda x: self._set_state("limit_hum", x), - 'set_trans_level': lambda x: self._set_state("trans_level", x), } super().__init__(args, kwargs) @@ -145,26 +144,6 @@ def target_humidity(): with pytest.raises(AirHumidifierException): self.device.set_target_humidity(110) - def test_set_favorite_level(self): - def favorite_level(): - return self.device.status().favorite_level - - self.device.set_favorite_level(30) - assert favorite_level() == 30 - self.device.set_favorite_level(55) - assert favorite_level() == 55 - self.device.set_favorite_level(85) - assert favorite_level() == 85 - - with pytest.raises(AirHumidifierException): - self.device.set_favorite_level(-1) - - with pytest.raises(AirHumidifierException): - self.device.set_favorite_level(29) - - with pytest.raises(AirHumidifierException): - self.device.set_favorite_level(86) - def test_set_child_lock(self): def child_lock(): return self.device.status().child_lock From 29562b54c1c729505407cfcfa7f4e4e12ad7ae23 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 24 Jan 2018 22:08:33 +0100 Subject: [PATCH 13/16] DeviceException changes reverted. --- miio/airconditioningcompanion.py | 2 +- miio/airpurifier.py | 4 ++-- miio/ceil.py | 4 ++-- miio/chuangmi_ir.py | 6 +----- miio/fan.py | 2 +- miio/philips_bulb.py | 4 ++-- miio/philips_eyecare.py | 4 ++-- miio/yeelight.py | 4 ++-- 8 files changed, 13 insertions(+), 17 deletions(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index 753392311..410a8ada4 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -1,6 +1,6 @@ +from .device import Device import enum from typing import Optional -from .device import Device class OperationMode(enum.Enum): diff --git a/miio/airpurifier.py b/miio/airpurifier.py index 03611f33f..b6b9a35f5 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -2,12 +2,12 @@ import enum from typing import Any, Dict, Optional from collections import defaultdict -from .device import Device, DeviceException +from .device import Device _LOGGER = logging.getLogger(__name__) -class AirPurifierException(DeviceException): +class AirPurifierException(Exception): pass diff --git a/miio/ceil.py b/miio/ceil.py index 46004fbb4..04dc38771 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -1,12 +1,12 @@ import logging +from .device import Device from typing import Any, Dict from collections import defaultdict -from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class CeilException(DeviceException): +class CeilException(Exception): pass diff --git a/miio/chuangmi_ir.py b/miio/chuangmi_ir.py index ad1efb95d..fc5cb911c 100644 --- a/miio/chuangmi_ir.py +++ b/miio/chuangmi_ir.py @@ -1,10 +1,6 @@ from .device import Device, DeviceException -class ChuangmiIrException(DeviceException): - pass - - class ChuangmiIr(Device): """Main class representing Chuangmi IR Remote Controller.""" @@ -14,7 +10,7 @@ def learn(self, key: int): :param int key: Storage slot, must be between 1 and 1000000""" if key < 1 or key > 1000000: - raise ChuangmiIrException("Invalid storage slot.") + raise DeviceException("Invalid parameter FIXME wrong exception") return self.send("miIO.ir_learn", {'key': str(key)}) def read(self, key: int): diff --git a/miio/fan.py b/miio/fan.py index 8296d92cb..61e074687 100644 --- a/miio/fan.py +++ b/miio/fan.py @@ -1,7 +1,7 @@ import logging +from .device import Device from typing import Any, Dict, Optional import enum -from .device import Device _LOGGER = logging.getLogger(__name__) diff --git a/miio/philips_bulb.py b/miio/philips_bulb.py index 84938d7e7..cd36cd918 100644 --- a/miio/philips_bulb.py +++ b/miio/philips_bulb.py @@ -1,12 +1,12 @@ import logging +from .device import Device from typing import Any, Dict from collections import defaultdict -from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class PhilipsBulbException(DeviceException): +class PhilipsBulbException(Exception): pass diff --git a/miio/philips_eyecare.py b/miio/philips_eyecare.py index 72eda0e25..dd8468d31 100644 --- a/miio/philips_eyecare.py +++ b/miio/philips_eyecare.py @@ -1,12 +1,12 @@ import logging +from .device import Device from typing import Any, Dict from collections import defaultdict -from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) -class PhilipsEyecareException(DeviceException): +class PhilipsEyecareException(Exception): pass diff --git a/miio/yeelight.py b/miio/yeelight.py index ed3315a3c..05d78fe9a 100644 --- a/miio/yeelight.py +++ b/miio/yeelight.py @@ -1,10 +1,10 @@ +from .device import Device from typing import Tuple, Optional from enum import IntEnum import warnings -from .device import Device, DeviceException -class YeelightException(DeviceException): +class YeelightException(Exception): pass From ce2c387dec8e9236de9e2dd28ba9609437f6bb57 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 24 Jan 2018 22:12:17 +0100 Subject: [PATCH 14/16] Test fixed. --- miio/tests/test_airhumidifier.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 02693cff7..416fe1fbd 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -71,7 +71,7 @@ def test_status(self): assert self.state().buzzer == (self.device.start_state["buzzer"] == 'on') assert self.state().child_lock == (self.device.start_state["child_lock"] == 'on') assert self.state().target_humidity == self.device.start_state["limit_hum"] - assert self.state().favorite_level == self.device.start_state["trans_level"] + assert self.state().trans_level == self.device.start_state["trans_level"] def test_set_mode(self): def mode(): From ec258ba82f3d19f2648bd5c07d24ea1c96765899 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Thu, 25 Jan 2018 07:09:56 +0100 Subject: [PATCH 15/16] Additional target humidity (30 percent) allowed. --- miio/airhumidifier.py | 4 ++-- miio/tests/test_airhumidifier.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index 7205640d9..db59494a8 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -83,7 +83,7 @@ def child_lock(self) -> bool: @property def target_humidity(self) -> int: - """Target humiditiy. Can be either 40, 50, 60, 70, 80 percent.""" + """Target humiditiy. Can be either 30, 40, 50, 60, 70, 80 percent.""" return self.data["limit_hum"] @property @@ -170,7 +170,7 @@ def set_child_lock(self, lock: bool): def set_target_humidity(self, humidity: int): """Set the target humidity.""" - if humidity not in [40, 50, 60, 70, 80]: + if humidity not in [30, 40, 50, 60, 70, 80]: raise AirHumidifierException( "Invalid target humidity: %s" % humidity) diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 416fe1fbd..3b5a12fad 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -125,8 +125,8 @@ def test_set_target_humidity(self): def target_humidity(): return self.device.status().target_humidity - self.device.set_target_humidity(40) - assert target_humidity() == 40 + self.device.set_target_humidity(30) + assert target_humidity() == 30 self.device.set_target_humidity(60) assert target_humidity() == 60 self.device.set_target_humidity(80) @@ -136,7 +136,7 @@ def target_humidity(): self.device.set_target_humidity(-1) with pytest.raises(AirHumidifierException): - self.device.set_target_humidity(30) + self.device.set_target_humidity(20) with pytest.raises(AirHumidifierException): self.device.set_target_humidity(90) From b3b7e8ac969c204d2df09fa9828de21239552a04 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Thu, 25 Jan 2018 07:17:04 +0100 Subject: [PATCH 16/16] Flake8 configuration reverted. --- tox.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/tox.ini b/tox.ini index 0af1a1059..93fe3c90e 100644 --- a/tox.ini +++ b/tox.ini @@ -35,7 +35,6 @@ commands=flake8 miio [flake8] exclude = .git,.tox,__pycache__ -max-line-length = 100 [testenv:typing] deps=mypy