From f9f3514d01373a2bfdef79d2a85b13916c84ac89 Mon Sep 17 00:00:00 2001 From: scp10011 <506775557@qq.com> Date: Fri, 22 Nov 2019 21:41:14 +0800 Subject: [PATCH 1/4] Improve various parameters 1.add work_state analysis 2.add xiaomi_band interface --- miio/tests/test_toiletlid.py | 67 +++++++++++++++++++++++++++++++++--- miio/toiletlid.py | 58 +++++++++++++++++++++++++++---- 2 files changed, 114 insertions(+), 11 deletions(-) diff --git a/miio/tests/test_toiletlid.py b/miio/tests/test_toiletlid.py index a226968c3..668f2d780 100644 --- a/miio/tests/test_toiletlid.py +++ b/miio/tests/test_toiletlid.py @@ -11,7 +11,6 @@ from .dummies import DummyDevice - """ Response instance >> status @@ -30,10 +29,12 @@ def __init__(self, *args, **kwargs): self.state = { "is_on": False, "work_state": 1, + "work_mode": "Vacant", "ambient_light": "Yellow", "filter_use_flux": "100", "filter_use_time": "180", } + self.users = {} self.return_values = { "get_prop": self._get_state, @@ -43,16 +44,45 @@ def __init__(self, *args, **kwargs): } super().__init__(args, kwargs) - def set_aled_v_of_uid(self, x): - uid, color = x - return self._set_state("ambient_light", [AmbientLightColor(color).name]) + def set_aled_v_of_uid(self, uid, color): + if uid: + if uid in self.users: + self.users.setdefault("ambient_light", AmbientLightColor(color).name) + else: + raise ValueError("This user is not bind.") + else: + return self._set_state("ambient_light", [AmbientLightColor(color).name]) def get_aled_v_of_uid(self, uid): - color = self._get_state(["ambient_light"]) + if uid: + if uid in self.users: + color = self.users.get("ambient_light") + else: + raise ValueError("This user is not bind.") + else: + color = self._get_state(["ambient_light"]) if not AmbientLightColor._member_map_.get(color[0]): raise ValueError(color) return AmbientLightColor._member_map_.get(color[0]).value + def uid_mac_op(self, xiaomi_id, band_mac, alias, operating): + if operating == "bind": + info = self.users.setdefault( + xiaomi_id, {"rssi": -50, "set": "3-0-2-2-0-0-5-5"} + ) + info.update(mac=band_mac, name=alias) + elif operating == "unbind": + self.users.pop(xiaomi_id) + else: + raise ValueError("operating error") + + def get_all_user_info(self): + users = {} + for index, xiaomi_id, info in enumerate(self.users.items(), start=1): + user_id = "user%s" % index + users[user_id] = {"uid": xiaomi_id, **info} + return users + @pytest.fixture(scope="class") def toiletlidv1(request): @@ -62,6 +92,15 @@ def toiletlidv1(request): @pytest.mark.usefixtures("toiletlidv1") class TestToiletlidV1(TestCase): + MOCK_USER = { + "11111111": { + "mac": "ff:ff:ff:ff:ff:ff", + "name": "myband", + "rssi": -50, + "set": "3-0-2-2-0-0-5-5", + } + } + def is_on(self): return self.device.status().is_on @@ -94,3 +133,21 @@ def test_nozzle_clean(self): self.device.nozzle_clean() assert self.is_on() is True self.device._reset_state() + + def test_get_all_user_info(self): + users = self.device.get_all_user_info() + for name, info in users.items(): + assert info["uid"] in self.MOCK_USER + data = self.MOCK_USER[info["uid"]] + assert info["name"] == data["name"] + assert info["mac"] == data["mac"] + + def test_bind_xiaomi_band(self): + for xiaomi_id, info in self.MOCK_USER.items(): + self.device.bind_xiaomi_band(xiaomi_id, info["mac"], info["name"]) + assert self.device.users == self.MOCK_USER + + def test_unbind_xiaomi_band(self): + for xiaomi_id, info in self.MOCK_USER.items(): + self.device.bind_xiaomi_band(xiaomi_id, info["mac"]) + assert self.device.users == {} diff --git a/miio/toiletlid.py b/miio/toiletlid.py index 1fa724347..ddc9ae110 100644 --- a/miio/toiletlid.py +++ b/miio/toiletlid.py @@ -1,6 +1,6 @@ import enum import logging -from typing import Any, Dict +from typing import Any, Dict, List import click @@ -27,6 +27,14 @@ class AmbientLightColor(enum.Enum): Red = "7" +class ToiletlidOperatingMode(enum.Enum): + Vacant = 0 + Occupied = 1 + RearCleanse = 2 + FrontCleanse = 3 + NozzleClean = 6 + + class ToiletlidStatus: def __init__(self, data: Dict[str, Any]) -> None: # {"work_state": 1,"filter_use_flux": 100,"filter_use_time": 180, "ambient_light": "Red"} @@ -37,6 +45,11 @@ def work_state(self) -> int: """Device state code""" return self.data["work_state"] + @property + def work_mode(self) -> str: + """Device working mode""" + return ToiletlidOperatingMode((self.work_state - 1) // 16).name + @property def is_on(self) -> bool: return self.work_state != 1 @@ -60,12 +73,14 @@ def __repr__(self) -> str: return ( "" % ( self.is_on, self.work_state, + self.work_mode, self.ambient_light, self.filter_use_percentage, self.filter_remaining_time, @@ -95,6 +110,7 @@ def __init__( "", "Work: {result.is_on}\n" "State: {result.work_state}\n" + "Work Mode: {result.work_mode}\n" "Ambient Light: {result.ambient_light}\n" "Filter remaining: {result.filter_use_percentage}\n" "Filter remaining time: {result.filter_remaining_time}\n", @@ -123,18 +139,22 @@ def nozzle_clean(self): @command( click.argument("color", type=EnumType(AmbientLightColor, False)), + click.argument("xiaomi_id", type=str, default=""), default_output=format_output( "Set the ambient light to {color} color the next time you start it." ), ) - def set_ambient_light(self, color: AmbientLightColor): + def set_ambient_light(self, color: AmbientLightColor, xiaomi_id: str = ""): """Set Ambient light color.""" - return self.send("set_aled_v_of_uid", ["", color.value]) + return self.send("set_aled_v_of_uid", [xiaomi_id, color.value]) - @command(default_output=format_output("Get the Ambient light color.")) - def get_ambient_light(self) -> str: + @command( + click.argument("xiaomi_id", type=str, default=""), + default_output=format_output("Get the Ambient light color."), + ) + def get_ambient_light(self, xiaomi_id: str = "") -> str: """Get Ambient light color.""" - color = self.send("get_aled_v_of_uid", [""]) + color = self.send("get_aled_v_of_uid", [xiaomi_id]) try: return AmbientLightColor(color[0]).name except ValueError: @@ -142,3 +162,29 @@ def get_ambient_light(self) -> str: "Get ambient light response error, return unknown value: %s.", color[0] ) return "Unknown" + + @command(default_output=format_output("Get user list.")) + def get_all_user_info(self) -> List[Dict]: + """Get All bind user.""" + users = self.send("get_all_user_info") + return users + + @command( + click.argument("xiaomi_id", type=str), + click.argument("band_mac", type=str), + click.argument("alias", type=str), + default_output=format_output("Bind xiaomi band to xiaomi id."), + ) + def bind_xiaomi_band(self, xiaomi_id: str, band_mac: str, alias: str): + + """Bind xiaomi band to xiaomi id.""" + self.send("uid_mac_op", [xiaomi_id, band_mac, alias, "bind"]) + + @command( + click.argument("xiaomi_id", type=str), + click.argument("band_mac", type=str), + default_output=format_output("Unbind xiaomi band to xiaomi id."), + ) + def unbind_xiaomi_band(self, xiaomi_id: str, band_mac: str): + """Unbind xiaomi band to xiaomi id.""" + self.send("uid_mac_op", [xiaomi_id, band_mac, "", "unbind"]) From 8156eeec634ded607e3190ff6325e5e61bc3d528 Mon Sep 17 00:00:00 2001 From: scp10011 <506775557@qq.com> Date: Fri, 22 Nov 2019 22:05:28 +0800 Subject: [PATCH 2/4] ci --- miio/tests/test_toiletlid.py | 1 + 1 file changed, 1 insertion(+) diff --git a/miio/tests/test_toiletlid.py b/miio/tests/test_toiletlid.py index 668f2d780..056b3b743 100644 --- a/miio/tests/test_toiletlid.py +++ b/miio/tests/test_toiletlid.py @@ -11,6 +11,7 @@ from .dummies import DummyDevice + """ Response instance >> status From e3f52eef6a01b8ed4eea5c27190a8d3c881a9950 Mon Sep 17 00:00:00 2001 From: scp10011 <506775557@qq.com> Date: Tue, 26 Nov 2019 09:50:03 +0800 Subject: [PATCH 3/4] update unittest --- miio/tests/test_toiletlid.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/miio/tests/test_toiletlid.py b/miio/tests/test_toiletlid.py index 056b3b743..015c3acb1 100644 --- a/miio/tests/test_toiletlid.py +++ b/miio/tests/test_toiletlid.py @@ -42,10 +42,13 @@ def __init__(self, *args, **kwargs): "nozzle_clean": lambda x: self._set_state("work_state", [97]), "set_aled_v_of_uid": self.set_aled_v_of_uid, "get_aled_v_of_uid": self.get_aled_v_of_uid, + "uid_mac_op": self.uid_mac_op, + "get_all_user_info": self.get_all_user_info, } super().__init__(args, kwargs) - def set_aled_v_of_uid(self, uid, color): + def set_aled_v_of_uid(self, args): + uid, color = args if uid: if uid in self.users: self.users.setdefault("ambient_light", AmbientLightColor(color).name) @@ -54,7 +57,8 @@ def set_aled_v_of_uid(self, uid, color): else: return self._set_state("ambient_light", [AmbientLightColor(color).name]) - def get_aled_v_of_uid(self, uid): + def get_aled_v_of_uid(self, args): + uid = args[0] if uid: if uid in self.users: color = self.users.get("ambient_light") @@ -66,7 +70,8 @@ def get_aled_v_of_uid(self, uid): raise ValueError(color) return AmbientLightColor._member_map_.get(color[0]).value - def uid_mac_op(self, xiaomi_id, band_mac, alias, operating): + def uid_mac_op(self, args): + xiaomi_id, band_mac, alias, operating = args if operating == "bind": info = self.users.setdefault( xiaomi_id, {"rssi": -50, "set": "3-0-2-2-0-0-5-5"} @@ -79,7 +84,7 @@ def uid_mac_op(self, xiaomi_id, band_mac, alias, operating): def get_all_user_info(self): users = {} - for index, xiaomi_id, info in enumerate(self.users.items(), start=1): + for index, (xiaomi_id, info) in enumerate(self.users.items(), start=1): user_id = "user%s" % index users[user_id] = {"uid": xiaomi_id, **info} return users @@ -150,5 +155,5 @@ def test_bind_xiaomi_band(self): def test_unbind_xiaomi_band(self): for xiaomi_id, info in self.MOCK_USER.items(): - self.device.bind_xiaomi_band(xiaomi_id, info["mac"]) + self.device.unbind_xiaomi_band(xiaomi_id, info["mac"]) assert self.device.users == {} From 8a4dabe2004ee8933793ab37e5c14cd1a01ee0fb Mon Sep 17 00:00:00 2001 From: scp10011 <506775557@qq.com> Date: Thu, 28 Nov 2019 17:01:20 +0800 Subject: [PATCH 4/4] work_mode return ToiletlidOperatingMode type un/bind_xiaomi_band return bind or unbind result --- miio/toiletlid.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/miio/toiletlid.py b/miio/toiletlid.py index ddc9ae110..9f6b59998 100644 --- a/miio/toiletlid.py +++ b/miio/toiletlid.py @@ -46,9 +46,9 @@ def work_state(self) -> int: return self.data["work_state"] @property - def work_mode(self) -> str: + def work_mode(self) -> ToiletlidOperatingMode: """Device working mode""" - return ToiletlidOperatingMode((self.work_state - 1) // 16).name + return ToiletlidOperatingMode((self.work_state - 1) // 16) @property def is_on(self) -> bool: @@ -178,7 +178,7 @@ def get_all_user_info(self) -> List[Dict]: def bind_xiaomi_band(self, xiaomi_id: str, band_mac: str, alias: str): """Bind xiaomi band to xiaomi id.""" - self.send("uid_mac_op", [xiaomi_id, band_mac, alias, "bind"]) + return self.send("uid_mac_op", [xiaomi_id, band_mac, alias, "bind"]) @command( click.argument("xiaomi_id", type=str), @@ -187,4 +187,4 @@ def bind_xiaomi_band(self, xiaomi_id: str, band_mac: str, alias: str): ) def unbind_xiaomi_band(self, xiaomi_id: str, band_mac: str): """Unbind xiaomi band to xiaomi id.""" - self.send("uid_mac_op", [xiaomi_id, band_mac, "", "unbind"]) + return self.send("uid_mac_op", [xiaomi_id, band_mac, "", "unbind"])