From dc1e015081e122cabddf866399ca96946dc81f1f Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 20:57:50 +0200 Subject: [PATCH 01/18] Add unified cli support to Air Humidifier --- miio/airhumidifier.py | 66 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index d6c015ad1..53ee352fa 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -3,6 +3,9 @@ from collections import defaultdict from typing import Any, Dict, Optional +import click + +from .click_common import command, format_output, EnumType from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -160,10 +163,33 @@ def __repr__(self) -> str: self.button_pressed) return s + def __json__(self): + return self.data + class AirHumidifier(Device): """Implementation of Xiaomi Mi Air Humidifier.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "Mode: {result.mode.value}\n" + "Temperature: {result.temperature} °C\n" + "Humidity: {result.humidity} %\n" + "LED brightness: {result.led_brightness}\n" + "Buzzer: {result.buzzer}\n" + "Child lock: {result.child_lock}\n" + "Target humidity: {result.target_humidity} %\n" + "Trans level: {result.trans_level}\n" + "Speed: {result.speed}\n" + "Depth: {result.depth}\n" + "Dry: {result.dry}\n" + "Use time: {result.use_time}\n" + "Hardware version: {result.hardware_version}\n" + "Button pressed: {result.button_pressed}\n" + ) + ) def status(self) -> AirHumidifierStatus: """Retrieve properties.""" @@ -188,22 +214,44 @@ def status(self) -> AirHumidifierStatus: return AirHumidifierStatus( defaultdict(lambda: None, zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + click.argument("mode", type=EnumType(OperationMode, False)), + default_output=format_output("Setting mode to '{mode.value}'") + ) def set_mode(self, mode: OperationMode): """Set mode.""" return self.send("set_mode", [mode.value]) + @command( + click.argument("brightness", type=EnumType(LedBrightness, False)), + default_output=format_output( + "Setting LED brightness to {brightness}") + ) def set_led_brightness(self, brightness: LedBrightness): """Set led brightness.""" return self.send("set_led_b", [brightness.value]) + @command( + click.argument("buzzer", type=bool), + default_output=format_output( + lambda buzzer: "Turning on buzzer" + if buzzer else "Turning off buzzer" + ) + ) def set_buzzer(self, buzzer: bool): """Set buzzer on/off.""" if buzzer: @@ -211,6 +259,13 @@ def set_buzzer(self, buzzer: bool): else: return self.send("set_buzzer", ["off"]) + @command( + click.argument("lock", type=bool), + default_output=format_output( + lambda lock: "Turning on child lock" + if lock else "Turning off child lock" + ) + ) def set_child_lock(self, lock: bool): """Set child lock on/off.""" if lock: @@ -218,6 +273,10 @@ def set_child_lock(self, lock: bool): else: return self.send("set_child_lock", ["off"]) + @command( + click.argument("humidity", type=int), + default_output=format_output("Setting target humidity to {humidity}") + ) def set_target_humidity(self, humidity: int): """Set the target humidity.""" if humidity not in [30, 40, 50, 60, 70, 80]: @@ -226,6 +285,13 @@ def set_target_humidity(self, humidity: int): return self.send("set_limit_hum", [humidity]) + @command( + click.argument("dry", type=bool), + default_output=format_output( + lambda dry: "Turning on dry mode" + if dry else "Turning off dry mode" + ) + ) def set_dry(self, dry: bool): """Set dry mode on/off.""" if dry: From 01d2182d8cc15aaa0e748dbeadfcfc38b7e2e39b Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:00:05 +0200 Subject: [PATCH 02/18] Add unified cli support to Air Quality Monitor --- miio/airqualitymonitor.py | 51 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/miio/airqualitymonitor.py b/miio/airqualitymonitor.py index 3c3b1d04f..56ceefc1e 100644 --- a/miio/airqualitymonitor.py +++ b/miio/airqualitymonitor.py @@ -1,6 +1,9 @@ import logging from collections import defaultdict +import click + +from .click_common import command, format_output from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -80,10 +83,23 @@ def __repr__(self) -> str: self.display_clock) return s + def __json__(self): + return self.data + class AirQualityMonitor(Device): """Xiaomi PM2.5 Air Quality Monitor.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "USB power: {result.usb_power}\n" + "AQI: {result.aqi}\n" + "Battery: {result.battery}\n" + "Display clock: {result.display_clock}\n" + ) + ) def status(self) -> AirQualityMonitorStatus: """Return device status.""" @@ -107,14 +123,27 @@ def status(self) -> AirQualityMonitorStatus: return AirQualityMonitorStatus( defaultdict(lambda: None, zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + click.argument("display_clock", type=bool), + default_output=format_output( + lambda led: "Turning on display clock" + if led else "Turning off display clock" + ) + ) def set_display_clock(self, display_clock: bool): """Enable/disable displaying a clock instead the AQI.""" if display_clock: @@ -122,6 +151,13 @@ def set_display_clock(self, display_clock: bool): else: self.send("set_time_state", ["off"]) + @command( + click.argument("auto_close", type=bool), + default_output=format_output( + lambda led: "Turning on auto close" + if led else "Turning off auto close" + ) + ) def set_auto_close(self, auto_close: bool): """Purpose unknown.""" if auto_close: @@ -129,6 +165,13 @@ def set_auto_close(self, auto_close: bool): else: self.send("set_auto_close", ["off"]) + @command( + click.argument("night_mode", type=bool), + default_output=format_output( + lambda led: "Turning on night mode" + if led else "Turning off night mode" + ) + ) def set_night_mode(self, night_mode: bool): """Decrease the brightness of the display.""" if night_mode: @@ -136,6 +179,14 @@ def set_night_mode(self, night_mode: bool): else: self.send("set_night_state", ["off"]) + @command( + click.argument("begin_hour", type=int), + click.argument("begin_minute", type=int), + click.argument("end_hour", type=int), + click.argument("end_minute", type=int), + default_output=format_output( + "Setting night time to {begin_hour}:{begin_minute} - {end_hour}:{end_minute}") + ) def set_night_time(self, begin_hour: int, begin_minute: int, end_hour: int, end_minute: int): """Enable night mode daily at bedtime.""" From 239c41217664f5128ca8290e2e57df02d32a4801 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:06:46 +0200 Subject: [PATCH 03/18] Add unified cli support to Ceiling Lamp --- miio/ceil.py | 75 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 69 insertions(+), 6 deletions(-) diff --git a/miio/ceil.py b/miio/ceil.py index 879b1449d..a79ab3752 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -2,6 +2,9 @@ from collections import defaultdict from typing import Any, Dict +import click + +from .click_common import command, format_output from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -63,14 +66,25 @@ def automatic_color_temperature(self) -> bool: return self.data["ac"] == 1 def __repr__(self) -> str: - s = "" % \ - (self.power, self.brightness, - self.color_temperature, self.scene, self.delay_off_countdown, - self.smart_night_light, self.automatic_color_temperature) + s = "" % \ + (self.power, + self.brightness, + self.color_temperature, + self.scene, + self.delay_off_countdown, + self.smart_night_light, + self.automatic_color_temperature) return s + def __json__(self): + return self.data + class Ceil(Device): """Main class representing Xiaomi Philips LED Ceiling Lamp.""" @@ -78,6 +92,16 @@ class Ceil(Device): # TODO: - Auto On/Off Not Supported # - Adjust Scenes with Wall Switch Not Supported + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "USB power: {result.usb_power}\n" + "AQI: {result.aqi}\n" + "Battery: {result.battery}\n" + "Time State: {result.time_state}\n" + ) + ) def status(self) -> CeilStatus: """Retrieve properties.""" properties = ['power', 'bright', 'cct', 'snm', 'dv', 'bl', 'ac', ] @@ -96,14 +120,24 @@ def status(self) -> CeilStatus: return CeilStatus(defaultdict(lambda: None, zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering on"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + click.argument("brightness", type=int), + default_output=format_output("Setting brightness to {level}") + ) def set_brightness(self, level: int): """Set brightness level.""" if level < 1 or level > 100: @@ -111,6 +145,10 @@ def set_brightness(self, level: int): return self.send("set_bright", [level]) + @command( + click.argument("level", type=int), + default_output=format_output("Setting color temperature to {level}") + ) def set_color_temperature(self, level: int): """Set Correlated Color Temperature.""" if level < 1 or level > 100: @@ -118,6 +156,11 @@ def set_color_temperature(self, level: int): return self.send("set_cct", [level]) + @command( + click.argument("brightness", type=int), + click.argument("cct", type=int), + default_output=format_output("Setting brightness to {brightness} and color temperature to {cct}") + ) def set_brightness_and_color_temperature(self, brightness: int, cct: int): """Set brightness level and the correlated color temperature.""" if brightness < 1 or brightness > 100: @@ -128,6 +171,10 @@ def set_brightness_and_color_temperature(self, brightness: int, cct: int): return self.send("set_bricct", [brightness, cct]) + @command( + click.argument("seconds", type=int), + default_output=format_output("Setting delayed turn off to {seconds} seconds") + ) def delay_off(self, seconds: int): """Turn off delay in seconds.""" @@ -137,6 +184,10 @@ def delay_off(self, seconds: int): return self.send("delay_off", [seconds]) + @command( + click.argument("number", type=int), + default_output=format_output("Setting fixed scene to {number}") + ) def set_scene(self, number: int): """Set a fixed scene. 4 fixed scenes are available (1-4)""" if number < 1 or number > 4: @@ -144,18 +195,30 @@ def set_scene(self, number: int): return self.send("apply_fixed_scene", [number]) + @command( + default_output=format_output("Turning on smart night light"), + ) def smart_night_light_on(self): """Smart Night Light On.""" return self.send("enable_bl", [1]) + @command( + default_output=format_output("Turning off smart night light"), + ) def smart_night_light_off(self): """Smart Night Light off.""" return self.send("enable_bl", [0]) + @command( + default_output=format_output("Turning on automatic color temperature"), + ) def automatic_color_temperature_on(self): """Automatic color temperature on.""" return self.send("enable_ac", [1]) + @command( + default_output=format_output("Turning off automatic color temperature"), + ) def automatic_color_temperature_off(self): """Automatic color temperature off.""" return self.send("enable_ac", [0]) From c7ae44308175c9dbe736cf05df6361b5bf21c17c Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:11:30 +0200 Subject: [PATCH 04/18] Add unified cli support to Chuangmi IR controller --- miio/chuangmi_ir.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/miio/chuangmi_ir.py b/miio/chuangmi_ir.py index 01315da03..be879e4ce 100644 --- a/miio/chuangmi_ir.py +++ b/miio/chuangmi_ir.py @@ -1,11 +1,13 @@ import base64 import re +import click from construct import ( Struct, Const, Rebuild, this, len_, Adapter, Computed, Int16ul, Int32ul, Int16ub, Array, BitStruct, BitsInteger, ) +from .click_common import command, format_output from .device import Device, DeviceException @@ -18,6 +20,10 @@ class ChuangmiIr(Device): PRONTO_RE = re.compile(r'^([\da-f]{4}\s?){3,}([\da-f]{4})$', re.IGNORECASE) + @command( + click.argument("key", type=int), + default_output=format_output("Learning command into storage key {key}") + ) def learn(self, key: int=1): """Learn an infrared command. @@ -27,6 +33,10 @@ def learn(self, key: int=1): raise ChuangmiIrException("Invalid storage slot.") return self.send("miIO.ir_learn", {'key': str(key)}) + @command( + click.argument("key", type=int), + default_output=format_output("Reading infrared command from key storage key {key}") + ) def read(self, key: int=1): """Read a learned command. @@ -100,6 +110,10 @@ def pronto_to_raw(cls, pronto: str, repeats: int=1): return signal_code, int(round(pronto_data.frequency)) + @command( + click.argument("command", type=str), + default_output=format_output("Playing the supplied command") + ) def play(self, command: str): """Plays a command in one of the supported formats.""" if ":" not in command: From 70a25215b28d74701a8398ebef8ce58314dbe157 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:21:22 +0200 Subject: [PATCH 05/18] Add unified cli support to Fan --- miio/fan.py | 111 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 9 deletions(-) diff --git a/miio/fan.py b/miio/fan.py index 2b056e502..bc7287742 100644 --- a/miio/fan.py +++ b/miio/fan.py @@ -2,6 +2,9 @@ import logging from typing import Any, Dict, Optional +import click + +from .click_common import command, format_output, EnumType from .device import Device _LOGGER = logging.getLogger(__name__) @@ -116,21 +119,65 @@ def angle(self) -> int: return self.data["angle"] def __str__(self) -> str: - s = " FanStatus: """Retrieve properties.""" properties = ['temp_dec', 'humidity', 'angle', 'speed', @@ -153,56 +200,102 @@ def status(self) -> FanStatus: return FanStatus(dict(zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + click.argument("speed", type=int), + default_output=format_output("Setting natural level to {level}") + ) def set_natural_level(self, level: int): """Set natural level.""" level = max(0, min(level, 100)) return self.send("set_natural_level", [level]) # 0...100 + @command( + click.argument("speed", type=int), + default_output=format_output("Setting speed level to {level}") + ) def set_speed_level(self, level: int): """Set speed level.""" level = max(0, min(level, 100)) return self.send("set_speed_level", [level]) # 0...100 + @command( + click.argument("direction", type=EnumType(MoveDirection, False)), + default_output=format_output( + "Setting move direction to {direction}") + ) def set_direction(self, direction: MoveDirection): """Set move direction.""" return self.send("set_move", [direction.value]) + @command( + click.argument("angle", type=int), + default_output=format_output("Setting angle to {angle}") + ) def fan_set_angle(self, angle: int): """Set angle.""" return self.send("set_angle", [angle]) + @command( + default_output=format_output("Turning on oscillate"), + ) def oscillate_on(self): """Enable oscillate.""" return self.send("set_angle_enable", ["on"]) + @command( + default_output=format_output("Turning off oscillate"), + ) def oscillate_off(self): """Disable oscillate.""" return self.send("set_angle_enable", ["off"]) + @command( + click.argument("brightness", type=EnumType(LedBrightness, False)), + default_output=format_output( + "Setting LED brightness to {brightness}") + ) def set_led_brightness(self, brightness: LedBrightness): """Set led brightness.""" return self.send("set_led_b", [brightness.value]) + @command( + default_output=format_output("Turning on LED"), + ) def led_on(self): """Turn led on.""" return self.send("set_led", ["on"]) + @command( + default_output=format_output("Turning off LED"), + ) def led_off(self): """Turn led off.""" return self.send("set_led", ["off"]) + @command( + default_output=format_output("Turning on buzzer"), + ) def buzzer_on(self): """Enable buzzer.""" return self.send("set_buzzer", ["on"]) + @command( + default_output=format_output("Turning off buzzer"), + ) def buzzer_off(self): """Disable buzzer.""" return self.send("set_buzzer", ["off"]) From 5cde0c8b1f58cc12f4ccad8b853280fc65a21456 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:29:30 +0200 Subject: [PATCH 06/18] Optimize imports --- mirobo/__init__.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mirobo/__init__.py b/mirobo/__init__.py index 0a8227ce4..ccab89525 100644 --- a/mirobo/__init__.py +++ b/mirobo/__init__.py @@ -1,5 +1,4 @@ # flake8: noqa -from miio import * import warnings warnings.simplefilter('always', DeprecationWarning) warnings.warn("Please convert to using 'miio' package, this package will " From 1c49375d3b92889ad989cd3f2dcd993792d23e0d Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:33:35 +0200 Subject: [PATCH 07/18] Add unified cli support to Philips Bulb --- miio/ceil.py | 10 ++++++---- miio/philips_bulb.py | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/miio/ceil.py b/miio/ceil.py index a79ab3752..eff105c68 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -96,10 +96,12 @@ class Ceil(Device): default_output=format_output( "", "Power: {result.power}\n" - "USB power: {result.usb_power}\n" - "AQI: {result.aqi}\n" - "Battery: {result.battery}\n" - "Time State: {result.time_state}\n" + "Brightness: {result.brightness}\n" + "Color temperature: {result.color_temperature}\n" + "Scene: {result.scene}\n" + "Delayed turn off: {result.delay_off_countdown}\n" + "Smart night light: {result.smart_night_light}\n" + "Automatic color temperature: {result.automatic_color_temperature}\n" ) ) def status(self) -> CeilStatus: diff --git a/miio/philips_bulb.py b/miio/philips_bulb.py index c1090bd00..4b08dfbb1 100644 --- a/miio/philips_bulb.py +++ b/miio/philips_bulb.py @@ -2,6 +2,9 @@ from collections import defaultdict from typing import Any, Dict +import click + +from .click_common import command, format_output from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -49,10 +52,23 @@ def __repr__(self) -> str: self.color_temperature, self.scene, self.delay_off_countdown) return s + def __json__(self): + return self.data + class PhilipsBulb(Device): """Main class representing Xiaomi Philips LED Ball Lamp.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "Brightness: {result.brightness}\n" + "Color temperature: {result.color_temperature}\n" + "Scene: {result.scene}\n" + "Delayed turn off: {result.delay_off_countdown}\n" + ) + ) def status(self) -> PhilipsBulbStatus: """Retrieve properties.""" properties = ['power', 'bright', 'cct', 'snm', 'dv', ] @@ -72,14 +88,24 @@ def status(self) -> PhilipsBulbStatus: return PhilipsBulbStatus( defaultdict(lambda: None, zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + click.argument("brightness", type=int), + default_output=format_output("Setting brightness to {level}") + ) def set_brightness(self, level: int): """Set brightness level.""" if level < 1 or level > 100: @@ -87,6 +113,10 @@ def set_brightness(self, level: int): return self.send("set_bright", [level]) + @command( + click.argument("level", type=int), + default_output=format_output("Setting color temperature to {level}") + ) def set_color_temperature(self, level: int): """Set Correlated Color Temperature.""" if level < 1 or level > 100: @@ -94,6 +124,11 @@ def set_color_temperature(self, level: int): return self.send("set_cct", [level]) + @command( + click.argument("brightness", type=int), + click.argument("cct", type=int), + default_output=format_output("Setting brightness to {brightness} and color temperature to {cct}") + ) def set_brightness_and_color_temperature(self, brightness: int, cct: int): """Set brightness level and the correlated color temperature.""" if brightness < 1 or brightness > 100: @@ -104,6 +139,10 @@ def set_brightness_and_color_temperature(self, brightness: int, cct: int): return self.send("set_bricct", [brightness, cct]) + @command( + click.argument("seconds", type=int), + default_output=format_output("Setting delayed turn off to {seconds} seconds") + ) def delay_off(self, seconds: int): """Set delay off seconds.""" @@ -113,6 +152,10 @@ def delay_off(self, seconds: int): return self.send("delay_off", [seconds]) + @command( + click.argument("number", type=int), + default_output=format_output("Setting fixed scene to {number}") + ) def set_scene(self, number: int): """Set scene number.""" if number < 1 or number > 4: From 2f2405800731e49d227590f0b29c57f2507e528c Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:42:41 +0200 Subject: [PATCH 08/18] Add unified cli support to Philips Eyecare Lamp --- miio/ceil.py | 2 +- miio/philips_bulb.py | 2 +- miio/philips_eyecare.py | 88 ++++++++++++++++++++++++++++++++++++++--- 3 files changed, 84 insertions(+), 8 deletions(-) diff --git a/miio/ceil.py b/miio/ceil.py index eff105c68..4e832f89f 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -137,7 +137,7 @@ def off(self): return self.send("set_power", ["off"]) @command( - click.argument("brightness", type=int), + click.argument("level", type=int), default_output=format_output("Setting brightness to {level}") ) def set_brightness(self, level: int): diff --git a/miio/philips_bulb.py b/miio/philips_bulb.py index 4b08dfbb1..c9ec155c6 100644 --- a/miio/philips_bulb.py +++ b/miio/philips_bulb.py @@ -103,7 +103,7 @@ def off(self): return self.send("set_power", ["off"]) @command( - click.argument("brightness", type=int), + click.argument("level", type=int), default_output=format_output("Setting brightness to {level}") ) def set_brightness(self, level: int): diff --git a/miio/philips_eyecare.py b/miio/philips_eyecare.py index e56fb777b..22fd70612 100644 --- a/miio/philips_eyecare.py +++ b/miio/philips_eyecare.py @@ -2,6 +2,9 @@ from collections import defaultdict from typing import Any, Dict +import click + +from .click_common import command, format_output from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -71,20 +74,47 @@ def delay_off_countdown(self) -> int: return self.data["dvalue"] def __repr__(self) -> str: - s = "" % \ - (self.power, self.brightness, - self.reminder, self.ambient, self.ambient_brightness, - self.eyecare, self.scene, self.smart_night_light, + (self.power, + self.brightness, + self.ambient, + self.ambient_brightness, + self.eyecare, + self.scene, + self.reminder, + self.smart_night_light, self.delay_off_countdown) return s + def __json__(self): + return self.data + class PhilipsEyecare(Device): """Main class representing Xiaomi Philips Eyecare Smart Lamp 2.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "Brightness: {result.brightness}\n" + "Ambient light: {result.ambient}\n" + "Ambient light brightness: {result.ambient_brightness}\n" + "Eyecare mode: {result.eyecare}\n" + "Scene: {result.scence}\n" + "Eye fatigue reminder: {result.reminder}\n" + "Smart night light: {result.smart_night_light}\n" + "Delayed turn off: {result.delay_off_countdown}\n" + ) + ) def status(self) -> PhilipsEyecareStatus: """Retrieve properties.""" properties = ['power', 'bright', 'notifystatus', 'ambstatus', @@ -105,22 +135,38 @@ def status(self) -> PhilipsEyecareStatus: return PhilipsEyecareStatus( defaultdict(lambda: None, zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + default_output=format_output("Turning on eyecare mode"), + ) def eyecare_on(self): """Turn the eyecare mode on.""" return self.send("set_eyecare", ["on"]) + @command( + default_output=format_output("Turning off eyecare mode"), + ) def eyecare_off(self): """Turn the eyecare mode off.""" return self.send("set_eyecare", ["off"]) + @command( + click.argument("level", type=int), + default_output=format_output("Setting brightness to {level}") + ) def set_brightness(self, level: int): """Set brightness level of the primary light.""" if level < 1 or level > 100: @@ -128,6 +174,10 @@ def set_brightness(self, level: int): return self.send("set_bright", [level]) + @command( + click.argument("number", type=int), + default_output=format_output("Setting fixed scene to {number}") + ) def set_scene(self, number: int): """Set one of the fixed eyecare user scenes.""" if number < 1 or number > 4: @@ -135,6 +185,10 @@ def set_scene(self, number: int): return self.send("set_user_scene", [number]) + @command( + click.argument("minutes", type=int), + default_output=format_output("Setting delayed turn off to {minutes} minutes") + ) def delay_off(self, minutes: int): """Set delay off minutes.""" @@ -144,30 +198,52 @@ def delay_off(self, minutes: int): return self.send("delay_off", [minutes]) + @command( + default_output=format_output("Turning on smart night light"), + ) def smart_night_light_on(self): """Turn the smart night light mode on.""" return self.send("enable_bl", ["on"]) + @command( + default_output=format_output("Turning off smart night light"), + ) def smart_night_light_off(self): """Turn the smart night light mode off.""" return self.send("enable_bl", ["off"]) + @command( + default_output=format_output("Turning on eye fatigue reminder"), + ) def reminder_on(self): """Enable the eye fatigue reminder / notification.""" return self.send("set_notifyuser", ["on"]) + @command( + default_output=format_output("Turning off eye fatigue reminder"), + ) def reminder_off(self): """Disable the eye fatigue reminder / notification.""" return self.send("set_notifyuser", ["off"]) + @command( + default_output=format_output("Turning on ambient light"), + ) def ambient_on(self): """Turn the ambient light on.""" return self.send("enable_amb", ["on"]) + @command( + default_output=format_output("Turning off ambient light"), + ) def ambient_off(self): """Turn the ambient light off.""" return self.send("enable_amb", ["off"]) + @command( + click.argument("level", type=int), + default_output=format_output("Setting brightness to {level}") + ) def set_ambient_brightness(self, level: int): """Set the brightness of the ambient light.""" if level < 1 or level > 100: From beed73acdc571d5b59b1660c6bc9025e81dc03c9 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:52:46 +0200 Subject: [PATCH 09/18] Add unified cli support to Power Strip --- miio/powerstrip.py | 49 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/miio/powerstrip.py b/miio/powerstrip.py index 7528e3bdc..ab7720d4c 100644 --- a/miio/powerstrip.py +++ b/miio/powerstrip.py @@ -3,6 +3,9 @@ from collections import defaultdict from typing import Dict, Any, Optional +import click + +from .click_common import command, format_output, EnumType from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -122,10 +125,27 @@ def __repr__(self) -> str: self.wifi_led) return s + def __json__(self): + return self.data + class PowerStrip(Device): """Main class representing the smart power strip.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "Temperature: {result.temperature} °C\n" + "Voltage: {result.voltage} V\n" + "Current: {result.current} A\n" + "Load power: {result.load_power} W\n" + "Power factor: {result.power_factor}\n" + "Power price: {result.power_price}\n" + "Leakage current: {result.leakage_current} A\n" + "Mode: {result.mode}\n" + "WiFi LED: {result.wifi_led}\n") + ) def status(self) -> PowerStripStatus: """Retrieve properties.""" properties = ['power', 'temperature', 'current', 'mode', @@ -147,20 +167,38 @@ def status(self) -> PowerStripStatus: return PowerStripStatus( defaultdict(lambda: None, zip(properties, values))) + @command( + default_output = format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output = format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) + @command( + click.argument("mode", type=EnumType(PowerMode, False)), + default_output=format_output( + "Setting mode to {mode}") + ) def set_power_mode(self, mode: PowerMode): """Set the power mode.""" # green, normal return self.send("set_power_mode", [mode.value]) + @command( + click.argument("led", type=bool), + default_output=format_output( + lambda led: "Turning on WiFi LED" + if led else "Turning off WiFi LED" + ) + ) def set_wifi_led(self, led: bool): """Set the wifi led on/off.""" if led: @@ -168,6 +206,10 @@ def set_wifi_led(self, led: bool): else: return self.send("set_wifi_led", ["off"]) + @command( + click.argument("price", type=int), + default_output=format_output("Setting power price to {price}") + ) def set_power_price(self, price: int): """Set the power price.""" if price < 0 or price > 999: @@ -175,6 +217,13 @@ def set_power_price(self, price: int): return self.send("set_power_price", [price]) + @command( + click.argument("power", type=bool), + default_output=format_output( + lambda led: "Turning on real-time power measurement" + if led else "Turning off real-time power measurement" + ) + ) def set_realtime_power(self, power: bool): """Set the realtime power on/off.""" if power: From 5f4974ab169fcb378dec7a94427bada098f4cc7c Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 21:52:54 +0200 Subject: [PATCH 10/18] Add unified cli support to Water Purifier --- miio/waterpurifier.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/miio/waterpurifier.py b/miio/waterpurifier.py index 9d70a28a1..5fb11b825 100644 --- a/miio/waterpurifier.py +++ b/miio/waterpurifier.py @@ -2,6 +2,7 @@ from collections import defaultdict from typing import Any, Dict +from .click_common import command, format_output from .device import Device _LOGGER = logging.getLogger(__name__) @@ -126,10 +127,35 @@ def __repr__(self) -> str: self.uv_filter_state, self.valve) + def __json__(self): + return self.data + class WaterPurifier(Device): """Main class representing the waiter purifier.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "Mode: {result.mode}\n" + "TDS: {result.tds}\n" + "Filter life remaining: {result.filter_life_remaining}\n" + "Filter state: {result.filter_state}\n" + "Filter2 life remaining: {result.filter2_life_remaining}\n" + "Filter2 state: {result.filter2_state}\n" + "Life remaining: {result.life_remaining}\n" + "State: {result.state}\n" + "Level: {result.level}\n" + "Volume: {result.volume}\n" + "Filter: {result.filter}\n" + "Usage: {result.usage}\n" + "Temperature: {result.temperature}\n" + "UV filter life remaining: {result.uv_filter_life_remaining}\n" + "UV filter state: {result.uv_filter_state}\n" + "Valve: {result.valve}\n" + ) + ) def status(self) -> WaterPurifierStatus: """Retrieve properties.""" @@ -154,10 +180,16 @@ def status(self) -> WaterPurifierStatus: return WaterPurifierStatus( defaultdict(lambda: None, zip(properties, values))) + @command( + default_output=format_output("Powering on"), + ) def on(self): """Power on.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering off"), + ) def off(self): """Power off.""" return self.send("set_power", ["off"]) From 9968bd82553e38e40a133bdb2896bbe034a77499 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 22:13:57 +0200 Subject: [PATCH 11/18] Add unified cli support to WiFi Repeater --- miio/wifirepeater.py | 50 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/miio/wifirepeater.py b/miio/wifirepeater.py index c633a85e8..bef6eec8d 100644 --- a/miio/wifirepeater.py +++ b/miio/wifirepeater.py @@ -1,5 +1,8 @@ import logging +import click + +from .click_common import command, format_output from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) @@ -42,6 +45,9 @@ def __repr__(self) -> str: len(self.associated_stations)) return s + def __json__(self): + return self.data + class WifiRepeaterConfiguration: def __init__(self, data): @@ -73,37 +79,77 @@ def __repr__(self) -> str: self.ssid_hidden) return s + def __json__(self): + return self.data + class WifiRepeater(Device): """Device class for Xiaomi Mi WiFi Repeater 2.""" + @command( + default_output=format_output( + "", + "Access policy: {result.access_policy}\n" + "Associated stations: {result.associated_stations}\n" + ) + ) def status(self) -> WifiRepeaterStatus: """Return the associated stations.""" return WifiRepeaterStatus(self.send("miIO.get_repeater_sta_info", [])) + @command( + default_output=format_output( + "", + "SSID: {result.ssid}\n" + "Password: {result.password}\n" + "SSID hidden: {result.ssid_hidden}\n" + ) + ) def configuration(self) -> WifiRepeaterConfiguration: """Return the configuration of the accesspoint.""" return WifiRepeaterConfiguration( self.send("miIO.get_repeater_ap_info", [])) + @command( + click.argument("wifi_roaming", type=bool), + default_output=format_output( + lambda led: "Turning on WiFi roaming" + if led else "Turning off WiFi roaming" + ) + ) def set_wifi_roaming(self, wifi_roaming: bool): """Turn the WiFi roaming on/off.""" return self.send("miIO.switch_wifi_explorer", [{ 'wifi_explorer': int(wifi_roaming) }]) - def set_configuration(self, ssid: str, password: str, hidden: bool = False): + @command( + click.argument("ssid", type=str), + click.argument("password", type=str), + click.argument("ssid_hidden", type=bool), + default_output=format_output("Setting accesspoint configuration") + ) + def set_configuration(self, ssid: str, password: str, ssid_hidden: bool = False): """Update the configuration of the accesspoint.""" return self.send("miIO.switch_wifi_ssid", [{ 'ssid': ssid, 'pwd': password, - 'hidden': int(hidden), + 'hidden': int(ssid_hidden), 'wifi_explorer': 0 }]) + @command( + default_output=format_output( + lambda result: "WiFi roaming is enabled" + if result else "WiFi roaming is disabled" + ) + ) def wifi_roaming(self) -> bool: """Return the roaming setting.""" return self.info().raw['desc']['wifi_explorer'] == 1 + @command( + default_output=format_output("RSSI of the accesspoint: {result}") + ) def rssi_accesspoint(self) -> int: """Received signal strength indicator of the accesspoint.""" return self.info().accesspoint['rssi'] From 17e505e1038f6a8e5c29f5d36e37d140e4208781 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 22:18:03 +0200 Subject: [PATCH 12/18] Make hound happy --- miio/ceil.py | 3 ++- miio/philips_bulb.py | 3 ++- miio/powerstrip.py | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/miio/ceil.py b/miio/ceil.py index 4e832f89f..10053de4d 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -161,7 +161,8 @@ def set_color_temperature(self, level: int): @command( click.argument("brightness", type=int), click.argument("cct", type=int), - default_output=format_output("Setting brightness to {brightness} and color temperature to {cct}") + default_output=format_output( + "Setting brightness to {brightness} and color temperature to {cct}") ) def set_brightness_and_color_temperature(self, brightness: int, cct: int): """Set brightness level and the correlated color temperature.""" diff --git a/miio/philips_bulb.py b/miio/philips_bulb.py index c9ec155c6..fac4a422a 100644 --- a/miio/philips_bulb.py +++ b/miio/philips_bulb.py @@ -127,7 +127,8 @@ def set_color_temperature(self, level: int): @command( click.argument("brightness", type=int), click.argument("cct", type=int), - default_output=format_output("Setting brightness to {brightness} and color temperature to {cct}") + default_output=format_output( + "Setting brightness to {brightness} and color temperature to {cct}") ) def set_brightness_and_color_temperature(self, brightness: int, cct: int): """Set brightness level and the correlated color temperature.""" diff --git a/miio/powerstrip.py b/miio/powerstrip.py index ab7720d4c..d0aef0220 100644 --- a/miio/powerstrip.py +++ b/miio/powerstrip.py @@ -168,14 +168,14 @@ def status(self) -> PowerStripStatus: defaultdict(lambda: None, zip(properties, values))) @command( - default_output = format_output("Powering on"), + default_output=format_output("Powering on"), ) def on(self): """Power on.""" return self.send("set_power", ["on"]) @command( - default_output = format_output("Powering off"), + default_output=format_output("Powering off"), ) def off(self): """Power off.""" From 2474d88b0d365f0ed43a06ecd16a4291b879f00c Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sat, 31 Mar 2018 23:14:11 +0200 Subject: [PATCH 13/18] Don't access Optional enums --- miio/airhumidifier.py | 2 +- miio/airpurifier.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index 53ee352fa..f1e02c650 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -174,7 +174,7 @@ class AirHumidifier(Device): default_output=format_output( "", "Power: {result.power}\n" - "Mode: {result.mode.value}\n" + "Mode: {result.mode}\n" "Temperature: {result.temperature} °C\n" "Humidity: {result.humidity} %\n" "LED brightness: {result.led_brightness}\n" diff --git a/miio/airpurifier.py b/miio/airpurifier.py index 5baad4a95..4001f85b6 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -387,9 +387,9 @@ class AirPurifier(Device): "Sound volume: {result.volume} %\n" "Filter RFID product id: {result.filter_rfid_product_id}\n" "Filter RFID tag: {result.filter_rfid_tag}\n" - "Filter type: {result.filter_type.value}\n" + "Filter type: {result.filter_type}\n" "Learn mode: {result.learn_mode}\n" - "Sleep mode: {result.sleep_mode.value}\n" + "Sleep mode: {result.sleep_mode}\n" "Sleep time: {result.sleep_time}\n" "Sleep mode learn count: {result.sleep_mode_learn_count}\n" "AQI sensor enabled on power off: {result.auto_detect}\n" From 8c310bd320d14e2db89247f1cbf9d076c9a2a5d3 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 1 Apr 2018 09:09:47 +0200 Subject: [PATCH 14/18] Revert "Optimize imports" This reverts commit 91dc4d74af962974aa46dc14dfe8fc6b35449437. --- miio/__init__.py | 28 ++++++++++----------- miio/airconditioningcompanion.py | 3 +-- miio/airhumidifier.py | 10 +++----- miio/airpurifier.py | 8 +++--- miio/airqualitymonitor.py | 3 --- miio/ceil.py | 8 +++--- miio/ceil_cli.py | 9 +++---- miio/chuangmi_ir.py | 4 +-- miio/chuangmi_plug.py | 8 +++--- miio/cli.py | 2 -- miio/device.py | 15 ++++++----- miio/discovery.py | 18 ++++++------- miio/extract_tokens.py | 11 ++++---- miio/philips_eyecare_cli.py | 9 +++---- miio/plug_cli.py | 11 ++++---- miio/protocol.py | 10 +++++--- miio/tests/test_airconditioningcompanion.py | 10 +++----- miio/tests/test_airhumidifier.py | 6 ++--- miio/tests/test_airpurifier.py | 7 ++---- miio/tests/test_airqualitymonitor.py | 4 +-- miio/tests/test_ceil.py | 4 +-- miio/tests/test_chuangmi_ir.py | 10 +++----- miio/tests/test_chuangmi_plug.py | 7 ++---- miio/tests/test_philips_bulb.py | 4 +-- miio/tests/test_philips_eyecare.py | 4 +-- miio/tests/test_powerstrip.py | 4 +-- miio/tests/test_protocol.py | 3 +-- miio/tests/test_vacuum.py | 6 ++--- miio/tests/test_waterpurifier.py | 4 +-- miio/tests/test_wifirepeater.py | 4 +-- miio/tests/test_yeelight.py | 4 +-- miio/updater.py | 2 +- miio/utils.py | 2 +- miio/vacuum.py | 2 +- miio/vacuum_cli.py | 20 +++++++-------- miio/vacuumcontainers.py | 3 +-- miio/yeelight.py | 5 ++-- mirobo/__init__.py | 1 + 38 files changed, 109 insertions(+), 164 deletions(-) diff --git a/miio/__init__.py b/miio/__init__.py index cdbe275f4..e97c9e430 100644 --- a/miio/__init__.py +++ b/miio/__init__.py @@ -1,22 +1,22 @@ # flake8: noqa -from miio.airconditioningcompanion import AirConditioningCompanion -from miio.airhumidifier import AirHumidifier +from miio.protocol import Message, Utils +from miio.vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, + CleaningDetails, CleaningSummary, Timer) +from miio.vacuum import Vacuum, VacuumException +from miio.chuangmi_plug import (Plug, PlugV1, PlugV3, ChuangmiPlug) from miio.airpurifier import AirPurifier -from miio.airqualitymonitor import AirQualityMonitor +from miio.airhumidifier import AirHumidifier +from miio.waterpurifier import WaterPurifier +from miio.powerstrip import PowerStrip from miio.ceil import Ceil -from miio.chuangmi_ir import ChuangmiIr -from miio.chuangmi_plug import (Plug, PlugV1, PlugV3, ChuangmiPlug) -from miio.device import Device, DeviceException -from miio.fan import Fan from miio.philips_bulb import PhilipsBulb from miio.philips_eyecare import PhilipsEyecare -from miio.powerstrip import PowerStrip -from miio.protocol import Message, Utils -from miio.vacuum import Vacuum, VacuumException -from miio.vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, - CleaningDetails, CleaningSummary, Timer, ) -from miio.waterpurifier import WaterPurifier -from miio.wifirepeater import WifiRepeater +from miio.chuangmi_ir import ChuangmiIr +from miio.fan import Fan from miio.wifispeaker import WifiSpeaker +from miio.wifirepeater import WifiRepeater +from miio.airqualitymonitor import AirQualityMonitor +from miio.airconditioningcompanion import AirConditioningCompanion from miio.yeelight import Yeelight +from miio.device import Device, DeviceException from miio.discovery import Discovery diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index b74ebfefd..eee5ac727 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -1,8 +1,7 @@ +from .device import Device import enum from typing import Optional -from .device import Device - class OperationMode(enum.Enum): Heat = 0 diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index f1e02c650..13437b10c 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -1,12 +1,10 @@ -import enum import logging -from collections import defaultdict -from typing import Any, Dict, Optional - +import enum import click - -from .click_common import command, format_output, EnumType +from typing import Any, Dict, Optional +from collections import defaultdict from .device import Device, DeviceException +from .click_common import command, format_output, EnumType _LOGGER = logging.getLogger(__name__) diff --git a/miio/airpurifier.py b/miio/airpurifier.py index 4001f85b6..266202717 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -1,13 +1,11 @@ -import enum import logging +import enum import re -from collections import defaultdict from typing import Any, Dict, Optional - +from collections import defaultdict import click - -from .click_common import command, format_output, EnumType from .device import Device, DeviceException +from .click_common import command, format_output, EnumType _LOGGER = logging.getLogger(__name__) diff --git a/miio/airqualitymonitor.py b/miio/airqualitymonitor.py index 56ceefc1e..74c2fa715 100644 --- a/miio/airqualitymonitor.py +++ b/miio/airqualitymonitor.py @@ -1,4 +1,3 @@ -import logging from collections import defaultdict import click @@ -6,8 +5,6 @@ from .click_common import command, format_output from .device import Device, DeviceException -_LOGGER = logging.getLogger(__name__) - class AirQualityMonitorException(DeviceException): pass diff --git a/miio/ceil.py b/miio/ceil.py index 10053de4d..813cb8a27 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -1,11 +1,9 @@ import logging -from collections import defaultdict -from typing import Any, Dict - import click - -from .click_common import command, format_output +from typing import Any, Dict +from collections import defaultdict from .device import Device, DeviceException +from .click_common import command, format_output _LOGGER = logging.getLogger(__name__) diff --git a/miio/ceil_cli.py b/miio/ceil_cli.py index a53a47aeb..8c0177bec 100644 --- a/miio/ceil_cli.py +++ b/miio/ceil_cli.py @@ -1,12 +1,11 @@ # -*- coding: UTF-8 -*- import logging -import sys - import click - -import miio # noqa: E402 +import sys from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token, ) + validate_token) +import miio # noqa: E402 + _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.Ceil) diff --git a/miio/chuangmi_ir.py b/miio/chuangmi_ir.py index be879e4ce..a8a68ed02 100644 --- a/miio/chuangmi_ir.py +++ b/miio/chuangmi_ir.py @@ -1,14 +1,12 @@ import base64 import re - import click from construct import ( Struct, Const, Rebuild, this, len_, Adapter, Computed, Int16ul, Int32ul, Int16ub, Array, BitStruct, BitsInteger, ) - -from .click_common import command, format_output from .device import Device, DeviceException +from .click_common import command, format_output class ChuangmiIrException(DeviceException): diff --git a/miio/chuangmi_plug.py b/miio/chuangmi_plug.py index a7de46c19..f1ad78229 100644 --- a/miio/chuangmi_plug.py +++ b/miio/chuangmi_plug.py @@ -1,12 +1,10 @@ import logging -from collections import defaultdict -from typing import Dict, Any, Optional - import click - -from .click_common import command, format_output +from typing import Dict, Any, Optional +from collections import defaultdict from .device import Device from .utils import deprecated +from .click_common import command, format_output _LOGGER = logging.getLogger(__name__) diff --git a/miio/cli.py b/miio/cli.py index 3e8cc02a5..04ddb662a 100644 --- a/miio/cli.py +++ b/miio/cli.py @@ -1,8 +1,6 @@ # -*- coding: UTF-8 -*- import logging - import click - from miio.click_common import ( ExceptionHandlerGroup, DeviceGroupMeta, GlobalContextObject, json_output, diff --git a/miio/device.py b/miio/device.py index 8cda0477f..0a0dd0383 100644 --- a/miio/device.py +++ b/miio/device.py @@ -1,19 +1,18 @@ -import binascii import codecs import datetime -import logging import socket -from enum import Enum -from typing import Any, List, Optional # noqa: F401 - -import click +import logging import construct +import binascii +import click +from typing import Any, List, Optional # noqa: F401 +from enum import Enum from .click_common import ( - DeviceGroupMeta, command, format_output, + DeviceGroupMeta, command, format_output ) -from .exceptions import DeviceException, DeviceError from .protocol import Message +from .exceptions import DeviceException, DeviceError _LOGGER = logging.getLogger(__name__) diff --git a/miio/discovery.py b/miio/discovery.py index 15f9c6f85..ebc8262f8 100644 --- a/miio/discovery.py +++ b/miio/discovery.py @@ -1,17 +1,17 @@ -import codecs -import inspect -import ipaddress import logging -from functools import partial -from typing import Union, Callable, Dict, Optional # noqa: F401 - import zeroconf - +import ipaddress +import inspect +import codecs from . import (Device, Vacuum, ChuangmiPlug, PowerStrip, AirPurifier, Ceil, PhilipsBulb, PhilipsEyecare, ChuangmiIr, AirHumidifier, - WaterPurifier, WifiSpeaker, WifiRepeater, Yeelight, ) + WaterPurifier, WifiSpeaker, WifiRepeater, Yeelight) from .chuangmi_plug import (MODEL_CHUANGMI_PLUG_V1, MODEL_CHUANGMI_PLUG_V3, - MODEL_CHUANGMI_PLUG_M1, ) + MODEL_CHUANGMI_PLUG_M1) + +from functools import partial +from typing import Union, Callable, Dict, Optional # noqa: F401 + _LOGGER = logging.getLogger(__name__) diff --git a/miio/extract_tokens.py b/miio/extract_tokens.py index 7e2a1ce0e..661637dae 100644 --- a/miio/extract_tokens.py +++ b/miio/extract_tokens.py @@ -1,14 +1,13 @@ import logging -import sqlite3 +import click import tempfile +import sqlite3 +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.backends import default_backend from pprint import pformat as pf -from typing import Iterator - import attr -import click from android_backup import AndroidBackup -from cryptography.hazmat.backends import default_backend -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from typing import Iterator logging.basicConfig(level=logging.INFO) _LOGGER = logging.getLogger(__name__) diff --git a/miio/philips_eyecare_cli.py b/miio/philips_eyecare_cli.py index e985f4b06..0dbd988e1 100644 --- a/miio/philips_eyecare_cli.py +++ b/miio/philips_eyecare_cli.py @@ -1,12 +1,11 @@ # -*- coding: UTF-8 -*- import logging -import sys - import click - -import miio # noqa: E402 +import sys from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token, ) + validate_token) +import miio # noqa: E402 + _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.PhilipsEyecare) diff --git a/miio/plug_cli.py b/miio/plug_cli.py index 12a1129ad..2564a71d8 100644 --- a/miio/plug_cli.py +++ b/miio/plug_cli.py @@ -1,14 +1,13 @@ # -*- coding: UTF-8 -*- -import ast import logging +import click +import ast import sys from typing import Any # noqa: F401 - -import click - -import miio # noqa: E402 from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token, ) + validate_token) +import miio # noqa: E402 + _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.Plug) diff --git a/miio/protocol.py b/miio/protocol.py index db0ddfb91..09f9ad773 100644 --- a/miio/protocol.py +++ b/miio/protocol.py @@ -10,20 +10,22 @@ An usage example can be seen in the source of :func:`miio.Device.send`. """ -import calendar import datetime import hashlib import json import logging +import calendar from typing import Any, Dict, Tuple +from pprint import pprint as pp # noqa: F401 -import construct from construct import (Struct, Bytes, Const, Int16ub, Int32ub, GreedyBytes, Adapter, Checksum, RawCopy, Rebuild, IfThenElse, - Default, Pointer, Hex, ) + Default, Pointer, Hex, Probe) +import construct + +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import padding -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes _LOGGER = logging.getLogger(__name__) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index 078aee2f0..c9b2cdb65 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -1,13 +1,9 @@ import string from unittest import TestCase - -import pytest - from miio import AirConditioningCompanion -from miio.airconditioningcompanion import (OperationMode, FanSpeed, Power, - SwingMode, Led, - AirConditioningCompanionStatus, - STORAGE_SLOT_ID, ) +from miio.airconditioningcompanion import (OperationMode, FanSpeed, Power, SwingMode, Led, + AirConditioningCompanionStatus, STORAGE_SLOT_ID, ) +import pytest STATE_ON = ['on'] STATE_OFF = ['off'] diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 321c79eee..5e74ff369 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -1,11 +1,9 @@ from unittest import TestCase - -import pytest - from miio import AirHumidifier from miio.airhumidifier import (OperationMode, LedBrightness, - AirHumidifierStatus, AirHumidifierException, ) + AirHumidifierStatus, AirHumidifierException) from .dummies import DummyDevice +import pytest class DummyAirHumidifier(DummyDevice, AirHumidifier): diff --git a/miio/tests/test_airpurifier.py b/miio/tests/test_airpurifier.py index 82d594b62..c3d04e7d2 100644 --- a/miio/tests/test_airpurifier.py +++ b/miio/tests/test_airpurifier.py @@ -1,12 +1,9 @@ from unittest import TestCase - -import pytest - from miio import AirPurifier from miio.airpurifier import (OperationMode, LedBrightness, FilterType, - SleepMode, AirPurifierStatus, - AirPurifierException, ) + SleepMode, AirPurifierStatus, AirPurifierException) from .dummies import DummyDevice +import pytest class DummyAirPurifier(DummyDevice, AirPurifier): diff --git a/miio/tests/test_airqualitymonitor.py b/miio/tests/test_airqualitymonitor.py index 11fe312e2..855ff8731 100644 --- a/miio/tests/test_airqualitymonitor.py +++ b/miio/tests/test_airqualitymonitor.py @@ -1,10 +1,8 @@ from unittest import TestCase - -import pytest - from miio import AirQualityMonitor from miio.airqualitymonitor import AirQualityMonitorStatus from .dummies import DummyDevice +import pytest class DummyAirQualityMonitor(DummyDevice, AirQualityMonitor): diff --git a/miio/tests/test_ceil.py b/miio/tests/test_ceil.py index 5cc7eea0b..d8f6de894 100644 --- a/miio/tests/test_ceil.py +++ b/miio/tests/test_ceil.py @@ -1,10 +1,8 @@ from unittest import TestCase - -import pytest - from miio import Ceil from miio.ceil import CeilStatus, CeilException from .dummies import DummyDevice +import pytest class DummyCeil(DummyDevice, Ceil): diff --git a/miio/tests/test_chuangmi_ir.py b/miio/tests/test_chuangmi_ir.py index 2acb96532..6b6105685 100644 --- a/miio/tests/test_chuangmi_ir.py +++ b/miio/tests/test_chuangmi_ir.py @@ -1,13 +1,11 @@ -import base64 -import json -import os from unittest import TestCase - -import pytest - from miio import ChuangmiIr from miio.chuangmi_ir import ChuangmiIrException from .dummies import DummyDevice +import pytest +import base64 +import json +import os with open(os.path.join( os.path.dirname(__file__), 'test_chuangmi_ir.json')) as inp: diff --git a/miio/tests/test_chuangmi_plug.py b/miio/tests/test_chuangmi_plug.py index dd922ffc0..b042b457e 100644 --- a/miio/tests/test_chuangmi_plug.py +++ b/miio/tests/test_chuangmi_plug.py @@ -1,12 +1,9 @@ from unittest import TestCase - -import pytest - from miio import ChuangmiPlug from miio.chuangmi_plug import (ChuangmiPlugStatus, MODEL_CHUANGMI_PLUG_V1, - MODEL_CHUANGMI_PLUG_V3, - MODEL_CHUANGMI_PLUG_M1, ) + MODEL_CHUANGMI_PLUG_V3, MODEL_CHUANGMI_PLUG_M1) from .dummies import DummyDevice +import pytest class DummyChuangmiPlugV1(DummyDevice, ChuangmiPlug): diff --git a/miio/tests/test_philips_bulb.py b/miio/tests/test_philips_bulb.py index 26f839051..6d6dc5adf 100644 --- a/miio/tests/test_philips_bulb.py +++ b/miio/tests/test_philips_bulb.py @@ -1,10 +1,8 @@ from unittest import TestCase - -import pytest - from miio import PhilipsBulb from miio.philips_bulb import PhilipsBulbStatus, PhilipsBulbException from .dummies import DummyDevice +import pytest class DummyPhilipsBulb(DummyDevice, PhilipsBulb): diff --git a/miio/tests/test_philips_eyecare.py b/miio/tests/test_philips_eyecare.py index 0ad9c41d8..b986e15c9 100644 --- a/miio/tests/test_philips_eyecare.py +++ b/miio/tests/test_philips_eyecare.py @@ -1,10 +1,8 @@ from unittest import TestCase - -import pytest - from miio import PhilipsEyecare from miio.philips_eyecare import PhilipsEyecareStatus, PhilipsEyecareException from .dummies import DummyDevice +import pytest class DummyPhilipsEyecare(DummyDevice, PhilipsEyecare): diff --git a/miio/tests/test_powerstrip.py b/miio/tests/test_powerstrip.py index faabe5112..03b61b4f1 100644 --- a/miio/tests/test_powerstrip.py +++ b/miio/tests/test_powerstrip.py @@ -1,10 +1,8 @@ from unittest import TestCase - -import pytest - from miio import PowerStrip from miio.powerstrip import PowerMode, PowerStripStatus, PowerStripException from .dummies import DummyDevice +import pytest class DummyPowerStrip(DummyDevice, PowerStrip): diff --git a/miio/tests/test_protocol.py b/miio/tests/test_protocol.py index 87c3e2af1..fcebcf0f2 100644 --- a/miio/tests/test_protocol.py +++ b/miio/tests/test_protocol.py @@ -1,8 +1,7 @@ -import binascii from unittest import TestCase - from .. import Utils from ..protocol import Message +import binascii class TestProtocol(TestCase): diff --git a/miio/tests/test_vacuum.py b/miio/tests/test_vacuum.py index 496e77287..e0a7c2669 100644 --- a/miio/tests/test_vacuum.py +++ b/miio/tests/test_vacuum.py @@ -1,10 +1,8 @@ -import datetime from unittest import TestCase - import pytest - -from miio import Vacuum, VacuumStatus from .dummies import DummyDevice +import datetime +from miio import Vacuum, VacuumStatus, VacuumException class DummyVacuum(DummyDevice, Vacuum): diff --git a/miio/tests/test_waterpurifier.py b/miio/tests/test_waterpurifier.py index ff5c38741..3467859a5 100644 --- a/miio/tests/test_waterpurifier.py +++ b/miio/tests/test_waterpurifier.py @@ -1,10 +1,8 @@ from unittest import TestCase - -import pytest - from miio import WaterPurifier from miio.waterpurifier import WaterPurifierStatus from .dummies import DummyDevice +import pytest class DummyWaterPurifier(DummyDevice, WaterPurifier): diff --git a/miio/tests/test_wifirepeater.py b/miio/tests/test_wifirepeater.py index fd2cd152c..2ec42b907 100644 --- a/miio/tests/test_wifirepeater.py +++ b/miio/tests/test_wifirepeater.py @@ -1,9 +1,7 @@ from unittest import TestCase - -import pytest - from miio import WifiRepeater from miio.wifirepeater import WifiRepeaterConfiguration, WifiRepeaterStatus +import pytest class DummyWifiRepeater(WifiRepeater): diff --git a/miio/tests/test_yeelight.py b/miio/tests/test_yeelight.py index 922bc66b4..2af70f362 100644 --- a/miio/tests/test_yeelight.py +++ b/miio/tests/test_yeelight.py @@ -1,9 +1,7 @@ from unittest import TestCase - -import pytest - from miio import Yeelight from miio.yeelight import YeelightMode, YeelightStatus, YeelightException +import pytest from .dummies import DummyDevice diff --git a/miio/updater.py b/miio/updater.py index a22988d04..649c32e03 100644 --- a/miio/updater.py +++ b/miio/updater.py @@ -1,7 +1,7 @@ +from http.server import HTTPServer, BaseHTTPRequestHandler import hashlib import logging import netifaces -from http.server import HTTPServer, BaseHTTPRequestHandler from os.path import basename _LOGGER = logging.getLogger(__name__) diff --git a/miio/utils.py b/miio/utils.py index b526fdbcf..85d3cc5be 100644 --- a/miio/utils.py +++ b/miio/utils.py @@ -1,5 +1,5 @@ -import functools import inspect +import functools import warnings from datetime import timedelta, datetime diff --git a/miio/vacuum.py b/miio/vacuum.py index 3012b4470..5310a839b 100644 --- a/miio/vacuum.py +++ b/miio/vacuum.py @@ -13,7 +13,7 @@ from appdirs import user_cache_dir from .click_common import ( - DeviceGroup, command, GlobalContextObject, + DeviceGroup, command, GlobalContextObject ) from .device import Device, DeviceException from .vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, diff --git a/miio/vacuum_cli.py b/miio/vacuum_cli.py index 5cb7c9a3d..66adad83b 100644 --- a/miio/vacuum_cli.py +++ b/miio/vacuum_cli.py @@ -1,24 +1,22 @@ # -*- coding: UTF-8 -*- +import logging +import click +import pretty_cron import ast +import sys import json -import logging +import time import pathlib -import sys import threading -import time +from tqdm import tqdm +from appdirs import user_cache_dir from pprint import pformat as pf from typing import Any # noqa: F401 - -import click -import pretty_cron -from appdirs import user_cache_dir -from tqdm import tqdm - -import miio # noqa: E402 from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token, ) + validate_token) from .device import UpdateState from .updater import OneShotServer +import miio # noqa: E402 _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.Device, ensure=True) diff --git a/miio/vacuumcontainers.py b/miio/vacuumcontainers.py index 5815d99f0..7887c1b62 100644 --- a/miio/vacuumcontainers.py +++ b/miio/vacuumcontainers.py @@ -1,8 +1,7 @@ # -*- coding: UTF-8 -*# from datetime import datetime, timedelta, time -from enum import IntEnum from typing import Any, Dict, List - +from enum import IntEnum from .utils import deprecated, pretty_time, pretty_seconds diff --git a/miio/yeelight.py b/miio/yeelight.py index d5c5eaa45..ed3315a3c 100644 --- a/miio/yeelight.py +++ b/miio/yeelight.py @@ -1,7 +1,6 @@ -import warnings -from enum import IntEnum from typing import Tuple, Optional - +from enum import IntEnum +import warnings from .device import Device, DeviceException diff --git a/mirobo/__init__.py b/mirobo/__init__.py index ccab89525..0a8227ce4 100644 --- a/mirobo/__init__.py +++ b/mirobo/__init__.py @@ -1,4 +1,5 @@ # flake8: noqa +from miio import * import warnings warnings.simplefilter('always', DeprecationWarning) warnings.warn("Please convert to using 'miio' package, this package will " From 9ab36b22087d68b2a9e0146ab4727eecd282ca89 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 1 Apr 2018 09:18:17 +0200 Subject: [PATCH 15/18] Use optimized imports --- miio/__init__.py | 29 +++++++++++---------- miio/airconditioningcompanion.py | 3 ++- miio/airhumidifier.py | 10 ++++--- miio/airpurifier.py | 8 +++--- miio/ceil.py | 8 +++--- miio/ceil_cli.py | 9 ++++--- miio/chuangmi_ir.py | 4 ++- miio/chuangmi_plug.py | 8 +++--- miio/cli.py | 2 ++ miio/device.py | 15 ++++++----- miio/discovery.py | 18 ++++++------- miio/extract_tokens.py | 11 ++++---- miio/philips_eyecare_cli.py | 9 ++++--- miio/plug_cli.py | 11 ++++---- miio/protocol.py | 10 +++---- miio/tests/test_airconditioningcompanion.py | 10 ++++--- miio/tests/test_airhumidifier.py | 6 +++-- miio/tests/test_airpurifier.py | 7 +++-- miio/tests/test_airqualitymonitor.py | 4 ++- miio/tests/test_ceil.py | 4 ++- miio/tests/test_chuangmi_ir.py | 10 ++++--- miio/tests/test_chuangmi_plug.py | 7 +++-- miio/tests/test_philips_bulb.py | 4 ++- miio/tests/test_philips_eyecare.py | 4 ++- miio/tests/test_powerstrip.py | 4 ++- miio/tests/test_protocol.py | 3 ++- miio/tests/test_vacuum.py | 6 +++-- miio/tests/test_waterpurifier.py | 4 ++- miio/tests/test_wifirepeater.py | 4 ++- miio/tests/test_yeelight.py | 4 ++- miio/updater.py | 2 +- miio/utils.py | 2 +- miio/vacuum.py | 2 +- miio/vacuum_cli.py | 20 +++++++------- miio/vacuumcontainers.py | 3 ++- miio/yeelight.py | 5 ++-- 36 files changed, 162 insertions(+), 108 deletions(-) diff --git a/miio/__init__.py b/miio/__init__.py index e97c9e430..4730d503d 100644 --- a/miio/__init__.py +++ b/miio/__init__.py @@ -1,22 +1,23 @@ # flake8: noqa -from miio.protocol import Message, Utils -from miio.vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, - CleaningDetails, CleaningSummary, Timer) -from miio.vacuum import Vacuum, VacuumException -from miio.chuangmi_plug import (Plug, PlugV1, PlugV3, ChuangmiPlug) -from miio.airpurifier import AirPurifier +from miio.airconditioningcompanion import AirConditioningCompanion from miio.airhumidifier import AirHumidifier -from miio.waterpurifier import WaterPurifier -from miio.powerstrip import PowerStrip +from miio.airpurifier import AirPurifier +from miio.airqualitymonitor import AirQualityMonitor from miio.ceil import Ceil -from miio.philips_bulb import PhilipsBulb -from miio.philips_eyecare import PhilipsEyecare from miio.chuangmi_ir import ChuangmiIr +from miio.chuangmi_plug import (Plug, PlugV1, PlugV3, ChuangmiPlug) +from miio.device import Device, DeviceException from miio.fan import Fan -from miio.wifispeaker import WifiSpeaker +from miio.philips_bulb import PhilipsBulb +from miio.philips_eyecare import PhilipsEyecare +from miio.powerstrip import PowerStrip +from miio.protocol import Message, Utils +from miio.vacuum import Vacuum, VacuumException +from miio.vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, + CleaningDetails, CleaningSummary, Timer, ) +from miio.waterpurifier import WaterPurifier from miio.wifirepeater import WifiRepeater -from miio.airqualitymonitor import AirQualityMonitor -from miio.airconditioningcompanion import AirConditioningCompanion +from miio.wifispeaker import WifiSpeaker from miio.yeelight import Yeelight -from miio.device import Device, DeviceException + from miio.discovery import Discovery diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index eee5ac727..b74ebfefd 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -1,7 +1,8 @@ -from .device import Device import enum from typing import Optional +from .device import Device + class OperationMode(enum.Enum): Heat = 0 diff --git a/miio/airhumidifier.py b/miio/airhumidifier.py index 13437b10c..f1e02c650 100644 --- a/miio/airhumidifier.py +++ b/miio/airhumidifier.py @@ -1,10 +1,12 @@ -import logging import enum -import click -from typing import Any, Dict, Optional +import logging from collections import defaultdict -from .device import Device, DeviceException +from typing import Any, Dict, Optional + +import click + from .click_common import command, format_output, EnumType +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) diff --git a/miio/airpurifier.py b/miio/airpurifier.py index 266202717..4001f85b6 100644 --- a/miio/airpurifier.py +++ b/miio/airpurifier.py @@ -1,11 +1,13 @@ -import logging import enum +import logging import re -from typing import Any, Dict, Optional from collections import defaultdict +from typing import Any, Dict, Optional + import click -from .device import Device, DeviceException + from .click_common import command, format_output, EnumType +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) diff --git a/miio/ceil.py b/miio/ceil.py index 813cb8a27..10053de4d 100644 --- a/miio/ceil.py +++ b/miio/ceil.py @@ -1,9 +1,11 @@ import logging -import click -from typing import Any, Dict from collections import defaultdict -from .device import Device, DeviceException +from typing import Any, Dict + +import click + from .click_common import command, format_output +from .device import Device, DeviceException _LOGGER = logging.getLogger(__name__) diff --git a/miio/ceil_cli.py b/miio/ceil_cli.py index 8c0177bec..a53a47aeb 100644 --- a/miio/ceil_cli.py +++ b/miio/ceil_cli.py @@ -1,11 +1,12 @@ # -*- coding: UTF-8 -*- import logging -import click import sys -from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token) -import miio # noqa: E402 +import click + +import miio # noqa: E402 +from miio.click_common import (ExceptionHandlerGroup, validate_ip, + validate_token, ) _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.Ceil) diff --git a/miio/chuangmi_ir.py b/miio/chuangmi_ir.py index a8a68ed02..be879e4ce 100644 --- a/miio/chuangmi_ir.py +++ b/miio/chuangmi_ir.py @@ -1,12 +1,14 @@ import base64 import re + import click from construct import ( Struct, Const, Rebuild, this, len_, Adapter, Computed, Int16ul, Int32ul, Int16ub, Array, BitStruct, BitsInteger, ) -from .device import Device, DeviceException + from .click_common import command, format_output +from .device import Device, DeviceException class ChuangmiIrException(DeviceException): diff --git a/miio/chuangmi_plug.py b/miio/chuangmi_plug.py index f1ad78229..a7de46c19 100644 --- a/miio/chuangmi_plug.py +++ b/miio/chuangmi_plug.py @@ -1,10 +1,12 @@ import logging -import click -from typing import Dict, Any, Optional from collections import defaultdict +from typing import Dict, Any, Optional + +import click + +from .click_common import command, format_output from .device import Device from .utils import deprecated -from .click_common import command, format_output _LOGGER = logging.getLogger(__name__) diff --git a/miio/cli.py b/miio/cli.py index 04ddb662a..3e8cc02a5 100644 --- a/miio/cli.py +++ b/miio/cli.py @@ -1,6 +1,8 @@ # -*- coding: UTF-8 -*- import logging + import click + from miio.click_common import ( ExceptionHandlerGroup, DeviceGroupMeta, GlobalContextObject, json_output, diff --git a/miio/device.py b/miio/device.py index 0a0dd0383..8cda0477f 100644 --- a/miio/device.py +++ b/miio/device.py @@ -1,18 +1,19 @@ +import binascii import codecs import datetime -import socket import logging -import construct -import binascii -import click -from typing import Any, List, Optional # noqa: F401 +import socket from enum import Enum +from typing import Any, List, Optional # noqa: F401 + +import click +import construct from .click_common import ( - DeviceGroupMeta, command, format_output + DeviceGroupMeta, command, format_output, ) -from .protocol import Message from .exceptions import DeviceException, DeviceError +from .protocol import Message _LOGGER = logging.getLogger(__name__) diff --git a/miio/discovery.py b/miio/discovery.py index ebc8262f8..15f9c6f85 100644 --- a/miio/discovery.py +++ b/miio/discovery.py @@ -1,17 +1,17 @@ +import codecs +import inspect +import ipaddress import logging +from functools import partial +from typing import Union, Callable, Dict, Optional # noqa: F401 + import zeroconf -import ipaddress -import inspect -import codecs + from . import (Device, Vacuum, ChuangmiPlug, PowerStrip, AirPurifier, Ceil, PhilipsBulb, PhilipsEyecare, ChuangmiIr, AirHumidifier, - WaterPurifier, WifiSpeaker, WifiRepeater, Yeelight) + WaterPurifier, WifiSpeaker, WifiRepeater, Yeelight, ) from .chuangmi_plug import (MODEL_CHUANGMI_PLUG_V1, MODEL_CHUANGMI_PLUG_V3, - MODEL_CHUANGMI_PLUG_M1) - -from functools import partial -from typing import Union, Callable, Dict, Optional # noqa: F401 - + MODEL_CHUANGMI_PLUG_M1, ) _LOGGER = logging.getLogger(__name__) diff --git a/miio/extract_tokens.py b/miio/extract_tokens.py index 661637dae..7e2a1ce0e 100644 --- a/miio/extract_tokens.py +++ b/miio/extract_tokens.py @@ -1,13 +1,14 @@ import logging -import click -import tempfile import sqlite3 -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes -from cryptography.hazmat.backends import default_backend +import tempfile from pprint import pformat as pf +from typing import Iterator + import attr +import click from android_backup import AndroidBackup -from typing import Iterator +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes logging.basicConfig(level=logging.INFO) _LOGGER = logging.getLogger(__name__) diff --git a/miio/philips_eyecare_cli.py b/miio/philips_eyecare_cli.py index 0dbd988e1..e985f4b06 100644 --- a/miio/philips_eyecare_cli.py +++ b/miio/philips_eyecare_cli.py @@ -1,11 +1,12 @@ # -*- coding: UTF-8 -*- import logging -import click import sys -from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token) -import miio # noqa: E402 +import click + +import miio # noqa: E402 +from miio.click_common import (ExceptionHandlerGroup, validate_ip, + validate_token, ) _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.PhilipsEyecare) diff --git a/miio/plug_cli.py b/miio/plug_cli.py index 2564a71d8..12a1129ad 100644 --- a/miio/plug_cli.py +++ b/miio/plug_cli.py @@ -1,13 +1,14 @@ # -*- coding: UTF-8 -*- -import logging -import click import ast +import logging import sys from typing import Any # noqa: F401 -from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token) -import miio # noqa: E402 +import click + +import miio # noqa: E402 +from miio.click_common import (ExceptionHandlerGroup, validate_ip, + validate_token, ) _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.Plug) diff --git a/miio/protocol.py b/miio/protocol.py index 09f9ad773..db0ddfb91 100644 --- a/miio/protocol.py +++ b/miio/protocol.py @@ -10,22 +10,20 @@ An usage example can be seen in the source of :func:`miio.Device.send`. """ +import calendar import datetime import hashlib import json import logging -import calendar from typing import Any, Dict, Tuple -from pprint import pprint as pp # noqa: F401 +import construct from construct import (Struct, Bytes, Const, Int16ub, Int32ub, GreedyBytes, Adapter, Checksum, RawCopy, Rebuild, IfThenElse, - Default, Pointer, Hex, Probe) -import construct - -from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes + Default, Pointer, Hex, ) from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import padding +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes _LOGGER = logging.getLogger(__name__) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index c9b2cdb65..078aee2f0 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -1,10 +1,14 @@ import string from unittest import TestCase -from miio import AirConditioningCompanion -from miio.airconditioningcompanion import (OperationMode, FanSpeed, Power, SwingMode, Led, - AirConditioningCompanionStatus, STORAGE_SLOT_ID, ) + import pytest +from miio import AirConditioningCompanion +from miio.airconditioningcompanion import (OperationMode, FanSpeed, Power, + SwingMode, Led, + AirConditioningCompanionStatus, + STORAGE_SLOT_ID, ) + STATE_ON = ['on'] STATE_OFF = ['off'] diff --git a/miio/tests/test_airhumidifier.py b/miio/tests/test_airhumidifier.py index 5e74ff369..321c79eee 100644 --- a/miio/tests/test_airhumidifier.py +++ b/miio/tests/test_airhumidifier.py @@ -1,9 +1,11 @@ from unittest import TestCase + +import pytest + from miio import AirHumidifier from miio.airhumidifier import (OperationMode, LedBrightness, - AirHumidifierStatus, AirHumidifierException) + AirHumidifierStatus, AirHumidifierException, ) from .dummies import DummyDevice -import pytest class DummyAirHumidifier(DummyDevice, AirHumidifier): diff --git a/miio/tests/test_airpurifier.py b/miio/tests/test_airpurifier.py index c3d04e7d2..82d594b62 100644 --- a/miio/tests/test_airpurifier.py +++ b/miio/tests/test_airpurifier.py @@ -1,9 +1,12 @@ from unittest import TestCase + +import pytest + from miio import AirPurifier from miio.airpurifier import (OperationMode, LedBrightness, FilterType, - SleepMode, AirPurifierStatus, AirPurifierException) + SleepMode, AirPurifierStatus, + AirPurifierException, ) from .dummies import DummyDevice -import pytest class DummyAirPurifier(DummyDevice, AirPurifier): diff --git a/miio/tests/test_airqualitymonitor.py b/miio/tests/test_airqualitymonitor.py index 855ff8731..11fe312e2 100644 --- a/miio/tests/test_airqualitymonitor.py +++ b/miio/tests/test_airqualitymonitor.py @@ -1,8 +1,10 @@ from unittest import TestCase + +import pytest + from miio import AirQualityMonitor from miio.airqualitymonitor import AirQualityMonitorStatus from .dummies import DummyDevice -import pytest class DummyAirQualityMonitor(DummyDevice, AirQualityMonitor): diff --git a/miio/tests/test_ceil.py b/miio/tests/test_ceil.py index d8f6de894..5cc7eea0b 100644 --- a/miio/tests/test_ceil.py +++ b/miio/tests/test_ceil.py @@ -1,8 +1,10 @@ from unittest import TestCase + +import pytest + from miio import Ceil from miio.ceil import CeilStatus, CeilException from .dummies import DummyDevice -import pytest class DummyCeil(DummyDevice, Ceil): diff --git a/miio/tests/test_chuangmi_ir.py b/miio/tests/test_chuangmi_ir.py index 6b6105685..2acb96532 100644 --- a/miio/tests/test_chuangmi_ir.py +++ b/miio/tests/test_chuangmi_ir.py @@ -1,11 +1,13 @@ +import base64 +import json +import os from unittest import TestCase + +import pytest + from miio import ChuangmiIr from miio.chuangmi_ir import ChuangmiIrException from .dummies import DummyDevice -import pytest -import base64 -import json -import os with open(os.path.join( os.path.dirname(__file__), 'test_chuangmi_ir.json')) as inp: diff --git a/miio/tests/test_chuangmi_plug.py b/miio/tests/test_chuangmi_plug.py index b042b457e..dd922ffc0 100644 --- a/miio/tests/test_chuangmi_plug.py +++ b/miio/tests/test_chuangmi_plug.py @@ -1,9 +1,12 @@ from unittest import TestCase + +import pytest + from miio import ChuangmiPlug from miio.chuangmi_plug import (ChuangmiPlugStatus, MODEL_CHUANGMI_PLUG_V1, - MODEL_CHUANGMI_PLUG_V3, MODEL_CHUANGMI_PLUG_M1) + MODEL_CHUANGMI_PLUG_V3, + MODEL_CHUANGMI_PLUG_M1, ) from .dummies import DummyDevice -import pytest class DummyChuangmiPlugV1(DummyDevice, ChuangmiPlug): diff --git a/miio/tests/test_philips_bulb.py b/miio/tests/test_philips_bulb.py index 6d6dc5adf..26f839051 100644 --- a/miio/tests/test_philips_bulb.py +++ b/miio/tests/test_philips_bulb.py @@ -1,8 +1,10 @@ from unittest import TestCase + +import pytest + from miio import PhilipsBulb from miio.philips_bulb import PhilipsBulbStatus, PhilipsBulbException from .dummies import DummyDevice -import pytest class DummyPhilipsBulb(DummyDevice, PhilipsBulb): diff --git a/miio/tests/test_philips_eyecare.py b/miio/tests/test_philips_eyecare.py index b986e15c9..0ad9c41d8 100644 --- a/miio/tests/test_philips_eyecare.py +++ b/miio/tests/test_philips_eyecare.py @@ -1,8 +1,10 @@ from unittest import TestCase + +import pytest + from miio import PhilipsEyecare from miio.philips_eyecare import PhilipsEyecareStatus, PhilipsEyecareException from .dummies import DummyDevice -import pytest class DummyPhilipsEyecare(DummyDevice, PhilipsEyecare): diff --git a/miio/tests/test_powerstrip.py b/miio/tests/test_powerstrip.py index 03b61b4f1..faabe5112 100644 --- a/miio/tests/test_powerstrip.py +++ b/miio/tests/test_powerstrip.py @@ -1,8 +1,10 @@ from unittest import TestCase + +import pytest + from miio import PowerStrip from miio.powerstrip import PowerMode, PowerStripStatus, PowerStripException from .dummies import DummyDevice -import pytest class DummyPowerStrip(DummyDevice, PowerStrip): diff --git a/miio/tests/test_protocol.py b/miio/tests/test_protocol.py index fcebcf0f2..87c3e2af1 100644 --- a/miio/tests/test_protocol.py +++ b/miio/tests/test_protocol.py @@ -1,7 +1,8 @@ +import binascii from unittest import TestCase + from .. import Utils from ..protocol import Message -import binascii class TestProtocol(TestCase): diff --git a/miio/tests/test_vacuum.py b/miio/tests/test_vacuum.py index e0a7c2669..496e77287 100644 --- a/miio/tests/test_vacuum.py +++ b/miio/tests/test_vacuum.py @@ -1,8 +1,10 @@ +import datetime from unittest import TestCase + import pytest + +from miio import Vacuum, VacuumStatus from .dummies import DummyDevice -import datetime -from miio import Vacuum, VacuumStatus, VacuumException class DummyVacuum(DummyDevice, Vacuum): diff --git a/miio/tests/test_waterpurifier.py b/miio/tests/test_waterpurifier.py index 3467859a5..ff5c38741 100644 --- a/miio/tests/test_waterpurifier.py +++ b/miio/tests/test_waterpurifier.py @@ -1,8 +1,10 @@ from unittest import TestCase + +import pytest + from miio import WaterPurifier from miio.waterpurifier import WaterPurifierStatus from .dummies import DummyDevice -import pytest class DummyWaterPurifier(DummyDevice, WaterPurifier): diff --git a/miio/tests/test_wifirepeater.py b/miio/tests/test_wifirepeater.py index 2ec42b907..fd2cd152c 100644 --- a/miio/tests/test_wifirepeater.py +++ b/miio/tests/test_wifirepeater.py @@ -1,7 +1,9 @@ from unittest import TestCase + +import pytest + from miio import WifiRepeater from miio.wifirepeater import WifiRepeaterConfiguration, WifiRepeaterStatus -import pytest class DummyWifiRepeater(WifiRepeater): diff --git a/miio/tests/test_yeelight.py b/miio/tests/test_yeelight.py index 2af70f362..922bc66b4 100644 --- a/miio/tests/test_yeelight.py +++ b/miio/tests/test_yeelight.py @@ -1,7 +1,9 @@ from unittest import TestCase + +import pytest + from miio import Yeelight from miio.yeelight import YeelightMode, YeelightStatus, YeelightException -import pytest from .dummies import DummyDevice diff --git a/miio/updater.py b/miio/updater.py index 649c32e03..a22988d04 100644 --- a/miio/updater.py +++ b/miio/updater.py @@ -1,7 +1,7 @@ -from http.server import HTTPServer, BaseHTTPRequestHandler import hashlib import logging import netifaces +from http.server import HTTPServer, BaseHTTPRequestHandler from os.path import basename _LOGGER = logging.getLogger(__name__) diff --git a/miio/utils.py b/miio/utils.py index 85d3cc5be..b526fdbcf 100644 --- a/miio/utils.py +++ b/miio/utils.py @@ -1,5 +1,5 @@ -import inspect import functools +import inspect import warnings from datetime import timedelta, datetime diff --git a/miio/vacuum.py b/miio/vacuum.py index 5310a839b..3012b4470 100644 --- a/miio/vacuum.py +++ b/miio/vacuum.py @@ -13,7 +13,7 @@ from appdirs import user_cache_dir from .click_common import ( - DeviceGroup, command, GlobalContextObject + DeviceGroup, command, GlobalContextObject, ) from .device import Device, DeviceException from .vacuumcontainers import (VacuumStatus, ConsumableStatus, DNDStatus, diff --git a/miio/vacuum_cli.py b/miio/vacuum_cli.py index 66adad83b..5cb7c9a3d 100644 --- a/miio/vacuum_cli.py +++ b/miio/vacuum_cli.py @@ -1,22 +1,24 @@ # -*- coding: UTF-8 -*- -import logging -import click -import pretty_cron import ast -import sys import json -import time +import logging import pathlib +import sys import threading -from tqdm import tqdm -from appdirs import user_cache_dir +import time from pprint import pformat as pf from typing import Any # noqa: F401 + +import click +import pretty_cron +from appdirs import user_cache_dir +from tqdm import tqdm + +import miio # noqa: E402 from miio.click_common import (ExceptionHandlerGroup, validate_ip, - validate_token) + validate_token, ) from .device import UpdateState from .updater import OneShotServer -import miio # noqa: E402 _LOGGER = logging.getLogger(__name__) pass_dev = click.make_pass_decorator(miio.Device, ensure=True) diff --git a/miio/vacuumcontainers.py b/miio/vacuumcontainers.py index 7887c1b62..5815d99f0 100644 --- a/miio/vacuumcontainers.py +++ b/miio/vacuumcontainers.py @@ -1,7 +1,8 @@ # -*- coding: UTF-8 -*# from datetime import datetime, timedelta, time -from typing import Any, Dict, List from enum import IntEnum +from typing import Any, Dict, List + from .utils import deprecated, pretty_time, pretty_seconds diff --git a/miio/yeelight.py b/miio/yeelight.py index ed3315a3c..d5c5eaa45 100644 --- a/miio/yeelight.py +++ b/miio/yeelight.py @@ -1,6 +1,7 @@ -from typing import Tuple, Optional -from enum import IntEnum import warnings +from enum import IntEnum +from typing import Tuple, Optional + from .device import Device, DeviceException From 9e247a4cd2b6469d50cef125baae8f2bacf59059 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 1 Apr 2018 09:52:12 +0200 Subject: [PATCH 16/18] Add unified cli support to Air Conditioner Companion --- miio/airconditioningcompanion.py | 71 ++++++++++++++++++++++++++++---- miio/chuangmi_ir.py | 2 +- 2 files changed, 63 insertions(+), 10 deletions(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index b74ebfefd..54c3592fe 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -1,6 +1,9 @@ import enum from typing import Optional +import click + +from .click_common import command, format_output, EnumType from .device import Device @@ -166,50 +169,104 @@ def __repr__(self) -> str: self.mode) return s + def __json__(self): + return self.data + class AirConditioningCompanion(Device): """Main class representing Xiaomi Air Conditioning Companion.""" + @command( + default_output=format_output( + "", + "Power: {result.power}\n" + "Load power: {result.load_power}\n" + "Air Condition model: {result.air_condition_model}\n" + "LED: {result.led}\n" + "Target temperature: {result.target_temperature} °C\n" + "Swing mode: {result.swing_mode}\n" + "Fan speed: {result.fan_speed}\n" + "Mode: {result.mode}\n" + ) + ) def status(self) -> AirConditioningCompanionStatus: """Return device status.""" status = self.send("get_model_and_state", []) return AirConditioningCompanionStatus(status) + @command( + default_output=format_output("Powering the air condition on"), + ) def on(self): """Turn the air condition on by infrared.""" return self.send("set_power", ["on"]) + @command( + default_output=format_output("Powering the air condition off"), + ) def off(self): """Turn the air condition off by infared.""" return self.send("set_power", ["off"]) + @command( + click.argument("slot", type=int), + default_output=format_output( + "Learning infrared command into storage slot {slot}") + ) def learn(self, slot: int=STORAGE_SLOT_ID): """Learn an infrared command.""" return self.send("start_ir_learn", [slot]) + @command( + default_output=format_output("Reading learned infrared commands") + ) def learn_result(self): """Read the learned command.""" return self.send("get_ir_learn_result", []) + @command( + click.argument("slot", type=int), + default_output=format_output( + "Learning infrared command into storage slot {slot} stopped") + ) def learn_stop(self, slot: int=STORAGE_SLOT_ID): """Stop learning of a infrared command.""" return self.send("end_ir_learn", [slot]) + @command( + click.argument("command", type=str), + default_output=format_output("Sending the supplied infrared command") + ) def send_ir_code(self, command: str): """Play a captured command. :param str command: Command to execute""" return self.send("send_ir_code", [str(command)]) + @command( + click.argument("command", type=str), + default_output=format_output("Sending a command to the air conditioner") + ) def send_command(self, command: str): """Send a command to the air conditioner. :param str command: Command to execute""" return self.send("send_cmd", [str(command)]) + @command( + click.argument("model", type=str), + click.argument("power", type=EnumType(Power, False)), + click.argument("operation_mode", type=EnumType(OperationMode, False)), + click.argument("target_temperature", type=int), + click.argument("fan_speed", type=EnumType(FanSpeed, False)), + click.argument("swing_mode", type=EnumType(SwingMode, False)), + click.argument("led", type=EnumType(Led, False)), + default_output=format_output( + "Sending a configuration to the air conditioner") + ) def send_configuration(self, model: str, power: Power, operation_mode: OperationMode, - target_temperature: float, fan_speed: FanSpeed, + target_temperature: int, fan_speed: FanSpeed, swing_mode: SwingMode, led: Led): prefix = str(model[0:2] + model[8:16]) @@ -231,20 +288,16 @@ def send_configuration(self, model: str, power: Power, 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:]) + configuration = configuration.replace('[tt]', format(target_temperature, 'X')) configuration = configuration.replace('[li]', str(led.value)) - temperature = (1 + int(target_temperature) - 17) % 16 - temperature = hex(temperature)[2:].upper() + temperature = format((1 + target_temperature - 17) % 16, 'X') configuration = configuration.replace('[tt1]', temperature) - temperature = (4 + int(target_temperature) - 17) % 16 - temperature = hex(temperature)[2:].upper() + temperature = format((4 + target_temperature - 17) % 16, 'X') configuration = configuration.replace('[tt4]', temperature) - temperature = (7 + int(target_temperature) - 17) % 16 - temperature = hex(temperature)[2:].upper() + temperature = format((7 + target_temperature - 17) % 16, 'X') configuration = configuration.replace('[tt7]', temperature) configuration = configuration + suffix diff --git a/miio/chuangmi_ir.py b/miio/chuangmi_ir.py index be879e4ce..689dbbc8c 100644 --- a/miio/chuangmi_ir.py +++ b/miio/chuangmi_ir.py @@ -35,7 +35,7 @@ def learn(self, key: int=1): @command( click.argument("key", type=int), - default_output=format_output("Reading infrared command from key storage key {key}") + default_output=format_output("Reading infrared command from storage key {key}") ) def read(self, key: int=1): """Read a learned command. From c7939cd702bc16698dd562b90b74b367e5fed5a3 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Sun, 1 Apr 2018 10:05:24 +0200 Subject: [PATCH 17/18] Add unified cli support to WiFi Speaker --- miio/tests/test_airconditioningcompanion.py | 6 +- miio/wifispeaker.py | 69 +++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/miio/tests/test_airconditioningcompanion.py b/miio/tests/test_airconditioningcompanion.py index 078aee2f0..64ec34f19 100644 --- a/miio/tests/test_airconditioningcompanion.py +++ b/miio/tests/test_airconditioningcompanion.py @@ -136,7 +136,7 @@ def send_configuration_known_aircondition(): '010000000001072700', # best guess Power.On, OperationMode.Auto, - 22.5, + 22, FanSpeed.Low, SwingMode.On, Led.Off) @@ -146,7 +146,7 @@ def send_configuration_known_aircondition_turn_off(): '010000000001072700', # best guess Power.Off, OperationMode.Auto, - 22.5, + 22, FanSpeed.Low, SwingMode.On, Led.Off) @@ -156,7 +156,7 @@ def send_configuration_unknown_aircondition(): '010507950000257301', Power.On, OperationMode.Auto, - 22.5, + 22, FanSpeed.Low, SwingMode.On, Led.Off) diff --git a/miio/wifispeaker.py b/miio/wifispeaker.py index 287fc7cf3..164a89136 100644 --- a/miio/wifispeaker.py +++ b/miio/wifispeaker.py @@ -2,6 +2,9 @@ import logging import warnings +import click + +from .click_common import command, format_output from .device import Device _LOGGER = logging.getLogger(__name__) @@ -86,6 +89,32 @@ def transport_channel(self) -> TransportChannel: """Transport channel, e.g. PLAYLIST""" return TransportChannel(self.data["transport_channel"]) + def __repr__(self) -> str: + s = "" % \ + (self.device_name, + self.channel, + self.state, + self.play_mode, + self.track_artist, + self.track_title, + self.track_duration, + self.transport_channel, + self.hardware_version) + + return s + + def __json__(self): + return self.data + class WifiSpeaker(Device): """Device class for Xiaomi Smart Wifi Speaker.""" @@ -95,39 +124,79 @@ def __init__(self, *args, **kwargs): "`play_mode` and `transport_channel`.", stacklevel=2) super().__init__(*args, **kwargs) + @command( + default_output=format_output( + "", + "Device name: {result.device_name}\n" + "Channel: {result.channel}\n" + "State: {result.state}\n" + "Play mode: {result.play_mode}\n" + "Track artist: {result.track_artist}\n" + "Track title: {result.track_title}\n" + "Track duration: {result.track_duration}\n" + "Transport channel: {result.transport_channel}\n" + "Hardware version: {result.hardware_version}\n" + ) + ) def status(self) -> WifiSpeakerStatus: """Return device status.""" return WifiSpeakerStatus(self.send("get_prop", ["umi"])) + @command( + default_output=format_output("Powering on"), + ) def power(self): """Toggle power on and off.""" # is this a toggle? return self.send("power") + @command( + default_output=format_output("Toggling play"), + ) def toggle(self): """Toggle play.""" return self.send("toggle") + @command( + click.argument("amount", type=int), + default_output=format_output("Increasing volume by {amount} percent") + ) def volume_up(self, amount: int = 5): """Set volume up.""" return self.send("vol_up", [amount]) + @command( + click.argument("amount", type=int), + default_output=format_output("Decreasing volume by {amount} percent") + ) def volume_down(self, amount: int = 5): """Set volume down.""" return self.send("vol_down", [amount]) + @command( + default_output=format_output("Playing previous track"), + ) def track_previous(self): """Move to previous track.""" return self.send("previous_track") + @command( + default_output=format_output("Playing next track"), + ) def track_next(self): """Move to next track.""" return self.send("next_track") + @command( + default_output=format_output("Switching to the next transport channel"), + ) def channel_next(self): """Change transport channel.""" return self.send("next_channel") + @command( + default_output=format_output("Track position: {result.rel_time}"), + ) def track_position(self): """Return current track position.""" return self.send("get_prop", ["rel_time"]) From bb9302e279ece014c4a32a2d441ec59478b62150 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Wed, 4 Apr 2018 08:41:36 +0200 Subject: [PATCH 18/18] Typo fixed --- miio/airconditioningcompanion.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/airconditioningcompanion.py b/miio/airconditioningcompanion.py index 54c3592fe..ddaa8540b 100644 --- a/miio/airconditioningcompanion.py +++ b/miio/airconditioningcompanion.py @@ -205,7 +205,7 @@ def on(self): default_output=format_output("Powering the air condition off"), ) def off(self): - """Turn the air condition off by infared.""" + """Turn the air condition off by infrared.""" return self.send("set_power", ["off"]) @command(