Skip to content

Commit 2b28659

Browse files
committed
fix: add rooms from map_info which is occassionally available
1 parent a69286f commit 2b28659

File tree

3 files changed

+109
-3
lines changed

3 files changed

+109
-3
lines changed

roborock/data/v1/v1_containers.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,14 @@ def __repr__(self) -> str:
543543
return _attr_repr(self)
544544

545545

546+
@dataclass
547+
class MultiMapsListRoom(RoborockBase):
548+
id: int | None = None
549+
tag: int | None = None
550+
iot_name_id: str | None = None
551+
iot_name: str | None = None
552+
553+
546554
@dataclass
547555
class MultiMapsListMapInfoBakMaps(RoborockBase):
548556
mapflag: Any | None = None
@@ -556,6 +564,7 @@ class MultiMapsListMapInfo(RoborockBase):
556564
add_time: Any | None = None
557565
length: Any | None = None
558566
bak_maps: list[MultiMapsListMapInfoBakMaps] | None = None
567+
rooms: list[MultiMapsListRoom] | None = None
559568

560569
@property
561570
def mapFlag(self) -> int:

roborock/devices/traits/v1/home.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import logging
2121
from typing import Self
2222

23-
from roborock.data import CombinedMapInfo, RoborockBase
23+
from roborock.data import CombinedMapInfo, NamedRoomMapping, RoborockBase
2424
from roborock.data.v1.v1_code_mappings import RoborockStateCode
2525
from roborock.devices.cache import DeviceCache
2626
from roborock.devices.traits.v1 import common
@@ -117,10 +117,31 @@ async def discover_home(self) -> None:
117117
async def _refresh_map_info(self, map_info) -> CombinedMapInfo:
118118
"""Collect room data for a specific map and return CombinedMapInfo."""
119119
await self._rooms_trait.refresh()
120+
121+
rooms: dict[int, NamedRoomMapping] = {}
122+
if map_info.rooms:
123+
# Not all vacuums resopnd with rooms inside map_info.
124+
for room in map_info.rooms:
125+
if room.id is not None and room.iot_name_id is not None:
126+
rooms[room.id] = NamedRoomMapping(
127+
segment_id=room.id,
128+
iot_id=room.iot_name_id,
129+
name=room.iot_name or "Unknown",
130+
)
131+
132+
# Add rooms from rooms_trait. If room already exists and rooms_trait has "Unknown", don't override.
133+
if self._rooms_trait.rooms:
134+
for room in self._rooms_trait.rooms:
135+
if room.segment_id is not None and room.name:
136+
if room.segment_id not in rooms or room.name != "Unknown":
137+
# Add the room to rooms if the room segment is not already in it
138+
# or if the room name isn't unknown.
139+
rooms[room.segment_id] = room
140+
120141
return CombinedMapInfo(
121142
map_flag=map_info.map_flag,
122143
name=map_info.name,
123-
rooms=self._rooms_trait.rooms or [],
144+
rooms=list(rooms.values()),
124145
)
125146

126147
async def _refresh_map_content(self) -> MapContent:

tests/devices/traits/v1/test_home.py

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
import pytest
88

9-
from roborock.data.containers import CombinedMapInfo
9+
from roborock.data.containers import CombinedMapInfo, NamedRoomMapping
1010
from roborock.data.v1.v1_code_mappings import RoborockStateCode
11+
from roborock.data.v1.v1_containers import MultiMapsListMapInfo, MultiMapsListRoom
1112
from roborock.devices.cache import DeviceCache, DeviceCacheData, InMemoryCache
1213
from roborock.devices.device import RoborockDevice
1314
from roborock.devices.traits.v1.home import HomeTrait
@@ -570,3 +571,78 @@ async def test_single_map_no_switching(
570571
if call[1].get("command") == RoborockCommand.LOAD_MULTI_MAP
571572
]
572573
assert len(load_map_calls) == 0
574+
575+
576+
async def test_refresh_map_info_room_override_and_addition_logic(
577+
home_trait: HomeTrait,
578+
rooms_trait: RoomsTrait,
579+
) -> None:
580+
"""Test the room override and addition logic in _refresh_map_info.
581+
582+
This test verifies:
583+
1. Room with "Unknown" does not override existing room from map_info
584+
2. Room with valid name overrides existing room from map_info
585+
3. Room with "Unknown" is added if not already in rooms
586+
4. Room with valid name is added if not already in rooms
587+
"""
588+
map_info = MultiMapsListMapInfo(
589+
map_flag=0,
590+
name="Test Map",
591+
rooms=[
592+
MultiMapsListRoom(
593+
id=16,
594+
iot_name_id="2362048",
595+
iot_name="Kitchen from map_info",
596+
),
597+
MultiMapsListRoom(
598+
id=19,
599+
iot_name_id="2362042",
600+
iot_name="Bedroom from map_info",
601+
),
602+
],
603+
)
604+
605+
# Mock rooms_trait to return multiple rooms covering all scenarios:
606+
# - segment_id 16 with "Unknown": exists in map_info, should NOT override
607+
# - segment_id 19 with valid name: exists in map_info, should override
608+
# - segment_id 17 with "Unknown": not in map_info, should be added
609+
# - segment_id 18 with valid name: not in map_info, should be added
610+
rooms_trait.rooms = [
611+
NamedRoomMapping(segment_id=16, iot_id="2362048", name="Unknown"), # Exists in map_info, should not override
612+
NamedRoomMapping(
613+
segment_id=19, iot_id="2362042", name="Updated Bedroom Name"
614+
), # Exists in map_info, should override
615+
NamedRoomMapping(segment_id=17, iot_id="2362044", name="Unknown"), # Not in map_info, should be added
616+
NamedRoomMapping(segment_id=18, iot_id="2362041", name="Example room 3"), # Not in map_info, should be added
617+
]
618+
619+
# Mock rooms_trait.refresh to prevent actual device calls
620+
with patch.object(rooms_trait, "refresh", new_callable=AsyncMock):
621+
result = await home_trait._refresh_map_info(map_info)
622+
623+
assert result.map_flag == 0
624+
assert result.name == "Test Map"
625+
assert len(result.rooms) == 4
626+
627+
# Sort rooms by segment_id for consistent assertions
628+
sorted_rooms = sorted(result.rooms, key=lambda r: r.segment_id)
629+
630+
# Room 16: from map_info, kept (not overridden by Unknown)
631+
assert sorted_rooms[0].segment_id == 16
632+
assert sorted_rooms[0].name == "Kitchen from map_info"
633+
assert sorted_rooms[0].iot_id == "2362048"
634+
635+
# Room 17: from rooms_trait with "Unknown", added because not in map_info
636+
assert sorted_rooms[1].segment_id == 17
637+
assert sorted_rooms[1].name == "Unknown"
638+
assert sorted_rooms[1].iot_id == "2362044"
639+
640+
# Room 18: from rooms_trait with valid name, added because not in map_info
641+
assert sorted_rooms[2].segment_id == 18
642+
assert sorted_rooms[2].name == "Example room 3"
643+
assert sorted_rooms[2].iot_id == "2362041"
644+
645+
# Room 19: from map_info, overridden by rooms_trait with valid name
646+
assert sorted_rooms[3].segment_id == 19
647+
assert sorted_rooms[3].name == "Updated Bedroom Name"
648+
assert sorted_rooms[3].iot_id == "2362042"

0 commit comments

Comments
 (0)