diff --git a/mirobo/__init__.py b/mirobo/__init__.py index c51860290..6b94945df 100644 --- a/mirobo/__init__.py +++ b/mirobo/__init__.py @@ -1,6 +1,7 @@ # flake8: noqa from mirobo.protocol import Message, Utils -from mirobo.vacuumcontainers import VacuumStatus, ConsumableStatus, CleaningDetails, CleaningSummary, Timer +from mirobo.vacuumcontainers import (VacuumStatus, ConsumableStatus, + CleaningDetails, CleaningSummary, Timer) from mirobo.vacuum import Vacuum, VacuumException from mirobo.plug import Plug from mirobo.plug_v1 import PlugV1 diff --git a/mirobo/airpurifier.py b/mirobo/airpurifier.py index 9423eef07..3f9ab78a1 100644 --- a/mirobo/airpurifier.py +++ b/mirobo/airpurifier.py @@ -1,6 +1,6 @@ import logging import enum -from typing import Any, Dict +from typing import Any, Dict, Optional from collections import defaultdict from .device import Device @@ -134,7 +134,7 @@ def humidity(self) -> int: return self.data["humidity"] @property - def temperature(self) -> float: + def temperature(self) -> Optional[float]: if self.data["temp_dec"] is not None: return self.data["temp_dec"] / 10.0 return None @@ -148,7 +148,7 @@ def led(self) -> bool: return self.data["led"] == "on" @property - def led_brightness(self) -> LedBrightness: + def led_brightness(self) -> Optional[LedBrightness]: if self.data["led_b"] is not None: return LedBrightness(self.data["led_b"]) return None diff --git a/mirobo/ceil.py b/mirobo/ceil.py index 31045568b..26cb7d459 100644 --- a/mirobo/ceil.py +++ b/mirobo/ceil.py @@ -5,6 +5,7 @@ _LOGGER = logging.getLogger(__name__) + class CeilStatus: """Container for status reports from Xiaomi Philips LED Ceiling Lamp""" @@ -50,10 +51,10 @@ def automatic_color_temperature(self) -> int: def __str__(self) -> str: s = "" % ( - self.power, self.brightness, - self.color_temperature, self.scene, self.dv, - self.smart_night_light, self.automatic_color_temperature) + "smart_night_light=%s, automatic_color_temperature=%s>" % \ + (self.power, self.brightness, + self.color_temperature, self.scene, self.dv, + self.smart_night_light, self.automatic_color_temperature) return s diff --git a/mirobo/ceil_cli.py b/mirobo/ceil_cli.py index 3dacab618..3ad20399a 100644 --- a/mirobo/ceil_cli.py +++ b/mirobo/ceil_cli.py @@ -132,7 +132,7 @@ def set_brightness(dev: mirobo.Ceil, level): @pass_dev def set_color_temperature(dev: mirobo.Ceil, level): """Set CCT level.""" - click.echo("Correlated color temperatur level: %s" % + click.echo("Color temperature level: %s" % dev.set_color_temperature(level)) diff --git a/mirobo/discovery.py b/mirobo/discovery.py index f2698a944..e72e44128 100644 --- a/mirobo/discovery.py +++ b/mirobo/discovery.py @@ -7,6 +7,7 @@ PhilipsEyecare, ChuangmiIr) from typing import Union, Callable, Dict + _LOGGER = logging.getLogger(__name__) @@ -20,6 +21,7 @@ def other_package_info(info, desc): class Listener: def __init__(self): self.found_devices = {} + def _check_if_supported(self, info, addr): name = info.name for k, v in Discovery._mdns_device_map.items(): @@ -28,15 +30,18 @@ def _check_if_supported(self, info, addr): dev = v(ip=addr) m = dev.do_discover() dev.token = m.checksum - _LOGGER.info("Found supported '%s' at %s:%s (%s) token: %s" % ( - v.__name__, addr, info.port, name, dev.token)) + _LOGGER.info( + "Found supported '%s' at %s:%s (%s) token: %s" % + (v.__name__, addr, info.port, name, dev.token)) return dev elif callable(v): _LOGGER.info(v(info)) dev = Device(ip=addr) - _LOGGER.info("token: %s" % codecs.encode(dev.do_discover().checksum, 'hex')) + _LOGGER.info("token: %s" % codecs.encode( + dev.do_discover().checksum, 'hex')) return None - _LOGGER.warning("Found unsupported device %s at %s, please report to developers" % (name, addr)) + _LOGGER.warning("Found unsupported device %s at %s, " + "please report to developers" % (name, addr)) return None def add_service(self, zeroconf, type, name): @@ -67,18 +72,21 @@ class Discovery: "philips-light-bulb": Ceil, "philips-light-ceil": Ceil, "philips-light-sread1": PhilipsEyecare, - "yeelink-light-": lambda x: other_package_info(x, "python-yeelight package"), - "lumi-gateway-": lambda x: other_package_info(x, "https://github.com/Danielhiversen/PyXiaomiGateway") - } # type: Dict[str, Union[Callable, Device]] + "yeelink-light-": lambda x: other_package_info( + x, "python-yeelight package"), + "lumi-gateway-": lambda x: other_package_info( + x, "https://github.com/Danielhiversen/PyXiaomiGateway") + } # type: Dict[str, Union[Callable, Device]] @staticmethod def discover_mdns(): _LOGGER.info("Discovering devices with mDNS, press any key to quit...") listener = Listener() - browser = zeroconf.ServiceBrowser(zeroconf.Zeroconf(), "_miio._udp.local.", listener) + browser = zeroconf.ServiceBrowser( + zeroconf.Zeroconf(), "_miio._udp.local.", listener) input() # to keep execution running until a key is pressed browser.cancel() - return listener.found_devices \ No newline at end of file + return listener.found_devices diff --git a/mirobo/plug.py b/mirobo/plug.py index 7d6e1fba5..5b8607ca7 100644 --- a/mirobo/plug.py +++ b/mirobo/plug.py @@ -1,5 +1,5 @@ from .device import Device -from typing import Dict, Any +from typing import Dict, Any, Optional class PlugStatus: @@ -20,7 +20,7 @@ def temperature(self) -> float: return self.data["temperature"] @property - def load_power(self) -> float: + def load_power(self) -> Optional[float]: if self.data["current"] is not None: # The constant of 110V is used intentionally. The current was # calculated with a wrong reference voltage already. diff --git a/mirobo/tests/test_protocol.py b/mirobo/tests/test_protocol.py index fa2ffc2ab..ba4671ddb 100644 --- a/mirobo/tests/test_protocol.py +++ b/mirobo/tests/test_protocol.py @@ -1,5 +1,5 @@ from unittest import TestCase -from .. import Message, Utils +from .. import Utils class TestProtocol(TestCase): diff --git a/mirobo/vacuum.py b/mirobo/vacuum.py index 8831d138e..02b1d8677 100644 --- a/mirobo/vacuum.py +++ b/mirobo/vacuum.py @@ -17,7 +17,8 @@ class VacuumException(DeviceException): class Vacuum(Device): """Main class representing the vacuum.""" - def __init__(self, ip: str, token: str, start_id: int = 0, debug: int = 0) -> None: + def __init__(self, ip: str, token: str, start_id: int = 0, + debug: int = 0) -> None: super().__init__(ip, token, start_id, debug) self.manual_seqnum = -1 @@ -52,8 +53,10 @@ def manual_stop(self): self.manual_seqnum = 0 return self.send("app_rc_end") - def manual_control_once(self, rotation: int, velocity: float, duration: int=1500): - """Starts the remote control mode and executes the action once before deactivating the mode.""" + def manual_control_once( + self, rotation: int, velocity: float, duration: int=1500): + """Starts the remote control mode and executes + the action once before deactivating the mode.""" number_of_tries = 3 self.manual_start() while number_of_tries > 0: @@ -66,13 +69,15 @@ def manual_control_once(self, rotation: int, velocity: float, duration: int=1500 time.sleep(2) number_of_tries -= 1 - def manual_control(self, rotation: int, velocity: float, duration: int=1500): + def manual_control(self, rotation: int, velocity: float, + duration: int=1500): """Give a command over manual control interface.""" if rotation <= -180 or rotation >= 180: - raise DeviceException("Given rotation is invalid, should be ]-3.1,3.1[, was %s" % rotation) + raise DeviceException("Given rotation is invalid, should " + "be ]-3.1,3.1[, was %s" % rotation) if velocity <= -0.3 or velocity >= 0.3: - raise DeviceException("Given velocity is invalid, should be ]-0.3, 0.3[, was: %s" % velocity) - + raise DeviceException("Given velocity is invalid, should " + "be ]-0.3, 0.3[, was: %s" % velocity) self.manual_seqnum += 1 params = {"omega": round(math.radians(rotation), 1), @@ -138,7 +143,8 @@ def set_timer(self, details): # how to create timers/change values? # ['ts', 'on'] to enable raise NotImplementedError() - return self.send("set_timer", [["ts",["cron_line",["start_clean",""]]]]) + return self.send( + "set_timer", [["ts", ["cron_line", ["start_clean", ""]]]]) return self.send("upd_timer", ["ts", "on"]) def dnd_status(self): diff --git a/mirobo/vacuum_cli.py b/mirobo/vacuum_cli.py index 649c09e21..192c193a2 100644 --- a/mirobo/vacuum_cli.py +++ b/mirobo/vacuum_cli.py @@ -9,6 +9,7 @@ from pprint import pformat as pf from typing import Any + if sys.version_info < (3, 4): print("To use this script you need python 3.4 or newer, got %s" % sys.version_info) @@ -181,7 +182,7 @@ def home(vac: mirobo.Vacuum): @cli.group() @pass_dev -#@click.argument('command', required=False) +# @click.argument('command', required=False) def manual(vac: mirobo.Vacuum): """Control the robot manually.""" command = '' @@ -191,7 +192,8 @@ def manual(vac: mirobo.Vacuum): if command == 'stop': click.echo("Stopping manual control") return vac.manual_stop() - #if not vac.manual_mode and command : + # if not vac.manual_mode and command : + @manual.command() @pass_dev @@ -239,7 +241,7 @@ def forward(vac: mirobo.Vacuum, amount: float): @manual.command() @click.argument('amount', type=float) @pass_dev -def backward(vac: mirobo.Vacuum, amount:float): +def backward(vac: mirobo.Vacuum, amount: float): """Run backwards.""" click.echo("Moving backwards") return vac.manual_control(0, -amount) @@ -341,6 +343,7 @@ def info(vac: mirobo.Vacuum): click.echo(res) _LOGGER.debug("Full response: %s" % pf(res.raw)) + @cli.command() @pass_dev def cleaning_history(vac: mirobo.Vacuum): @@ -368,12 +371,14 @@ def sound(vac: mirobo.Vacuum): """Query sound settings.""" click.echo(vac.sound_info()) + @cli.command() @pass_dev def serial_number(vac: mirobo.Vacuum): """Query serial number.""" click.echo("Serial#: %s" % vac.serial_number()) + @cli.command() @click.argument('tz', required=False) @pass_dev @@ -385,6 +390,7 @@ def timezone(vac: mirobo.Vacuum, tz=None): else: click.echo("Timezone: %s" % vac.timezone()) + @cli.command() @click.argument('cmd', required=True) @click.argument('parameters', required=False) diff --git a/mirobo/yeelight.py b/mirobo/yeelight.py index 39ff16361..0e9935e1f 100644 --- a/mirobo/yeelight.py +++ b/mirobo/yeelight.py @@ -1,12 +1,14 @@ from .device import Device -from typing import Tuple +from typing import Tuple, Optional from enum import IntEnum + class YeelightMode(IntEnum): RGB = 1 ColorTemperature = 2 HSV = 3 + class YeelightStatus: def __init__(self, data): self.data = data @@ -20,30 +22,27 @@ def bright(self) -> int: return int(self.data["bright"]) @property - def rgb(self) -> Tuple[int, int, int]: - rgb = self.data["rgb"] - blue = rgb & 0xff - green = (rgb >> 8) & 0xff - red = (rgb >> 16) & 0xff - return red, green, blue + def rgb(self) -> Optional[Tuple[int, int, int]]: + if self.color_mode == YeelightMode.RGB: + rgb = self.data["rgb"] + blue = rgb & 0xff + green = (rgb >> 8) & 0xff + red = (rgb >> 16) & 0xff + return red, green, blue + return None @property def color_mode(self) -> YeelightMode: return YeelightMode(int(self.data["color_mode"])) @property - def hsv(self): + def hsv(self) -> Optional[Tuple[int, int, int]]: if self.color_mode == YeelightMode.HSV: return self.data["hue"], self.data["sat"], self.data["bright"] + return None @property - def rgb(self): - if self.color_mode == YeelightMode.RGB: - val = self.data["rgb"] - raise NotImplementedError() - - @property - def color_temp(self) -> int: + def color_temp(self) -> Optional[int]: if self.color_mode == YeelightMode.ColorTemperature: return int(self.data["ct"]) return None @@ -53,15 +52,17 @@ def name(self) -> str: return self.data["name"] def __repr__(self): - return "" % ( - self.is_on, - self.color_mode, - self.bright, - self.color_temp, - self.rgb, - self.hsv, - self.name - ) + s = "" % \ + (self.is_on, + self.color_mode, + self.bright, + self.color_temp, + self.rgb, + self.hsv, + self.name) + return s + class Yeelight(Device): """A rudimentary support for Yeelight bulbs.