2020from roborock .exceptions import RoborockDeviceBusy , RoborockException
2121from roborock .roborock_typing import RoborockCommand
2222
23+ from .map_content import MapContent , MapContentTrait
2324from .maps import MapsTrait
2425from .rooms import RoomsTrait
2526from .status import StatusTrait
@@ -38,6 +39,7 @@ def __init__(
3839 self ,
3940 status_trait : StatusTrait ,
4041 maps_trait : MapsTrait ,
42+ map_content : MapContentTrait ,
4143 rooms_trait : RoomsTrait ,
4244 cache : Cache ,
4345 ) -> None :
@@ -59,9 +61,11 @@ def __init__(
5961 super ().__init__ ()
6062 self ._status_trait = status_trait
6163 self ._maps_trait = maps_trait
64+ self ._map_content = map_content
6265 self ._rooms_trait = rooms_trait
6366 self ._cache = cache
6467 self ._home_map_info : dict [int , CombinedMapInfo ] | None = None
68+ self ._home_map_content : dict [int , MapContent ] | None = None
6569
6670 async def discover_home (self ) -> None :
6771 """Iterate through all maps to discover rooms and cache them.
@@ -75,10 +79,18 @@ async def discover_home(self) -> None:
7579 After discovery, the home cache will be populated and can be accessed via the `home_map_info` property.
7680 """
7781 cache_data = await self ._cache .get ()
78- if cache_data .home_map_info :
82+ if cache_data .home_map_info and cache_data . home_map_content :
7983 _LOGGER .debug ("Home cache already populated, skipping discovery" )
8084 self ._home_map_info = cache_data .home_map_info
81- return
85+ try :
86+ self ._home_map_content = {
87+ k : self ._map_content .parse_map_content (v ) for k , v in cache_data .home_map_content .items ()
88+ }
89+ except (ValueError , RoborockException ) as ex :
90+ _LOGGER .warning ("Failed to parse cached home map content, will re-discover: %s" , ex )
91+ self ._home_map_content = {}
92+ else :
93+ return
8294
8395 if self ._status_trait .state == RoborockStateCode .cleaning :
8496 raise RoborockDeviceBusy ("Cannot perform home discovery while the device is cleaning" )
@@ -87,9 +99,9 @@ async def discover_home(self) -> None:
8799 if self ._maps_trait .current_map_info is None :
88100 raise RoborockException ("Cannot perform home discovery without current map info" )
89101
90- home_map_info = await self ._build_home_map_info ()
102+ home_map_info , home_map_content = await self ._build_home_map_info ()
91103 _LOGGER .debug ("Home discovery complete, caching data for %d maps" , len (home_map_info ))
92- await self ._update_home_map_info (home_map_info )
104+ await self ._update_home_cache (home_map_info , home_map_content )
93105
94106 async def _refresh_map_info (self , map_info ) -> CombinedMapInfo :
95107 """Collect room data for a specific map and return CombinedMapInfo."""
@@ -100,9 +112,19 @@ async def _refresh_map_info(self, map_info) -> CombinedMapInfo:
100112 rooms = self ._rooms_trait .rooms or [],
101113 )
102114
103- async def _build_home_map_info (self ) -> dict [int , CombinedMapInfo ]:
104- """Perform the actual discovery and caching of home data."""
115+ async def _refresh_map_content (self ) -> MapContent :
116+ """Refresh the map content trait to get the latest map data."""
117+ await self ._map_content .refresh ()
118+ return MapContent (
119+ image_content = self ._map_content .image_content ,
120+ map_data = self ._map_content .map_data ,
121+ raw_api_response = self ._map_content .raw_api_response ,
122+ )
123+
124+ async def _build_home_map_info (self ) -> tuple [dict [int , CombinedMapInfo ], dict [int , MapContent ]]:
125+ """Perform the actual discovery and caching of home map info and content."""
105126 home_map_info : dict [int , CombinedMapInfo ] = {}
127+ home_map_content : dict [int , MapContent ] = {}
106128
107129 # Sort map_info to process the current map last, reducing map switching.
108130 # False (non-original maps) sorts before True (original map). We ensure
@@ -120,9 +142,12 @@ async def _build_home_map_info(self) -> dict[int, CombinedMapInfo]:
120142 await self ._maps_trait .set_current_map (map_info .map_flag )
121143 await asyncio .sleep (MAP_SLEEP )
122144
123- map_data = await self ._refresh_map_info (map_info )
124- home_map_info [map_info .map_flag ] = map_data
125- return home_map_info
145+ map_content = await self ._refresh_map_content ()
146+ home_map_content [map_info .map_flag ] = map_content
147+
148+ combined_map_info = await self ._refresh_map_info (map_info )
149+ home_map_info [map_info .map_flag ] = combined_map_info
150+ return home_map_info , home_map_content
126151
127152 async def refresh (self ) -> Self :
128153 """Refresh current map's underlying map and room data, updating cache as needed.
@@ -141,13 +166,11 @@ async def refresh(self) -> Self:
141166 ) is None :
142167 raise RoborockException ("Cannot refresh home data without current map info" )
143168
169+ # Refresh the map content to ensure we have the latest image and object positions
170+ new_map_content = await self ._refresh_map_content ()
144171 # Refresh the current map's room data
145- current_map_data = self ._home_map_info .get (map_flag )
146- if current_map_data :
147- map_data = await self ._refresh_map_info (current_map_info )
148- if map_data != current_map_data :
149- await self ._update_home_map_info ({** self ._home_map_info , map_flag : map_data })
150-
172+ combined_map_info = await self ._refresh_map_info (current_map_info )
173+ await self ._update_current_map_cache (map_flag , combined_map_info , new_map_content )
151174 return self
152175
153176 @property
@@ -163,12 +186,36 @@ def current_map_data(self) -> CombinedMapInfo | None:
163186 return None
164187 return self ._home_map_info .get (current_map_flag )
165188
189+ @property
190+ def home_map_content (self ) -> dict [int , MapContent ] | None :
191+ """Returns the map content for all cached maps."""
192+ return self ._home_map_content
193+
166194 def _parse_response (self , response : common .V1ResponseData ) -> Self :
167195 """This trait does not parse responses directly."""
168196 raise NotImplementedError ("HomeTrait does not support direct command responses" )
169197
170- async def _update_home_map_info (self , home_map_info : dict [int , CombinedMapInfo ]) -> None :
198+ async def _update_home_cache (
199+ self , home_map_info : dict [int , CombinedMapInfo ], home_map_content : dict [int , MapContent ]
200+ ) -> None :
201+ """Update the entire home cache with new map info and content."""
171202 cache_data = await self ._cache .get ()
172203 cache_data .home_map_info = home_map_info
204+ cache_data .home_map_content = {k : v .raw_api_response for k , v in home_map_content .items () if v .raw_api_response }
173205 await self ._cache .set (cache_data )
174206 self ._home_map_info = home_map_info
207+ self ._home_map_content = home_map_content
208+
209+ async def _update_current_map_cache (
210+ self , map_flag : int , map_info : CombinedMapInfo , map_content : MapContent
211+ ) -> None :
212+ """Update the cache for the current map only."""
213+ cache_data = await self ._cache .get ()
214+ cache_data .home_map_info [map_flag ] = map_info
215+ if map_content .raw_api_response :
216+ cache_data .home_map_content [map_flag ] = map_content .raw_api_response
217+ await self ._cache .set (cache_data )
218+ if self ._home_map_info is None or self ._home_map_content is None :
219+ raise RoborockException ("Home cache is not initialized, cannot update current map cache" )
220+ self ._home_map_info [map_flag ] = map_info
221+ self ._home_map_content [map_flag ] = map_content
0 commit comments