From 54295d348209442408a1921ed4bc30cbe2175e50 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 5 Dec 2022 21:05:28 +0100 Subject: [PATCH 01/16] Multi maps part 2 --- miio/integrations/vacuum/roborock/vacuum.py | 79 ++++++++++++++++-- .../vacuum/roborock/vacuumcontainers.py | 82 ++++++++++++++++++- 2 files changed, 150 insertions(+), 11 deletions(-) diff --git a/miio/integrations/vacuum/roborock/vacuum.py b/miio/integrations/vacuum/roborock/vacuum.py index 5983956c0..4311b5d35 100644 --- a/miio/integrations/vacuum/roborock/vacuum.py +++ b/miio/integrations/vacuum/roborock/vacuum.py @@ -7,7 +7,7 @@ import os import pathlib import time -from typing import List, Optional, Type, Union +from typing import Dict, List, Optional, Tuple, Type, Union import click import pytz @@ -47,6 +47,7 @@ CleaningSummary, ConsumableStatus, DNDStatus, + FloorCleanDetails, MapList, SoundInstallStatus, SoundStatus, @@ -137,6 +138,9 @@ def __init__( ip, token, start_id, debug, lazy_discover, timeout, model=model ) self.manual_seqnum = -1 + self._floor_clean_details: Dict[int, Optional[CleaningDetails]] = {} + self._last_clean_details: Optional[CleaningDetails] = None + self._searched_clean_id: Optional[int] = None self._maps: Optional[MapList] = None self._map_enum_cache = None @@ -335,14 +339,20 @@ def status(self) -> VacuumStatus: """Return status of the vacuum.""" status = self.vacuum_status() status.embed(self.consumable_status()) - status.embed(self.clean_history()) + clean_history = self.clean_history() + status.embed(clean_history) + (details_floors, details_last) = self.last_clean_all_floor( + history=clean_history + ) + status.embed(details_last) + status.embed(details_floors) status.embed(self.dnd_status()) return status @command() def vacuum_status(self) -> VacuumStatus: """Return only status of the vacuum.""" - return VacuumStatus(self.send("get_status")[0]) + return VacuumStatus(self.send("get_status")[0], self.get_maps()) def enable_log_upload(self): raise NotImplementedError("unknown parameters") @@ -489,17 +499,69 @@ def clean_history(self) -> CleaningSummary: return CleaningSummary(self.send("get_clean_summary")) @command() - def last_clean_details(self) -> Optional[CleaningDetails]: + def last_clean_details( + self, history: Optional[CleaningSummary] = None + ) -> Optional[CleaningDetails]: """Return details from the last cleaning. Returns None if there has been no cleanups. """ - history = self.clean_history() + if history is None: + history = self.clean_history() if not history.ids: return None - last_clean_id = history.ids.pop(0) - return self.clean_details(last_clean_id) + last_clean_id = history.ids[0] + if last_clean_id == self._searched_clean_id: + return self._last_clean_details + + self._last_clean_details = self.clean_details(last_clean_id) + return self._last_clean_details + + @command() + def last_clean_all_floor( + self, history: Optional[CleaningSummary] = None + ) -> Tuple[FloorCleanDetails, Optional[CleaningDetails]]: + """Return details from the last cleaning and for each floor. + + Returns None if there has been no cleanups for that floor. + """ + if history is None: + history = self.clean_history() + + map_ids = self.get_maps().map_id_list + + # if cache empty, fill with None + if not self._floor_clean_details: + for id in map_ids: + self._floor_clean_details[id] = None + + if not history.ids: + return ( + FloorCleanDetails(self._floor_clean_details), + self._last_clean_details, + ) + + last_clean_id = history.ids[0] + for id in history.ids: + # already searched this record + if id == self._searched_clean_id: + break + + clean_detail = self.clean_details(id) + if clean_detail.map_id in map_ids: + self._floor_clean_details[clean_detail.map_id] = clean_detail + map_ids.remove(clean_detail.map_id) + + if id == last_clean_id: + self._last_clean_details = clean_detail + + # all floors found + if not map_ids: + break + + self._searched_clean_id = last_clean_id + return (FloorCleanDetails(self._floor_clean_details), self._last_clean_details) @command( click.argument("id_", type=int, metavar="ID"), @@ -514,8 +576,7 @@ def clean_details( _LOGGER.warning("No cleaning record found for id %s", id_) return None - res = CleaningDetails(details.pop()) - return res + return CleaningDetails(details.pop(), self.get_maps()) @command() @action(name="Find robot", type="vacuum") diff --git a/miio/integrations/vacuum/roborock/vacuumcontainers.py b/miio/integrations/vacuum/roborock/vacuumcontainers.py index 04de1c1d0..0664ea9d1 100644 --- a/miio/integrations/vacuum/roborock/vacuumcontainers.py +++ b/miio/integrations/vacuum/roborock/vacuumcontainers.py @@ -6,6 +6,7 @@ from croniter import croniter from pytz import BaseTzInfo +from miio.descriptors import SensorDescriptor from miio.device import DeviceStatus from miio.devicestatus import sensor, setting from miio.interfaces.vacuuminterface import VacuumDeviceStatus, VacuumState @@ -136,7 +137,9 @@ def map_name_dict(self) -> Dict[str, int]: class VacuumStatus(VacuumDeviceStatus): """Container for status reports from the vacuum.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__( + self, data: Dict[str, Any], maps: Optional[MapList] = None + ) -> None: # {'result': [{'state': 8, 'dnd_enabled': 1, 'clean_time': 0, # 'msg_ver': 4, 'map_present': 1, 'error_code': 0, 'in_cleaning': 0, # 'clean_area': 0, 'battery': 100, 'fan_power': 20, 'msg_seq': 320}], @@ -177,6 +180,7 @@ def __init__(self, data: Dict[str, Any]) -> None: # 'water_shortage_status': 0, 'dock_type': 0, 'dust_collection_status': 0, # 'auto_dust_collection': 1, 'mop_mode': 300, 'debug_mode': 0}] self.data = data + self._maps = maps @property @sensor("State code", entity_category="diagnostic", enabled_default=False) @@ -337,6 +341,14 @@ def current_map_id(self) -> int: """ return int((self.data["map_status"] + 1) / 4 - 1) + @property + def current_map_name(self) -> str: + """The name of the current map with regards to the multi map feature.""" + if self._maps is None: + return str(self.current_map_id) + + return self._maps.map_list[self.current_map_id]["name"] + @property def in_zone_cleaning(self) -> bool: """Return True if the vacuum is in zone cleaning mode.""" @@ -494,10 +506,15 @@ def dust_collection_count(self) -> Optional[int]: class CleaningDetails(DeviceStatus): """Contains details about a specific cleaning run.""" - def __init__(self, data: Union[List[Any], Dict[str, Any]]) -> None: + def __init__( + self, + data: Union[List[Any], Dict[str, Any]], + maps: Optional[MapList] = None, + ) -> None: # start, end, duration, area, unk, complete # { "result": [ [ 1488347071, 1488347123, 16, 0, 0, 0 ] ], "id": 1 } # newer models return a dict + self._maps = maps if isinstance(data, list): self.data = { "begin": data[0], @@ -560,6 +577,15 @@ def map_id(self) -> int: """Map id used (multi map feature) during the cleaning run.""" return self.data.get("map_flag", 0) + @property + @sensor("Last clean map name", icon="mdi:floor-plan", entity_category="diagnostic") + def map_name(self) -> str: + """The name of the map used (multi map feature) during the cleaning run.""" + if self._maps is None: + return str(self.map_id) + + return self._maps.map_list[self.map_id]["name"] + @property def error_code(self) -> int: """Error code.""" @@ -579,6 +605,58 @@ def complete(self) -> bool: return self.data["complete"] == 1 +class FloorCleanDetails(DeviceStatus): + """Contains details about a last cleaning run per floor.""" + + def __init__(self, data: Dict[str, Any]) -> None: + self.data = data + + for map_id in self.data: + if self.data[map_id] is None: + setattr(self, f"CleanDetails_{map_id}", None) + setattr(self, f"start_{map_id}", None) + continue + setattr(self, f"CleanDetails_{map_id}", self.data[map_id]) + setattr(self, f"start_{map_id}", self.data[map_id].start) + + def __repr__(self): + + s = f"<{self.__class__.__name__}" + for map_id in self.data: + name = f"CleanDetails_{map_id}" + value = getattr(self, name) + s += f" {name}={value}" + + name = f"start_{map_id}" + value = getattr(self, name) + s += f" {name}={value}" + + for name, embedded in self._embedded.items(): + s += f" {name}={repr(embedded)}" + + s += ">" + return s + + def sensors(self) -> Dict[str, SensorDescriptor]: + """Return the dict of sensors exposed by the status container.""" + self._sensors = {} # type: ignore[attr-defined] + + for map_id in self.data: + self._sensors[f"start_{map_id}"] = SensorDescriptor( + id=f"FloorCleanDetails.start_{map_id}", + property=f"start_{map_id}", + name=f"Floor {map_id} clean start", + type="sensor", + extras={ + "icon": "mdi:clock-time-twelve", + "device_class": "timestamp", + "entity_category": "diagnostic", + }, + ) + + return self._sensors + + class ConsumableStatus(DeviceStatus): """Container for consumable status information, including information about brushes and duration until they should be changed. The methods returning time left are based From e7f693cdf8a6d8f46f7de73ff3f8cd5a948a4cb6 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 5 Dec 2022 21:11:25 +0100 Subject: [PATCH 02/16] fix tests --- miio/integrations/vacuum/roborock/tests/test_vacuum.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/miio/integrations/vacuum/roborock/tests/test_vacuum.py b/miio/integrations/vacuum/roborock/tests/test_vacuum.py index 8608fa680..ff69b43e9 100644 --- a/miio/integrations/vacuum/roborock/tests/test_vacuum.py +++ b/miio/integrations/vacuum/roborock/tests/test_vacuum.py @@ -40,6 +40,9 @@ def __init__(self, *args, **kwargs): } self._maps = None self._map_enum_cache = None + self._floor_clean_details = {} + self._last_clean_details = None + self._searched_clean_id = None self.dummies = {} self.dummies["consumables"] = [ From 7e918867ee650054d60eee1053e5c4a627d24679 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 5 Dec 2022 21:17:28 +0100 Subject: [PATCH 03/16] fix black --- miio/integrations/vacuum/roborock/vacuumcontainers.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/miio/integrations/vacuum/roborock/vacuumcontainers.py b/miio/integrations/vacuum/roborock/vacuumcontainers.py index 0664ea9d1..49cedea20 100644 --- a/miio/integrations/vacuum/roborock/vacuumcontainers.py +++ b/miio/integrations/vacuum/roborock/vacuumcontainers.py @@ -137,9 +137,7 @@ def map_name_dict(self) -> Dict[str, int]: class VacuumStatus(VacuumDeviceStatus): """Container for status reports from the vacuum.""" - def __init__( - self, data: Dict[str, Any], maps: Optional[MapList] = None - ) -> None: + def __init__(self, data: Dict[str, Any], maps: Optional[MapList] = None) -> None: # {'result': [{'state': 8, 'dnd_enabled': 1, 'clean_time': 0, # 'msg_ver': 4, 'map_present': 1, 'error_code': 0, 'in_cleaning': 0, # 'clean_area': 0, 'battery': 100, 'fan_power': 20, 'msg_seq': 320}], From 9161737b1aa07f49b6548ce02ab8cca4087a3215 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Mon, 30 Jan 2023 21:52:08 +0100 Subject: [PATCH 04/16] Do not pass maps around but use embing --- miio/integrations/roborock/vacuum/vacuum.py | 3 ++- miio/integrations/roborock/vacuum/vacuumcontainers.py | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index fec19d9bc..17951d6f1 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -340,6 +340,7 @@ def manual_control( def status(self) -> VacuumStatus: """Return status of the vacuum.""" status = self.vacuum_status() + status.embed(self.get_maps()) status.embed(self.consumable_status()) clean_history = self.clean_history() status.embed(clean_history) @@ -354,7 +355,7 @@ def status(self) -> VacuumStatus: @command() def vacuum_status(self) -> VacuumStatus: """Return only status of the vacuum.""" - return VacuumStatus(self.send("get_status")[0], self.get_maps()) + return VacuumStatus(self.send("get_status")[0]) def enable_log_upload(self): raise NotImplementedError("unknown parameters") diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index c09f96431..4c27b2690 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -137,7 +137,7 @@ def map_name_dict(self) -> Dict[str, int]: class VacuumStatus(VacuumDeviceStatus): """Container for status reports from the vacuum.""" - def __init__(self, data: Dict[str, Any], maps: Optional[MapList] = None) -> None: + def __init__(self, data: Dict[str, Any]) -> None: # {'result': [{'state': 8, 'dnd_enabled': 1, 'clean_time': 0, # 'msg_ver': 4, 'map_present': 1, 'error_code': 0, 'in_cleaning': 0, # 'clean_area': 0, 'battery': 100, 'fan_power': 20, 'msg_seq': 320}], @@ -178,7 +178,6 @@ def __init__(self, data: Dict[str, Any], maps: Optional[MapList] = None) -> None # 'water_shortage_status': 0, 'dock_type': 0, 'dust_collection_status': 0, # 'auto_dust_collection': 1, 'mop_mode': 300, 'debug_mode': 0}] self.data = data - self._maps = maps @property @sensor("State code", entity_category="diagnostic", enabled_default=False) @@ -342,10 +341,12 @@ def current_map_id(self) -> int: @property def current_map_name(self) -> str: """The name of the current map with regards to the multi map feature.""" - if self._maps is None: + try: + map_list = self.MapList__map_list + except AttributeError: return str(self.current_map_id) - return self._maps.map_list[self.current_map_id]["name"] + return map_list[self.current_map_id]["name"] @property def in_zone_cleaning(self) -> bool: From 1eeb5d3bf9f276302387b109b5fc36c90c40d5c6 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 09:31:16 +0100 Subject: [PATCH 05/16] Update vacuum.py --- miio/integrations/roborock/vacuum/vacuum.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 8f93eb829..b1d4225a7 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -150,10 +150,11 @@ def __init__( self._maps: Optional[MapList] = None self._map_enum_cache = None self._status_helper = UpdateHelper(self.vacuum_status) + self._status_helper.add_update_method("map_list", self.get_maps) self._status_helper.add_update_method("consumables", self.consumable_status) self._status_helper.add_update_method("dnd_status", self.dnd_status) self._status_helper.add_update_method("clean_history", self.clean_history) - self._status_helper.add_update_method("last_clean", self.last_clean_details) + self._status_helper.add_update_method("last_clean", self.last_clean_all_floor) self._status_helper.add_update_method("mop_dryer", self.mop_dryer_settings) def send( From 72b22971e98ef91337e2ab6aa018ea002e32705b Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 11:48:55 +0100 Subject: [PATCH 06/16] Single return for last_clean_all_floor --- miio/integrations/roborock/vacuum/vacuum.py | 42 ++++++++++----------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index b1d4225a7..59f924a25 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -144,9 +144,10 @@ def __init__( ip, token, start_id, debug, lazy_discover, timeout, model=model ) self.manual_seqnum = -1 + self._clean_history = Optional[CleaningSummary] = None + self._searched_clean_id: Optional[int] = None self._floor_clean_details: Dict[int, Optional[CleaningDetails]] = {} self._last_clean_details: Optional[CleaningDetails] = None - self._searched_clean_id: Optional[int] = None self._maps: Optional[MapList] = None self._map_enum_cache = None self._status_helper = UpdateHelper(self.vacuum_status) @@ -154,7 +155,8 @@ def __init__( self._status_helper.add_update_method("consumables", self.consumable_status) self._status_helper.add_update_method("dnd_status", self.dnd_status) self._status_helper.add_update_method("clean_history", self.clean_history) - self._status_helper.add_update_method("last_clean", self.last_clean_all_floor) + self._status_helper.add_update_method("last_clean_all_floor", self.last_clean_all_floor) + self._status_helper.add_update_method("last_clean", self.last_clean_details) self._status_helper.add_update_method("mop_dryer", self.mop_dryer_settings) def send( @@ -520,22 +522,21 @@ def enable_lab_mode(self, enable): @command() def clean_history(self) -> CleaningSummary: """Return generic cleaning history.""" - return CleaningSummary(self.send("get_clean_summary")) + self._clean_history = CleaningSummary(self.send("get_clean_summary")) + return self._clean_history @command() - def last_clean_details( - self, history: Optional[CleaningSummary] = None - ) -> Optional[CleaningDetails]: + def last_clean_details(self, skip_cache=False) -> Optional[CleaningDetails]: """Return details from the last cleaning. Returns None if there has been no cleanups. """ - if history is None: - history = self.clean_history() - if not history.ids: + if self._clean_history is None or skip_cache: + self._clean_history = self.clean_history() + if not self._clean_history.ids: return None - last_clean_id = history.ids[0] + last_clean_id = self._clean_history.ids[0] if last_clean_id == self._searched_clean_id: return self._last_clean_details @@ -543,15 +544,13 @@ def last_clean_details( return self._last_clean_details @command() - def last_clean_all_floor( - self, history: Optional[CleaningSummary] = None - ) -> Tuple[FloorCleanDetails, Optional[CleaningDetails]]: + def last_clean_all_floor(self, skip_cache=False) -> FloorCleanDetails: """Return details from the last cleaning and for each floor. Returns None if there has been no cleanups for that floor. """ - if history is None: - history = self.clean_history() + if self._clean_history is None or skip_cache: + self._clean_history = self.clean_history() map_ids = self.get_maps().map_id_list @@ -560,14 +559,11 @@ def last_clean_all_floor( for id in map_ids: self._floor_clean_details[id] = None - if not history.ids: - return ( - FloorCleanDetails(self._floor_clean_details), - self._last_clean_details, - ) + if not self._clean_history.ids: + return FloorCleanDetails(self._floor_clean_details) - last_clean_id = history.ids[0] - for id in history.ids: + last_clean_id = self._clean_history.ids[0] + for id in self._clean_history.ids: # already searched this record if id == self._searched_clean_id: break @@ -585,7 +581,7 @@ def last_clean_all_floor( break self._searched_clean_id = last_clean_id - return (FloorCleanDetails(self._floor_clean_details), self._last_clean_details) + return FloorCleanDetails(self._floor_clean_details) @command( click.argument("id_", type=int, metavar="ID"), From 62a4b28218f8d05c3173c3d27515b06c0c2a7f24 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 12:01:06 +0100 Subject: [PATCH 07/16] use parent acces instead of supplying get_maps --- miio/integrations/roborock/vacuum/vacuum.py | 2 +- miio/integrations/roborock/vacuum/vacuumcontainers.py | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 59f924a25..dc2849c40 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -594,7 +594,7 @@ def clean_details(self, id_: int) -> Optional[CleaningDetails]: _LOGGER.warning("No cleaning record found for id %s", id_) return None - return CleaningDetails(details.pop(), self.get_maps()) + return CleaningDetails(details.pop()) @command() @action(name="Find robot", type="vacuum") diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index 4c27b2690..b661cbfdb 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -342,7 +342,7 @@ def current_map_id(self) -> int: def current_map_name(self) -> str: """The name of the current map with regards to the multi map feature.""" try: - map_list = self.MapList__map_list + map_list = self.map_list__map_list except AttributeError: return str(self.current_map_id) @@ -534,12 +534,10 @@ class CleaningDetails(DeviceStatus): def __init__( self, data: Union[List[Any], Dict[str, Any]], - maps: Optional[MapList] = None, ) -> None: # start, end, duration, area, unk, complete # { "result": [ [ 1488347071, 1488347123, 16, 0, 0, 0 ] ], "id": 1 } # newer models return a dict - self._maps = maps if isinstance(data, list): self.data = { "begin": data[0], @@ -606,10 +604,12 @@ def map_id(self) -> int: @sensor("Last clean map name", icon="mdi:floor-plan", entity_category="diagnostic") def map_name(self) -> str: """The name of the map used (multi map feature) during the cleaning run.""" - if self._maps is None: + try: + map_list = self._parent.map_list__map_list + except AttributeError: return str(self.map_id) - return self._maps.map_list[self.map_id]["name"] + return map_list[self.map_id]["name"] @property def error_code(self) -> int: From f26ae627cfb333654cbbe3fb403514695598df4b Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 12:02:45 +0100 Subject: [PATCH 08/16] Update vacuumcontainers.py --- miio/integrations/roborock/vacuum/vacuumcontainers.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index b661cbfdb..21ab2c29f 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -531,10 +531,7 @@ def dust_collection_count(self) -> Optional[int]: class CleaningDetails(DeviceStatus): """Contains details about a specific cleaning run.""" - def __init__( - self, - data: Union[List[Any], Dict[str, Any]], - ) -> None: + def __init__(self, data: Union[List[Any], Dict[str, Any]]) -> None: # start, end, duration, area, unk, complete # { "result": [ [ 1488347071, 1488347123, 16, 0, 0, 0 ] ], "id": 1 } # newer models return a dict From e47c6d72c24a026e3734605c3d61fb0aa6e36044 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 12:12:19 +0100 Subject: [PATCH 09/16] Update vacuum.py --- miio/integrations/roborock/vacuum/vacuum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index dc2849c40..bc3ba23a2 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -144,7 +144,7 @@ def __init__( ip, token, start_id, debug, lazy_discover, timeout, model=model ) self.manual_seqnum = -1 - self._clean_history = Optional[CleaningSummary] = None + self._clean_history: Optional[CleaningSummary] = None self._searched_clean_id: Optional[int] = None self._floor_clean_details: Dict[int, Optional[CleaningDetails]] = {} self._last_clean_details: Optional[CleaningDetails] = None From 38c06d046822a9028ee3a8d523ed9859e65790f6 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 12:23:32 +0100 Subject: [PATCH 10/16] rename to floor_clean --- miio/integrations/roborock/vacuum/vacuum.py | 2 +- miio/integrations/roborock/vacuum/vacuumcontainers.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index bc3ba23a2..926917494 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -155,7 +155,7 @@ def __init__( self._status_helper.add_update_method("consumables", self.consumable_status) self._status_helper.add_update_method("dnd_status", self.dnd_status) self._status_helper.add_update_method("clean_history", self.clean_history) - self._status_helper.add_update_method("last_clean_all_floor", self.last_clean_all_floor) + self._status_helper.add_update_method("floor_clean", self.last_clean_all_floor) self._status_helper.add_update_method("last_clean", self.last_clean_details) self._status_helper.add_update_method("mop_dryer", self.mop_dryer_settings) diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index 21ab2c29f..6576f92a6 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -342,7 +342,7 @@ def current_map_id(self) -> int: def current_map_name(self) -> str: """The name of the current map with regards to the multi map feature.""" try: - map_list = self.map_list__map_list + map_list = self.map_list.map_list except AttributeError: return str(self.current_map_id) @@ -602,7 +602,7 @@ def map_id(self) -> int: def map_name(self) -> str: """The name of the map used (multi map feature) during the cleaning run.""" try: - map_list = self._parent.map_list__map_list + map_list = self._parent.map_list.map_list except AttributeError: return str(self.map_id) From 3e9508f94085f9cc8349228b464b16d828ec5433 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 12:54:08 +0100 Subject: [PATCH 11/16] fix linting --- miio/integrations/roborock/vacuum/vacuum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 926917494..62c2d2182 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -7,7 +7,7 @@ import os import pathlib import time -from typing import Any, Dict, List, Optional, Tuple, Type, Union +from typing import Any, Dict, List, Optional, Type from enum import Enum import click From 4ba96906db672033f04fe84b3b0df8f344421de7 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 12:56:29 +0100 Subject: [PATCH 12/16] fix isort --- miio/integrations/roborock/vacuum/vacuum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 62c2d2182..04af74832 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -7,8 +7,8 @@ import os import pathlib import time -from typing import Any, Dict, List, Optional, Type from enum import Enum +from typing import Any, Dict, List, Optional, Type import click import pytz From e79c236b9f743c185f3d94264398447742a966ab Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 13:00:55 +0100 Subject: [PATCH 13/16] fix docformatter --- miio/integrations/roborock/vacuum/vacuumcontainers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index 6576f92a6..bcd7f3905 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -642,7 +642,6 @@ def __init__(self, data: Dict[str, Any]) -> None: setattr(self, f"start_{map_id}", self.data[map_id].start) def __repr__(self): - s = f"<{self.__class__.__name__}" for map_id in self.data: name = f"CleanDetails_{map_id}" From dc78d5af3a5a41c9bf7950d1fde28d0c5e6bb3b2 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 13:25:49 +0100 Subject: [PATCH 14/16] fix mypy --- miio/integrations/roborock/vacuum/vacuum.py | 6 ++++-- miio/integrations/roborock/vacuum/vacuumcontainers.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 04af74832..90e70db4d 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -532,7 +532,8 @@ def last_clean_details(self, skip_cache=False) -> Optional[CleaningDetails]: Returns None if there has been no cleanups. """ if self._clean_history is None or skip_cache: - self._clean_history = self.clean_history() + self.clean_history() + assert isinstance(self._clean_history, CleaningSummary) if not self._clean_history.ids: return None @@ -550,7 +551,8 @@ def last_clean_all_floor(self, skip_cache=False) -> FloorCleanDetails: Returns None if there has been no cleanups for that floor. """ if self._clean_history is None or skip_cache: - self._clean_history = self.clean_history() + self.clean_history() + assert isinstance(self._clean_history, CleaningSummary) map_ids = self.get_maps().map_id_list diff --git a/miio/integrations/roborock/vacuum/vacuumcontainers.py b/miio/integrations/roborock/vacuum/vacuumcontainers.py index bcd7f3905..3a0bce465 100644 --- a/miio/integrations/roborock/vacuum/vacuumcontainers.py +++ b/miio/integrations/roborock/vacuum/vacuumcontainers.py @@ -630,7 +630,7 @@ def complete(self) -> bool: class FloorCleanDetails(DeviceStatus): """Contains details about a last cleaning run per floor.""" - def __init__(self, data: Dict[str, Any]) -> None: + def __init__(self, data: Dict[int, Any]) -> None: self.data = data for map_id in self.data: @@ -667,7 +667,7 @@ def sensors(self) -> Dict[str, SensorDescriptor]: id=f"FloorCleanDetails.start_{map_id}", property=f"start_{map_id}", name=f"Floor {map_id} clean start", - type="sensor", + type=datetime, extras={ "icon": "mdi:clock-time-twelve", "device_class": "timestamp", From a90c8f59955d26772e7e2ce8b6041c9195cd6330 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 13:33:46 +0100 Subject: [PATCH 15/16] fix linting --- miio/integrations/roborock/vacuum/vacuum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 90e70db4d..08797c030 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -533,7 +533,7 @@ def last_clean_details(self, skip_cache=False) -> Optional[CleaningDetails]: """ if self._clean_history is None or skip_cache: self.clean_history() - assert isinstance(self._clean_history, CleaningSummary) + assert isinstance(self._clean_history, CleaningSummary) # nosec assert_used if not self._clean_history.ids: return None @@ -552,7 +552,7 @@ def last_clean_all_floor(self, skip_cache=False) -> FloorCleanDetails: """ if self._clean_history is None or skip_cache: self.clean_history() - assert isinstance(self._clean_history, CleaningSummary) + assert isinstance(self._clean_history, CleaningSummary) # nosec assert_used map_ids = self.get_maps().map_id_list From 99731d3042806b7b8ad9b99ba4b6bae999f65952 Mon Sep 17 00:00:00 2001 From: starkillerOG Date: Fri, 10 Feb 2023 13:44:27 +0100 Subject: [PATCH 16/16] fix black --- miio/integrations/roborock/vacuum/vacuum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/miio/integrations/roborock/vacuum/vacuum.py b/miio/integrations/roborock/vacuum/vacuum.py index 08797c030..7d1d411fd 100644 --- a/miio/integrations/roborock/vacuum/vacuum.py +++ b/miio/integrations/roborock/vacuum/vacuum.py @@ -533,7 +533,7 @@ def last_clean_details(self, skip_cache=False) -> Optional[CleaningDetails]: """ if self._clean_history is None or skip_cache: self.clean_history() - assert isinstance(self._clean_history, CleaningSummary) # nosec assert_used + assert isinstance(self._clean_history, CleaningSummary) # nosec assert_used if not self._clean_history.ids: return None @@ -552,7 +552,7 @@ def last_clean_all_floor(self, skip_cache=False) -> FloorCleanDetails: """ if self._clean_history is None or skip_cache: self.clean_history() - assert isinstance(self._clean_history, CleaningSummary) # nosec assert_used + assert isinstance(self._clean_history, CleaningSummary) # nosec assert_used map_ids = self.get_maps().map_id_list