33import logging
44from dataclasses import dataclass
55
6- from roborock .data import HomeData , NamedRoomMapping , RoborockBase
6+ from roborock .data import HomeData , HomeDataRoom , NamedRoomMapping , RoborockBase
77from roborock .devices .traits .v1 import common
88from roborock .roborock_typing import RoborockCommand
99from roborock .web_api import UserWebApiClient
@@ -36,7 +36,7 @@ def __init__(self, home_data: HomeData, web_api: UserWebApiClient) -> None:
3636 super ().__init__ ()
3737 self ._home_data = home_data
3838 self ._web_api = web_api
39- self ._seen_unknown_room_iot_ids : set [str ] = set ()
39+ self ._discovered_iot_ids : set [str ] = set ()
4040
4141 async def refresh (self ) -> None :
4242 """Refresh room mappings and backfill unknown room names from the web API."""
@@ -45,47 +45,39 @@ async def refresh(self) -> None:
4545 raise ValueError (f"Unexpected RoomsTrait response format: { response !r} " )
4646
4747 segment_map = _extract_segment_map (response )
48- await self ._populate_missing_home_data_rooms (segment_map )
49-
50- new_data = self ._parse_response (response , segment_map )
48+ # Track all iot ids seen before. Refresh the room list when new ids are found.
49+ new_iot_ids = set (segment_map .values ()) - set (self ._home_data .rooms_map .keys ())
50+ if new_iot_ids - self ._discovered_iot_ids :
51+ _LOGGER .debug ("Refreshing room list to discover new room names" )
52+ if updated_rooms := await self ._refresh_rooms ():
53+ _LOGGER .debug ("Updating rooms: %s" , list (updated_rooms ))
54+ self ._home_data .rooms = updated_rooms
55+ self ._discovered_iot_ids .update (new_iot_ids )
56+
57+ new_data = self ._parse_rooms (segment_map , self ._home_data .rooms_name_map )
5158 self ._update_trait_values (new_data )
5259 _LOGGER .debug ("Refreshed %s: %s" , self .__class__ .__name__ , new_data )
5360
54- @property
55- def _iot_id_room_name_map (self ) -> dict [str , str ]:
56- """Returns a dictionary of Room IOT IDs to room names."""
57- return {str (room .id ): room .name for room in self ._home_data .rooms or ()}
58-
59- def _parse_response (self , response : common .V1ResponseData , segment_map : dict [int , str ] | None = None ) -> Rooms :
61+ @staticmethod
62+ def _parse_rooms (
63+ segment_map : dict [int , str ],
64+ name_map : dict [str , str ],
65+ ) -> Rooms :
6066 """Parse the response from the device into a list of NamedRoomMapping."""
61- if not isinstance (response , list ):
62- raise ValueError (f"Unexpected RoomsTrait response format: { response !r} " )
63- if segment_map is None :
64- segment_map = _extract_segment_map (response )
65- name_map = self ._iot_id_room_name_map
6667 return Rooms (
6768 rooms = [
68- NamedRoomMapping (segment_id = segment_id , iot_id = iot_id , name = name_map .get (iot_id , f"Room { segment_id } " ))
69+ NamedRoomMapping (segment_id = segment_id , iot_id = iot_id , raw_name = name_map .get (iot_id ))
6970 for segment_id , iot_id in segment_map .items ()
7071 ]
7172 )
7273
73- async def _populate_missing_home_data_rooms (self , segment_map : dict [int , str ]) -> None :
74- """Load missing room names into home data for newly-seen unknown room ids."""
75- missing_room_iot_ids = set (segment_map .values ()) - set (self ._iot_id_room_name_map .keys ())
76- new_missing_room_iot_ids = missing_room_iot_ids - self ._seen_unknown_room_iot_ids
77- if not new_missing_room_iot_ids :
78- return
79-
74+ async def _refresh_rooms (self ) -> list [HomeDataRoom ]:
75+ """Fetch the latest rooms from the web API."""
8076 try :
81- web_rooms = await self ._web_api .get_rooms ()
77+ return await self ._web_api .get_rooms ()
8278 except Exception :
8379 _LOGGER .debug ("Failed to fetch rooms from web API" , exc_info = True )
84- else :
85- if isinstance (web_rooms , list ) and web_rooms :
86- self ._home_data .rooms = web_rooms
87-
88- self ._seen_unknown_room_iot_ids .update (missing_room_iot_ids )
80+ return []
8981
9082
9183def _extract_segment_map (response : list ) -> dict [int , str ]:
0 commit comments