From 5a272b5d28cbf004f8dfc80b0bfbdad8ba7bc934 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 26 Jan 2018 17:16:28 +0100 Subject: [PATCH 1/6] Tests for optional return values added. --- miio/airconditioningcompanion.py | 26 ++++++++++++--------- miio/tests/test_airconditioningcompanion.py | 16 +++++++++++++ 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index 7984e66e9..fc259498e 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -101,9 +101,12 @@ def is_on(self) -> bool: return self.power == 'on' @property - def temperature(self) -> int: + def temperature(self) -> Optional[int]: """Current temperature.""" - return int(self.data[1][6:8], 16) + try: + return int(self.data[1][6:8], 16) + except ValueError: + return None @property def swing_mode(self) -> bool: @@ -113,20 +116,20 @@ def swing_mode(self) -> bool: @property def fan_speed(self) -> Optional[FanSpeed]: """Current fan speed.""" - speed = int(self.data[1][4:5]) - if speed is not None: + try: + speed = int(self.data[1][4:5]) return FanSpeed(speed) - - return None + except ValueError: + return None @property def mode(self) -> Optional[OperationMode]: """Current operation mode.""" - mode = int(self.data[1][3:4]) - if mode is not None: + try: + mode = int(self.data[1][3:4]) return OperationMode(mode) - - return None + except ValueError: + return None class AirConditioningCompanion(Device): @@ -175,7 +178,8 @@ def send_configuration(self, model: str, power: Power, if model in DEVICE_COMMAND_TEMPLATES: configuration = model + DEVICE_COMMAND_TEMPLATES[model]['base'] else: - configuration = model + DEVICE_COMMAND_TEMPLATES['fallback']['base'] + configuration = \ + model + DEVICE_COMMAND_TEMPLATES['fallback']['base'] configuration = configuration.replace('[po]', power.value) configuration = configuration.replace('[mo]', operation_mode.value) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index 245b35c44..7f1ae4a90 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -50,3 +50,19 @@ def test_status(self): assert self.state().swing_mode is False assert self.state().fan_speed == FanSpeed.Low assert self.state().mode == OperationMode.Auto + + def test_status_without_temperature(self): + self.device._reset_state() + self.device.state[1] = None + assert self.state().temperature is None + + def test_status_without_mode(self): + self.device._reset_state() + self.device.state[1] = None + assert self.state().mode is None + + def test_status_without_fan_speed(self): + self.device._reset_state() + self.device.state[1] = None + assert self.state().fan_speed is None + From cee9fef3baef110c7dd08352f707bbb24a580602 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 26 Jan 2018 17:21:50 +0100 Subject: [PATCH 2/6] Blank line removed. --- miio/tests/test_airconditioningcompanion.py | 1 - 1 file changed, 1 deletion(-) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index 7f1ae4a90..c60bd0236 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -65,4 +65,3 @@ def test_status_without_fan_speed(self): self.device._reset_state() self.device.state[1] = None assert self.state().fan_speed is None - From c909f2628ab514af4ea4ba63571ef6d4517cd605 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 26 Jan 2018 17:26:16 +0100 Subject: [PATCH 3/6] Catch a TypError. It cannot be a ValueError in this case. --- miio/airconditioningcompanion.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index fc259498e..c750ab45e 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -105,7 +105,7 @@ def temperature(self) -> Optional[int]: """Current temperature.""" try: return int(self.data[1][6:8], 16) - except ValueError: + except TypeError: return None @property @@ -119,7 +119,7 @@ def fan_speed(self) -> Optional[FanSpeed]: try: speed = int(self.data[1][4:5]) return FanSpeed(speed) - except ValueError: + except TypeError: return None @property @@ -128,7 +128,7 @@ def mode(self) -> Optional[OperationMode]: try: mode = int(self.data[1][3:4]) return OperationMode(mode) - except ValueError: + except TypeError: return None From b5b1e77b0e3dc5bec7fe68663ccb4a47264db121 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 26 Jan 2018 18:11:57 +0100 Subject: [PATCH 4/6] Open loop tests added and bugs fixed. --- miio/airconditioningcompanion.py | 20 +++++----- miio/tests/test_airconditioningcompanion.py | 43 ++++++++++++++++++++- 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index c750ab45e..dbe1abec7 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -48,7 +48,7 @@ class Power(enum.Enum): }, '0100010727': { 'deviceType': 'gree_2', - 'base': '[po][mo][wi][sw][tt]1100190[tt1]205002102000t7t0190[tt1]207002000000[tt4]0', + 'base': '[po][mo][wi][sw][tt]1100190[tt1]205002102000[tt7]0190[tt1]207002000000[tt4]0', 'off': '01011101004000205002112000D04000207002000000A0' }, '0100004795': { @@ -140,17 +140,17 @@ def status(self) -> AirConditioningCompanionStatus: status = self.send("get_model_and_state", []) return AirConditioningCompanionStatus(status) - def learn(self): + def learn(self, slot: int=STORAGE_SLOT_ID): """Learn an infrared command.""" - return self.send("start_ir_learn", [STORAGE_SLOT_ID]) + return self.send("start_ir_learn", [slot]) def learn_result(self): """Read the learned command.""" return self.send("get_ir_learn_result", []) - def learn_stop(self): + def learn_stop(self, slot: int=STORAGE_SLOT_ID): """Stop learning of a infrared command.""" - return self.send("end_ir_learn", [STORAGE_SLOT_ID]) + return self.send("end_ir_learn", [slot]) def send_ir_code(self, command: str): """Play a captured command. @@ -181,16 +181,16 @@ def send_configuration(self, model: str, power: Power, configuration = \ model + DEVICE_COMMAND_TEMPLATES['fallback']['base'] - configuration = configuration.replace('[po]', power.value) - configuration = configuration.replace('[mo]', operation_mode.value) - configuration = configuration.replace('[wi]', fan_speed.value) - configuration = configuration.replace('[sw]', swing_mode.value) + configuration = configuration.replace('[po]', str(power.value)) + configuration = configuration.replace('[mo]', str(operation_mode.value)) + configuration = configuration.replace('[wi]', str(fan_speed.value)) + configuration = configuration.replace('[sw]', str(swing_mode.value)) configuration = configuration.replace( '[tt]', hex(int(target_temperature))[2:]) temperature = (1 + int(target_temperature) - 17) % 16 temperature = hex(temperature)[2:].upper() - configuration = configuration.replace('[[tt1]]', temperature) + configuration = configuration.replace('[tt1]', temperature) temperature = (4 + int(target_temperature) - 17) % 16 temperature = hex(temperature)[2:].upper() diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index c60bd0236..2e8f6e44a 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -1,6 +1,8 @@ +import string from unittest import TestCase from miio import AirConditioningCompanion -from miio.airconditioningcompanion import OperationMode, FanSpeed +from miio.airconditioningcompanion import OperationMode, FanSpeed, Power, \ + SwingMode, STORAGE_SLOT_ID import pytest @@ -9,7 +11,12 @@ def __init__(self, *args, **kwargs): self.state = ['010500978022222102', '010201190280222221', '2'] self.return_values = { - 'get_model_and_state': self._get_state + 'get_model_and_state': self._get_state, + 'start_ir_learn': lambda x: True, + 'end_ir_learn': lambda x: True, + 'get_ir_learn_result': lambda x: True, + 'send_ir_code': lambda x: True, + 'send_cmd': self._send_cmd_input_validation, } self.start_state = self.state.copy() @@ -25,6 +32,9 @@ def _get_state(self, props): """Return the requested data""" return self.state + def _send_cmd_input_validation(self, props): + return all(c in string.hexdigits for c in props[0]) + @pytest.fixture(scope="class") def airconditioningcompanion(request): @@ -65,3 +75,32 @@ def test_status_without_fan_speed(self): self.device._reset_state() self.device.state[1] = None assert self.state().fan_speed is None + + def test_learn(self): + assert self.device.learn(STORAGE_SLOT_ID) is True + assert self.device.learn() is True + + def test_learn_result(self): + assert self.device.learn_result() is True + + def test_learn_stop(self): + assert self.device.learn(STORAGE_SLOT_ID) is True + assert self.device.learn() is True + + def test_send_ir_code(self): + assert self.device.send_ir_code('0000000') is True + + def test_send_command(self): + assert self.device.send_command('0000000') is True + + def test_send_configuration(self): + def send_configuration(): + return self.device.send_configuration( + '0100010727', + Power.On, + OperationMode.Auto, + 22.5, + FanSpeed.Low, + SwingMode.On) + + assert send_configuration() is True From f761f6cfbb1694b76b400edbb305aa10056ee647 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 26 Jan 2018 18:20:02 +0100 Subject: [PATCH 5/6] Additional cases added. --- miio/tests/test_airconditioningcompanion.py | 28 ++++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index 2e8f6e44a..1c20463c0 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -84,8 +84,8 @@ def test_learn_result(self): assert self.device.learn_result() is True def test_learn_stop(self): - assert self.device.learn(STORAGE_SLOT_ID) is True - assert self.device.learn() is True + assert self.device.lern_stop(STORAGE_SLOT_ID) is True + assert self.device.learn_stop() is True def test_send_ir_code(self): assert self.device.send_ir_code('0000000') is True @@ -94,13 +94,33 @@ def test_send_command(self): assert self.device.send_command('0000000') is True def test_send_configuration(self): - def send_configuration(): + def send_configuration_known_aircondition(): + return self.device.send_configuration( + '0100010727', + Power.On, + OperationMode.Auto, + 22.5, + FanSpeed.Low, + SwingMode.On) + + def send_configuration_known_aircondition_turn_off(): return self.device.send_configuration( '0100010727', + Power.Off, + OperationMode.Auto, + 22.5, + FanSpeed.Low, + SwingMode.On) + + def send_configuration_unknown_aircondition(): + return self.device.send_configuration( + '01000fffff', Power.On, OperationMode.Auto, 22.5, FanSpeed.Low, SwingMode.On) - assert send_configuration() is True + assert send_configuration_known_aircondition() is True + assert send_configuration_known_aircondition_turn_off() is True + assert send_configuration_unknown_aircondition() is True From 36abfa5a474e48f3572dbe5b94f73c24d95f1fe3 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Fri, 26 Jan 2018 18:25:11 +0100 Subject: [PATCH 6/6] Typo fixed. --- miio/tests/test_airconditioningcompanion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index 1c20463c0..ce40db84d 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -84,7 +84,7 @@ def test_learn_result(self): assert self.device.learn_result() is True def test_learn_stop(self): - assert self.device.lern_stop(STORAGE_SLOT_ID) is True + assert self.device.learn_stop(STORAGE_SLOT_ID) is True assert self.device.learn_stop() is True def test_send_ir_code(self):