python-roborock 4.18.0__tar.gz → 4.19.0__tar.gz
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-4.18.0 → python_roborock-4.19.0}/PKG-INFO +1 -1
- {python_roborock-4.18.0 → python_roborock-4.19.0}/pyproject.toml +1 -1
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/__init__.py +1 -1
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/home.py +7 -6
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/rooms.py +46 -14
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/mqtt/roborock_session.py +17 -4
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/web_api.py +6 -2
- {python_roborock-4.18.0 → python_roborock-4.19.0}/.gitignore +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/LICENSE +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/README.md +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/broadcast_protocol.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/callbacks.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/cli.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/const.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q10/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q7/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/code_mappings.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/containers.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/dyad/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/dyad/dyad_containers.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/v1/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/v1/v1_clean_modes.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/v1/v1_code_mappings.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/v1/v1_containers.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/zeo/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/zeo/zeo_containers.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/device_features.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/README.md +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/cache.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/device.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/device_manager.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/file_cache.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/rpc/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/rpc/a01_channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/rpc/v1_channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/a01/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/command.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/common.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/status.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q7/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/traits_mixin.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/child_lock.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/command.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/common.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/consumeable.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/device_features.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/led_status.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/map_content.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/maps.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/network_info.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/routines.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/status.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/volume.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/transport/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/transport/channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/transport/local_channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/transport/mqtt_channel.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/diagnostics.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/exceptions.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/map/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/map/map_parser.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/mqtt/health_manager.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/protocol.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/protocols/__init__.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/protocols/b01_q10_protocol.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/protocols/b01_q7_protocol.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/py.typed +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/roborock_message.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/util.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.19.0
|
|
4
4
|
Summary: A package to control Roborock vacuums.
|
|
5
5
|
Project-URL: Repository, https://github.com/humbertogontijo/python-roborock
|
|
6
6
|
Project-URL: Documentation, https://python-roborock.readthedocs.io/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-roborock"
|
|
3
|
-
version = "4.
|
|
3
|
+
version = "4.19.0"
|
|
4
4
|
description = "A package to control Roborock vacuums."
|
|
5
5
|
authors = [{ name = "humbertogontijo", email = "humbertogontijo@users.noreply.github.com" }, {name="Lash-L"}, {name="allenporter"}]
|
|
6
6
|
requires-python = ">=3.11, <4"
|
|
@@ -193,7 +193,7 @@ class PropertiesApi(Trait):
|
|
|
193
193
|
self.device_features = DeviceFeaturesTrait(product, self._device_cache)
|
|
194
194
|
self.status = StatusTrait(self.device_features, region=self._region)
|
|
195
195
|
self.consumables = ConsumableTrait()
|
|
196
|
-
self.rooms = RoomsTrait(home_data)
|
|
196
|
+
self.rooms = RoomsTrait(home_data, web_api)
|
|
197
197
|
self.maps = MapsTrait(self.status)
|
|
198
198
|
self.map_content = MapContentTrait(map_parser_config)
|
|
199
199
|
self.home = HomeTrait(self.status, self.maps, self.map_content, self.rooms, self._device_cache)
|
|
@@ -120,22 +120,23 @@ class HomeTrait(RoborockBase, common.V1TraitMixin):
|
|
|
120
120
|
|
|
121
121
|
rooms: dict[int, NamedRoomMapping] = {}
|
|
122
122
|
if map_info.rooms:
|
|
123
|
-
# Not all vacuums
|
|
123
|
+
# Not all vacuums respond with rooms inside map_info.
|
|
124
|
+
# If we can determine if all vacuums will return everything with get_rooms, we could remove this step.
|
|
124
125
|
for room in map_info.rooms:
|
|
125
126
|
if room.id is not None and room.iot_name_id is not None:
|
|
126
127
|
rooms[room.id] = NamedRoomMapping(
|
|
127
128
|
segment_id=room.id,
|
|
128
129
|
iot_id=room.iot_name_id,
|
|
129
|
-
name=room.iot_name or "
|
|
130
|
+
name=room.iot_name or f"Room {room.id}",
|
|
130
131
|
)
|
|
131
132
|
|
|
132
|
-
# Add rooms from rooms_trait.
|
|
133
|
+
# Add rooms from rooms_trait.
|
|
134
|
+
# Keep existing names from map_info unless they are fallback names.
|
|
133
135
|
if self._rooms_trait.rooms:
|
|
134
136
|
for room in self._rooms_trait.rooms:
|
|
135
137
|
if room.segment_id is not None and room.name:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
# or if the room name isn't unknown.
|
|
138
|
+
existing_room = rooms.get(room.segment_id)
|
|
139
|
+
if existing_room is None or existing_room.name == f"Room {room.segment_id}":
|
|
139
140
|
rooms[room.segment_id] = room
|
|
140
141
|
|
|
141
142
|
return CombinedMapInfo(
|
|
@@ -6,11 +6,10 @@ from dataclasses import dataclass
|
|
|
6
6
|
from roborock.data import HomeData, NamedRoomMapping, RoborockBase
|
|
7
7
|
from roborock.devices.traits.v1 import common
|
|
8
8
|
from roborock.roborock_typing import RoborockCommand
|
|
9
|
+
from roborock.web_api import UserWebApiClient
|
|
9
10
|
|
|
10
11
|
_LOGGER = logging.getLogger(__name__)
|
|
11
12
|
|
|
12
|
-
_DEFAULT_NAME = "Unknown"
|
|
13
|
-
|
|
14
13
|
|
|
15
14
|
@dataclass
|
|
16
15
|
class Rooms(RoborockBase):
|
|
@@ -32,36 +31,69 @@ class RoomsTrait(Rooms, common.V1TraitMixin):
|
|
|
32
31
|
|
|
33
32
|
command = RoborockCommand.GET_ROOM_MAPPING
|
|
34
33
|
|
|
35
|
-
def __init__(self, home_data: HomeData) -> None:
|
|
34
|
+
def __init__(self, home_data: HomeData, web_api: UserWebApiClient) -> None:
|
|
36
35
|
"""Initialize the RoomsTrait."""
|
|
37
36
|
super().__init__()
|
|
38
37
|
self._home_data = home_data
|
|
38
|
+
self._web_api = web_api
|
|
39
|
+
self._seen_unknown_room_iot_ids: set[str] = set()
|
|
40
|
+
|
|
41
|
+
async def refresh(self) -> None:
|
|
42
|
+
"""Refresh room mappings and backfill unknown room names from the web API."""
|
|
43
|
+
response = await self.rpc_channel.send_command(self.command)
|
|
44
|
+
if not isinstance(response, list):
|
|
45
|
+
raise ValueError(f"Unexpected RoomsTrait response format: {response!r}")
|
|
46
|
+
|
|
47
|
+
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)
|
|
51
|
+
self._update_trait_values(new_data)
|
|
52
|
+
_LOGGER.debug("Refreshed %s: %s", self.__class__.__name__, new_data)
|
|
39
53
|
|
|
40
54
|
@property
|
|
41
55
|
def _iot_id_room_name_map(self) -> dict[str, str]:
|
|
42
56
|
"""Returns a dictionary of Room IOT IDs to room names."""
|
|
43
57
|
return {str(room.id): room.name for room in self._home_data.rooms or ()}
|
|
44
58
|
|
|
45
|
-
def _parse_response(self, response: common.V1ResponseData) -> Rooms:
|
|
59
|
+
def _parse_response(self, response: common.V1ResponseData, segment_map: dict[int, str] | None = None) -> Rooms:
|
|
46
60
|
"""Parse the response from the device into a list of NamedRoomMapping."""
|
|
47
61
|
if not isinstance(response, list):
|
|
48
62
|
raise ValueError(f"Unexpected RoomsTrait response format: {response!r}")
|
|
63
|
+
if segment_map is None:
|
|
64
|
+
segment_map = _extract_segment_map(response)
|
|
49
65
|
name_map = self._iot_id_room_name_map
|
|
50
|
-
segment_pairs = _extract_segment_pairs(response)
|
|
51
66
|
return Rooms(
|
|
52
67
|
rooms=[
|
|
53
|
-
NamedRoomMapping(segment_id=segment_id, iot_id=iot_id, name=name_map.get(iot_id,
|
|
54
|
-
for segment_id, iot_id in
|
|
68
|
+
NamedRoomMapping(segment_id=segment_id, iot_id=iot_id, name=name_map.get(iot_id, f"Room {segment_id}"))
|
|
69
|
+
for segment_id, iot_id in segment_map.items()
|
|
55
70
|
]
|
|
56
71
|
)
|
|
57
72
|
|
|
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
|
+
|
|
80
|
+
try:
|
|
81
|
+
web_rooms = await self._web_api.get_rooms()
|
|
82
|
+
except Exception:
|
|
83
|
+
_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)
|
|
89
|
+
|
|
58
90
|
|
|
59
|
-
def
|
|
60
|
-
"""Extract segment_id
|
|
91
|
+
def _extract_segment_map(response: list) -> dict[int, str]:
|
|
92
|
+
"""Extract a segment_id -> iot_id mapping from the response.
|
|
61
93
|
|
|
62
94
|
The response format can be either a flat list of [segment_id, iot_id] or a
|
|
63
95
|
list of lists, where each inner list is a pair of [segment_id, iot_id]. This
|
|
64
|
-
function normalizes the response into a
|
|
96
|
+
function normalizes the response into a dict of segment_id to iot_id.
|
|
65
97
|
|
|
66
98
|
NOTE: We currently only partial samples of the room mapping formats, so
|
|
67
99
|
improving test coverage with samples from a real device with this format
|
|
@@ -69,13 +101,13 @@ def _extract_segment_pairs(response: list) -> list[tuple[int, str]]:
|
|
|
69
101
|
"""
|
|
70
102
|
if len(response) == 2 and not isinstance(response[0], list):
|
|
71
103
|
segment_id, iot_id = response[0], response[1]
|
|
72
|
-
return
|
|
104
|
+
return {segment_id: str(iot_id)}
|
|
73
105
|
|
|
74
|
-
|
|
106
|
+
segment_map: dict[int, str] = {}
|
|
75
107
|
for part in response:
|
|
76
108
|
if not isinstance(part, list) or len(part) < 2:
|
|
77
109
|
_LOGGER.warning("Unexpected room mapping entry format: %r", part)
|
|
78
110
|
continue
|
|
79
111
|
segment_id, iot_id = part[0], part[1]
|
|
80
|
-
|
|
81
|
-
return
|
|
112
|
+
segment_map[segment_id] = str(iot_id)
|
|
113
|
+
return segment_map
|
|
@@ -27,7 +27,7 @@ from .session import MqttParams, MqttSession, MqttSessionException, MqttSessionU
|
|
|
27
27
|
_LOGGER = logging.getLogger(__name__)
|
|
28
28
|
_MQTT_LOGGER = logging.getLogger(f"{__name__}.aiomqtt")
|
|
29
29
|
|
|
30
|
-
CLIENT_KEEPALIVE = datetime.timedelta(seconds=
|
|
30
|
+
CLIENT_KEEPALIVE = datetime.timedelta(seconds=45)
|
|
31
31
|
TOPIC_KEEPALIVE = datetime.timedelta(seconds=60)
|
|
32
32
|
|
|
33
33
|
# Exponential backoff parameters
|
|
@@ -56,9 +56,12 @@ class RoborockMqttSession(MqttSession):
|
|
|
56
56
|
The client is run as a background task that will run until shutdown. Once
|
|
57
57
|
connected, the client will wait for messages to be received in a loop. If
|
|
58
58
|
the connection is lost, the client will be re-created and reconnected. There
|
|
59
|
-
is backoff to avoid spamming the broker with connection attempts.
|
|
60
|
-
|
|
61
|
-
|
|
59
|
+
is backoff to avoid spamming the broker with connection attempts.
|
|
60
|
+
|
|
61
|
+
Reconnect attempts are deferred while there are no active subscriptions,
|
|
62
|
+
which avoids unnecessary reconnect churn for idle sessions. Reconnects
|
|
63
|
+
resume as soon as a subscription is added again. The client automatically
|
|
64
|
+
re-establishes any existing subscriptions when the connection returns.
|
|
62
65
|
"""
|
|
63
66
|
|
|
64
67
|
def __init__(
|
|
@@ -175,6 +178,16 @@ class RoborockMqttSession(MqttSession):
|
|
|
175
178
|
if self._stop:
|
|
176
179
|
_LOGGER.debug("MQTT session closed, stopping retry loop")
|
|
177
180
|
return
|
|
181
|
+
if not self._client_subscribed_topics and not self._listeners.keys():
|
|
182
|
+
_LOGGER.debug("MQTT session disconnected with no active subscriptions, deferring reconnect")
|
|
183
|
+
self._diagnostics.increment("reconnect_deferred")
|
|
184
|
+
while not self._stop and not self._client_subscribed_topics and not self._listeners.keys():
|
|
185
|
+
await asyncio.sleep(0.1)
|
|
186
|
+
if self._stop:
|
|
187
|
+
_LOGGER.debug("MQTT session closed while waiting for active subscriptions")
|
|
188
|
+
return
|
|
189
|
+
self._backoff = MIN_BACKOFF_INTERVAL
|
|
190
|
+
continue
|
|
178
191
|
_LOGGER.info("MQTT session disconnected, retrying in %s seconds", self._backoff.total_seconds())
|
|
179
192
|
self._diagnostics.increment("reconnect_wait")
|
|
180
193
|
await asyncio.sleep(self._backoff.total_seconds())
|
|
@@ -544,10 +544,10 @@ class RoborockApiClient:
|
|
|
544
544
|
rriot.r.a,
|
|
545
545
|
self.session,
|
|
546
546
|
{
|
|
547
|
-
"Authorization": _get_hawk_authentication(rriot, "/
|
|
547
|
+
"Authorization": _get_hawk_authentication(rriot, f"/user/homes/{home_id}/rooms"),
|
|
548
548
|
},
|
|
549
549
|
)
|
|
550
|
-
room_response = await room_request.request("get", f"/user/homes/{
|
|
550
|
+
room_response = await room_request.request("get", f"/user/homes/{home_id}/rooms")
|
|
551
551
|
if not room_response.get("success"):
|
|
552
552
|
raise RoborockException(room_response)
|
|
553
553
|
rooms = room_response.get("result")
|
|
@@ -752,6 +752,10 @@ class UserWebApiClient:
|
|
|
752
752
|
"""Fetch routines (scenes) for a specific device."""
|
|
753
753
|
return await self._web_api.get_scenes(self._user_data, device_id)
|
|
754
754
|
|
|
755
|
+
async def get_rooms(self) -> list[HomeDataRoom]:
|
|
756
|
+
"""Fetch rooms using the API client."""
|
|
757
|
+
return await self._web_api.get_rooms(self._user_data)
|
|
758
|
+
|
|
755
759
|
async def execute_routine(self, scene_id: int) -> None:
|
|
756
760
|
"""Execute a specific routine (scene) by its ID."""
|
|
757
761
|
await self._web_api.execute_scene(self._user_data, scene_id)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q10/b01_q10_code_mappings.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q10/b01_q10_containers.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/data/b01_q7/b01_q7_code_mappings.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/__init__.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q10/command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q7/__init__.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/b01/q7/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/device_features.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/do_not_disturb.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/dust_collection_mode.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/flow_led_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/network_info.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/smart_wash_params.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/traits/v1/wash_towel_mode.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/transport/local_channel.py
RENAMED
|
File without changes
|
{python_roborock-4.18.0 → python_roborock-4.19.0}/roborock/devices/transport/mqtt_channel.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|