python-roborock 5.14.2__py3-none-any.whl → 5.15.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_roborock-5.14.2.dist-info → python_roborock-5.15.0.dist-info}/METADATA +1 -1
- {python_roborock-5.14.2.dist-info → python_roborock-5.15.0.dist-info}/RECORD +8 -8
- roborock/devices/traits/v1/__init__.py +1 -1
- roborock/devices/traits/v1/rooms.py +20 -4
- roborock/web_api.py +31 -0
- {python_roborock-5.14.2.dist-info → python_roborock-5.15.0.dist-info}/WHEEL +0 -0
- {python_roborock-5.14.2.dist-info → python_roborock-5.15.0.dist-info}/entry_points.txt +0 -0
- {python_roborock-5.14.2.dist-info → python_roborock-5.15.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.15.0
|
|
4
4
|
Summary: A package to control Roborock vacuums.
|
|
5
5
|
Project-URL: Repository, https://github.com/python-roborock/python-roborock
|
|
6
6
|
Project-URL: Documentation, https://python-roborock.readthedocs.io/
|
|
@@ -11,7 +11,7 @@ roborock/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
11
11
|
roborock/roborock_message.py,sha256=BPDT_uzCeD4L_4LottCMeft1kYmYPoG9ktcqqj0SYhQ,6466
|
|
12
12
|
roborock/roborock_typing.py,sha256=Rwx0c0oZCMY-4O8VMLnFSO_OUNb_D59cyG_ktZTZoZI,17134
|
|
13
13
|
roborock/util.py,sha256=mjw329ujLjoWPPAr9mG0VZstaVL06dmVvNnYACB-Pxk,1650
|
|
14
|
-
roborock/web_api.py,sha256=
|
|
14
|
+
roborock/web_api.py,sha256=MDJ9OZr1hPaKRYxfU033DDrFEOoXm4wml0yhSJCSEyA,36040
|
|
15
15
|
roborock/data/__init__.py,sha256=DikqaVM7VPVddkBNkHSss5zb1_iKB7GYmc2GiHoMAkA,257
|
|
16
16
|
roborock/data/code_mappings.py,sha256=CzD9q-VuPy70pDZdjZ6kgK4vcGdzNGV3Eo5z9QGOYp0,8399
|
|
17
17
|
roborock/data/containers.py,sha256=-b6H2snGQTzsJSsctgil6sx8rLtCDihTTzdkxcFRdlE,16489
|
|
@@ -56,7 +56,7 @@ roborock/devices/traits/b01/q7/__init__.py,sha256=jxvN9KVrqQPgwNjIbseGME2v8DX-ry
|
|
|
56
56
|
roborock/devices/traits/b01/q7/clean_summary.py,sha256=Tod29LUHBsOS0XL8SU1SdBQEHWTCifGZVCwSWGhYpy8,2933
|
|
57
57
|
roborock/devices/traits/b01/q7/map.py,sha256=Zrvj8LNctIFksCBoiZVQ1x4hgG3wwp1jqPY-If__JXw,1489
|
|
58
58
|
roborock/devices/traits/b01/q7/map_content.py,sha256=rI21-kMmIgf1TY98HXrWG_4rEEs9qzdYBm7RTU47yN4,3519
|
|
59
|
-
roborock/devices/traits/v1/__init__.py,sha256=
|
|
59
|
+
roborock/devices/traits/v1/__init__.py,sha256=yUa3oN5CZtuVh-fst8FlstpCy1XnS3q42oPlQG9fFYw,15616
|
|
60
60
|
roborock/devices/traits/v1/child_lock.py,sha256=NeaPqcEoBRXvEzKZGonkyINkwCBOK3xa4zSWvJW66kA,1161
|
|
61
61
|
roborock/devices/traits/v1/clean_summary.py,sha256=2uDl3Tg6H9INf7HTEPPat_PBgodoWeX_ko5MJgWggn8,4625
|
|
62
62
|
roborock/devices/traits/v1/command.py,sha256=2yNyCF_EDPkLE_vK6IN5VB8ZVypwrrwKTByCdQzJs3c,1494
|
|
@@ -71,7 +71,7 @@ roborock/devices/traits/v1/led_status.py,sha256=qUY6GgC-RSXCAKlL2D0_FBO-1xwi2eU3
|
|
|
71
71
|
roborock/devices/traits/v1/map_content.py,sha256=w_34H6ItiYm98QFOmEDCP0AvTBWAFVuB-uz5rmgBRwI,3175
|
|
72
72
|
roborock/devices/traits/v1/maps.py,sha256=JdOjJCeJ6iAH85pNHKHbVGlD-zOrha9h6XAh7IDeQr8,3468
|
|
73
73
|
roborock/devices/traits/v1/network_info.py,sha256=CX9-ye2Zb_8lAWPGvegXWSOguxMY2K0xO-2OmWmE67o,2291
|
|
74
|
-
roborock/devices/traits/v1/rooms.py,sha256=
|
|
74
|
+
roborock/devices/traits/v1/rooms.py,sha256=PKNEvzL_Pk5pxGpiMC-XgGpgWVRjivMw_yv7vpGlz3s,6221
|
|
75
75
|
roborock/devices/traits/v1/routines.py,sha256=BfktlpnyDjD2DB3zBDS5BnmjZPE38aHa-wjMontPnik,931
|
|
76
76
|
roborock/devices/traits/v1/smart_wash_params.py,sha256=fAhJpMgUUP1kJcfEAAPeD3anMmCsuX7I1SEoUrUgfjE,504
|
|
77
77
|
roborock/devices/traits/v1/status.py,sha256=g71kUSZ5XKMSF9mEH2QGr-d9L9ecyUGB1M-LKiKz-js,3915
|
|
@@ -97,8 +97,8 @@ roborock/protocols/a01_protocol.py,sha256=JCIhUuVNamcENu0gtZR2x8rBz6dpAZLcbA-NQg
|
|
|
97
97
|
roborock/protocols/b01_q10_protocol.py,sha256=SimfXpQotkEkb58ThZq7xa7fCxPxF-hrpAJcRKI-yZE,3407
|
|
98
98
|
roborock/protocols/b01_q7_protocol.py,sha256=o8repRrxhxknzspsg1K27ds643rs87ilWXbj8RJtOCs,4619
|
|
99
99
|
roborock/protocols/v1_protocol.py,sha256=uA-EMXd1AUBAXjkjAm0VxZlPLre0v2X9Kei5UqyPzaY,11141
|
|
100
|
-
python_roborock-5.
|
|
101
|
-
python_roborock-5.
|
|
102
|
-
python_roborock-5.
|
|
103
|
-
python_roborock-5.
|
|
104
|
-
python_roborock-5.
|
|
100
|
+
python_roborock-5.15.0.dist-info/METADATA,sha256=f68xtyNkzC0wrSIQUY2b9LWuqDe76dAKdII1KU4ku_Q,4963
|
|
101
|
+
python_roborock-5.15.0.dist-info/WHEEL,sha256=mffPy8wBnZQn2VnJUU5jE99KsxaSfiyMHV9Yt0aLVxs,87
|
|
102
|
+
python_roborock-5.15.0.dist-info/entry_points.txt,sha256=EvC1nMqi9ZXKgZnqlNXA33v_3nzgPNjnM0mzWlrehnY,47
|
|
103
|
+
python_roborock-5.15.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
104
|
+
python_roborock-5.15.0.dist-info/RECORD,,
|
|
@@ -199,7 +199,7 @@ class PropertiesApi(Trait):
|
|
|
199
199
|
self.device_features = DeviceFeaturesTrait(product, self._device_cache)
|
|
200
200
|
self.status = StatusTrait(self.device_features, region=self._region)
|
|
201
201
|
self.consumables = ConsumableTrait()
|
|
202
|
-
self.rooms = RoomsTrait(home_data, web_api)
|
|
202
|
+
self.rooms = RoomsTrait(home_data, device_uid, web_api)
|
|
203
203
|
self.maps = MapsTrait(self.status)
|
|
204
204
|
self.map_content = MapContentTrait(map_parser_config)
|
|
205
205
|
self.home = HomeTrait(self.status, self.maps, self.map_content, self.rooms, self._device_cache)
|
|
@@ -84,12 +84,21 @@ class RoomsTrait(Rooms, common.V1TraitMixin):
|
|
|
84
84
|
command = RoborockCommand.GET_ROOM_MAPPING
|
|
85
85
|
converter = RoomsConverter()
|
|
86
86
|
|
|
87
|
-
def __init__(self, home_data: HomeData, web_api: UserWebApiClient) -> None:
|
|
87
|
+
def __init__(self, home_data: HomeData, device_uid: str, web_api: UserWebApiClient) -> None:
|
|
88
88
|
"""Initialize the RoomsTrait."""
|
|
89
89
|
super().__init__()
|
|
90
90
|
self._home_data = home_data
|
|
91
|
+
self._device_uid = device_uid
|
|
92
|
+
self._shared_device_uid = next(
|
|
93
|
+
(device.duid for device in home_data.received_devices if device.duid == device_uid), None
|
|
94
|
+
)
|
|
91
95
|
self._web_api = web_api
|
|
92
96
|
self._discovered_iot_ids: set[str] = set()
|
|
97
|
+
self._room_names: dict[str, str] = dict(home_data.rooms_name_map)
|
|
98
|
+
|
|
99
|
+
@property
|
|
100
|
+
def _room_name_map(self) -> dict[str, str]:
|
|
101
|
+
return self._room_names
|
|
93
102
|
|
|
94
103
|
async def refresh(self) -> None:
|
|
95
104
|
"""Refresh room mappings and backfill unknown room names from the web API."""
|
|
@@ -104,12 +113,14 @@ class RoomsTrait(Rooms, common.V1TraitMixin):
|
|
|
104
113
|
|
|
105
114
|
segment_map = RoomsConverter.extract_segment_map(response)
|
|
106
115
|
# Track all iot ids seen before. Refresh the room list when new ids are found.
|
|
107
|
-
new_iot_ids = set(segment_map.values()) - set(self.
|
|
116
|
+
new_iot_ids = set(segment_map.values()) - set(self._room_name_map.keys())
|
|
108
117
|
if new_iot_ids - self._discovered_iot_ids:
|
|
109
118
|
_LOGGER.debug("Refreshing room list to discover new room names")
|
|
110
119
|
if updated_rooms := await self._refresh_rooms():
|
|
111
120
|
_LOGGER.debug("Updating rooms: %s", list(updated_rooms))
|
|
112
|
-
self.
|
|
121
|
+
self._room_names = {room.iot_id: room.name for room in updated_rooms}
|
|
122
|
+
if self._shared_device_uid is None:
|
|
123
|
+
self._home_data.rooms = updated_rooms
|
|
113
124
|
self._discovered_iot_ids.update(new_iot_ids)
|
|
114
125
|
try:
|
|
115
126
|
rooms = self.converter.convert(response)
|
|
@@ -121,12 +132,17 @@ class RoomsTrait(Rooms, common.V1TraitMixin):
|
|
|
121
132
|
inner_error=err,
|
|
122
133
|
) from err
|
|
123
134
|
|
|
124
|
-
rooms = rooms.with_room_names(self.
|
|
135
|
+
rooms = rooms.with_room_names(self._room_name_map)
|
|
125
136
|
common.merge_trait_values(self, rooms)
|
|
126
137
|
|
|
127
138
|
async def _refresh_rooms(self) -> list[HomeDataRoom]:
|
|
128
139
|
"""Fetch the latest rooms from the web API."""
|
|
129
140
|
try:
|
|
141
|
+
if self._shared_device_uid is not None:
|
|
142
|
+
rooms_by_id = {room.iot_id: room for room in self._home_data.rooms}
|
|
143
|
+
shared_rooms = await self._web_api.get_shared_device_rooms(self._shared_device_uid)
|
|
144
|
+
rooms_by_id.update({room.iot_id: room for room in shared_rooms})
|
|
145
|
+
return list(rooms_by_id.values())
|
|
130
146
|
return await self._web_api.get_rooms()
|
|
131
147
|
except Exception:
|
|
132
148
|
_LOGGER.debug("Failed to fetch rooms from web API", exc_info=True)
|
roborock/web_api.py
CHANGED
|
@@ -558,6 +558,33 @@ class RoborockApiClient:
|
|
|
558
558
|
else:
|
|
559
559
|
raise RoborockException("home_response result was an unexpected type")
|
|
560
560
|
|
|
561
|
+
async def get_shared_device_rooms(self, user_data: UserData, device_id: str) -> list[HomeDataRoom]:
|
|
562
|
+
"""Fetch room names for a shared (received) device."""
|
|
563
|
+
rriot = user_data.rriot
|
|
564
|
+
if rriot is None:
|
|
565
|
+
raise RoborockException("rriot is none")
|
|
566
|
+
if rriot.r.a is None:
|
|
567
|
+
raise RoborockException("Missing field 'a' in rriot reference")
|
|
568
|
+
path = f"/user/deviceshare/query/{device_id}/rooms"
|
|
569
|
+
room_request = PreparedRequest(
|
|
570
|
+
rriot.r.a,
|
|
571
|
+
self.session,
|
|
572
|
+
{"Authorization": _get_hawk_authentication(rriot, path)},
|
|
573
|
+
)
|
|
574
|
+
room_response = await room_request.request("get", path)
|
|
575
|
+
if not room_response.get("success"):
|
|
576
|
+
raise RoborockException(room_response)
|
|
577
|
+
rooms = room_response.get("result")
|
|
578
|
+
if isinstance(rooms, list):
|
|
579
|
+
output_list = []
|
|
580
|
+
for room in rooms:
|
|
581
|
+
normalized_room = room
|
|
582
|
+
if isinstance(room, dict) and "id" not in room and "roomId" in room:
|
|
583
|
+
normalized_room = {**room, "id": room["roomId"]}
|
|
584
|
+
output_list.append(HomeDataRoom.from_dict(normalized_room))
|
|
585
|
+
return output_list
|
|
586
|
+
raise RoborockException("get_shared_device_rooms result was an unexpected type")
|
|
587
|
+
|
|
561
588
|
async def get_scenes(self, user_data: UserData, device_id: str) -> list[HomeDataScene]:
|
|
562
589
|
rriot = user_data.rriot
|
|
563
590
|
if rriot is None:
|
|
@@ -775,6 +802,10 @@ class UserWebApiClient:
|
|
|
775
802
|
self._unauthorized_hook()
|
|
776
803
|
raise
|
|
777
804
|
|
|
805
|
+
async def get_shared_device_rooms(self, device_id: str) -> list[HomeDataRoom]:
|
|
806
|
+
"""Fetch shared-device rooms using the API client."""
|
|
807
|
+
return await self._web_api.get_shared_device_rooms(self._user_data, device_id)
|
|
808
|
+
|
|
778
809
|
async def execute_routine(self, scene_id: int) -> None:
|
|
779
810
|
"""Execute a specific routine (scene) by its ID."""
|
|
780
811
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|