roborock.devices.traits.v1.maps
Trait for managing maps and room mappings on Roborock devices.
New datatypes are introduced here to manage the additional information associated with maps and rooms, such as map names and room names. These override the base container datatypes to add additional fields.
1"""Trait for managing maps and room mappings on Roborock devices. 2 3New datatypes are introduced here to manage the additional information associated 4with maps and rooms, such as map names and room names. These override the 5base container datatypes to add additional fields. 6""" 7 8import logging 9 10from roborock.data import MultiMapsList, MultiMapsListMapInfo 11from roborock.devices.traits.v1 import common 12from roborock.roborock_typing import RoborockCommand 13 14from .status import StatusTrait 15 16_LOGGER = logging.getLogger(__name__) 17 18 19class MultiMapsListConverter(common.V1TraitDataConverter): 20 """Converters responses to MultiMapsList.""" 21 22 def convert(self, response: common.V1ResponseData) -> MultiMapsList: 23 """Parse the response from the device into a MapsTrait instance. 24 25 This overrides the base implementation to handle the specific 26 response format for the multi maps list. This is needed because we have 27 a custom constructor that requires the StatusTrait. 28 """ 29 if not isinstance(response, list): 30 raise ValueError(f"Unexpected MapsTrait response format: {response!r}") 31 response = response[0] 32 if not isinstance(response, dict): 33 raise ValueError(f"Unexpected MapsTrait response format: {response!r}") 34 return MultiMapsList.from_dict(response) 35 36 37@common.mqtt_rpc_channel 38class MapsTrait(MultiMapsList, common.V1TraitMixin): 39 """Trait for managing the maps of Roborock devices. 40 41 A device may have multiple maps, each identified by a unique map_flag. 42 Each map can have multiple rooms associated with it, in a `RoomMapping`. 43 44 The MapsTrait depends on the StatusTrait to determine the currently active 45 map. It is the responsibility of the caller to ensure that the StatusTrait 46 is up to date before using this trait. However, there is a possibility of 47 races if another client changes the current map between the time the 48 StatusTrait is refreshed and when the MapsTrait is used. This is mitigated 49 by the fact that the map list is unlikely to change frequently, and the 50 current map is only changed when the user explicitly switches maps. 51 """ 52 53 command = RoborockCommand.GET_MULTI_MAPS_LIST 54 converter = MultiMapsListConverter() 55 56 def __init__(self, status_trait: StatusTrait) -> None: 57 """Initialize the MapsTrait. 58 59 We keep track of the StatusTrait to ensure we have the latest 60 status information when dealing with maps. 61 """ 62 super().__init__() 63 self._status_trait = status_trait 64 65 @property 66 def current_map(self) -> int | None: 67 """Returns the currently active map (map_flag), if available.""" 68 return self._status_trait.current_map 69 70 @property 71 def current_map_info(self) -> MultiMapsListMapInfo | None: 72 """Returns the currently active map info, if available.""" 73 if (current_map := self.current_map) is None or self.map_info is None: 74 return None 75 for map_info in self.map_info: 76 if map_info.map_flag == current_map: 77 return map_info 78 return None 79 80 async def set_current_map(self, map_flag: int) -> None: 81 """Update the current map of the device by it's map_flag id.""" 82 await self.rpc_channel.send_command(RoborockCommand.LOAD_MULTI_MAP, params=[map_flag]) 83 # Refresh our status to make sure it reflects the new map 84 await self._status_trait.refresh()
20class MultiMapsListConverter(common.V1TraitDataConverter): 21 """Converters responses to MultiMapsList.""" 22 23 def convert(self, response: common.V1ResponseData) -> MultiMapsList: 24 """Parse the response from the device into a MapsTrait instance. 25 26 This overrides the base implementation to handle the specific 27 response format for the multi maps list. This is needed because we have 28 a custom constructor that requires the StatusTrait. 29 """ 30 if not isinstance(response, list): 31 raise ValueError(f"Unexpected MapsTrait response format: {response!r}") 32 response = response[0] 33 if not isinstance(response, dict): 34 raise ValueError(f"Unexpected MapsTrait response format: {response!r}") 35 return MultiMapsList.from_dict(response)
Converters responses to MultiMapsList.
def
convert( self, response: dict | list | int | str) -> roborock.data.v1.v1_containers.MultiMapsList:
23 def convert(self, response: common.V1ResponseData) -> MultiMapsList: 24 """Parse the response from the device into a MapsTrait instance. 25 26 This overrides the base implementation to handle the specific 27 response format for the multi maps list. This is needed because we have 28 a custom constructor that requires the StatusTrait. 29 """ 30 if not isinstance(response, list): 31 raise ValueError(f"Unexpected MapsTrait response format: {response!r}") 32 response = response[0] 33 if not isinstance(response, dict): 34 raise ValueError(f"Unexpected MapsTrait response format: {response!r}") 35 return MultiMapsList.from_dict(response)
Parse the response from the device into a MapsTrait instance.
This overrides the base implementation to handle the specific response format for the multi maps list. This is needed because we have a custom constructor that requires the StatusTrait.