python-roborock 0.6.13__tar.gz → 0.6.15__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-0.6.13 → python_roborock-0.6.15}/PKG-INFO +1 -1
- {python_roborock-0.6.13 → python_roborock-0.6.15}/pyproject.toml +1 -1
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/api.py +11 -3
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/containers.py +20 -6
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/roborock_message.py +1 -1
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/typing.py +22 -17
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/util.py +7 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/LICENSE +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/README.md +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/__init__.py +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/cli.py +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/cloud_api.py +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/code_mappings.py +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/exceptions.py +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/local_api.py +0 -0
- {python_roborock-0.6.13 → python_roborock-0.6.15}/roborock/roborock_future.py +0 -0
|
@@ -40,6 +40,7 @@ from .exceptions import RoborockException, RoborockTimeout, VacuumError
|
|
|
40
40
|
from .roborock_future import RoborockFuture
|
|
41
41
|
from .roborock_message import RoborockMessage
|
|
42
42
|
from .typing import RoborockCommand, RoborockDeviceProp, RoborockDockSummary
|
|
43
|
+
from .util import unpack_list
|
|
43
44
|
|
|
44
45
|
_LOGGER = logging.getLogger(__name__)
|
|
45
46
|
QUEUE_TIMEOUT = 4
|
|
@@ -190,6 +191,14 @@ class RoborockClient:
|
|
|
190
191
|
clean_summary = await self.send_command(device_id, RoborockCommand.GET_CLEAN_SUMMARY)
|
|
191
192
|
if isinstance(clean_summary, dict):
|
|
192
193
|
return CleanSummary.from_dict(clean_summary)
|
|
194
|
+
elif isinstance(clean_summary, list):
|
|
195
|
+
clean_time, clean_area, clean_count, records = unpack_list(clean_summary, 4)
|
|
196
|
+
return CleanSummary(
|
|
197
|
+
clean_time=clean_time,
|
|
198
|
+
clean_area=clean_area,
|
|
199
|
+
clean_count=clean_count,
|
|
200
|
+
records=records
|
|
201
|
+
)
|
|
193
202
|
elif isinstance(clean_summary, int):
|
|
194
203
|
return CleanSummary(clean_time=clean_summary)
|
|
195
204
|
except RoborockTimeout as e:
|
|
@@ -244,6 +253,7 @@ class RoborockClient:
|
|
|
244
253
|
async def get_dock_summary(self, device_id: str, dock_type: RoborockEnum) -> RoborockDockSummary | None:
|
|
245
254
|
"""Gets the status summary from the dock with the methods available for a given dock.
|
|
246
255
|
|
|
256
|
+
:param device_id: Device id
|
|
247
257
|
:param dock_type: RoborockDockTypeCode"""
|
|
248
258
|
try:
|
|
249
259
|
commands: list[
|
|
@@ -258,9 +268,7 @@ class RoborockClient:
|
|
|
258
268
|
self.get_wash_towel_mode(device_id),
|
|
259
269
|
self.get_smart_wash_params(device_id),
|
|
260
270
|
]
|
|
261
|
-
[dust_collection_mode, wash_towel_mode, smart_wash_params] = (
|
|
262
|
-
list(await asyncio.gather(*commands)) + [None, None]
|
|
263
|
-
)[:3]
|
|
271
|
+
[dust_collection_mode, wash_towel_mode, smart_wash_params] = unpack_list(list(await asyncio.gather(*commands)), 3)
|
|
264
272
|
|
|
265
273
|
return RoborockDockSummary(dust_collection_mode, wash_towel_mode, smart_wash_params)
|
|
266
274
|
except RoborockTimeout as e:
|
|
@@ -25,6 +25,8 @@ from .code_mappings import (
|
|
|
25
25
|
|
|
26
26
|
def camelize(s: str):
|
|
27
27
|
first, *others = s.split("_")
|
|
28
|
+
if len(others) == 0:
|
|
29
|
+
return s
|
|
28
30
|
return "".join([first.lower(), *map(str.title, others)])
|
|
29
31
|
|
|
30
32
|
|
|
@@ -32,19 +34,27 @@ def decamelize(s: str):
|
|
|
32
34
|
return re.sub("([A-Z]+)", "_\\1", s).lower()
|
|
33
35
|
|
|
34
36
|
|
|
35
|
-
def decamelize_obj(d: dict | list):
|
|
37
|
+
def decamelize_obj(d: dict | list, ignore_keys: list[str]):
|
|
36
38
|
if isinstance(d, list):
|
|
37
|
-
return [decamelize_obj(i) if isinstance(i, (dict, list)) else i for i in d]
|
|
38
|
-
return {
|
|
39
|
+
return [decamelize_obj(i, ignore_keys) if isinstance(i, (dict, list)) else i for i in d]
|
|
40
|
+
return {
|
|
41
|
+
(decamelize(a) if a not in ignore_keys else a): decamelize_obj(b, ignore_keys)
|
|
42
|
+
if isinstance(b, (dict, list))
|
|
43
|
+
else b
|
|
44
|
+
for a, b in d.items()
|
|
45
|
+
}
|
|
39
46
|
|
|
40
47
|
|
|
41
48
|
@dataclass
|
|
42
49
|
class RoborockBase:
|
|
50
|
+
_ignore_keys = [] # type: ignore
|
|
51
|
+
|
|
43
52
|
@classmethod
|
|
44
53
|
def from_dict(cls, data: dict[str, Any]):
|
|
45
|
-
|
|
54
|
+
ignore_keys = cls._ignore_keys
|
|
55
|
+
return from_dict(cls, decamelize_obj(data, ignore_keys), config=Config(cast=[Enum]))
|
|
46
56
|
|
|
47
|
-
def as_dict(self):
|
|
57
|
+
def as_dict(self) -> dict:
|
|
48
58
|
return asdict(
|
|
49
59
|
self,
|
|
50
60
|
dict_factory=lambda _fields: {camelize(key): value for (key, value) in _fields if value is not None},
|
|
@@ -277,7 +287,9 @@ class MultiMapsListMapInfoBakMaps(RoborockBase):
|
|
|
277
287
|
|
|
278
288
|
@dataclass
|
|
279
289
|
class MultiMapsListMapInfo(RoborockBase):
|
|
280
|
-
|
|
290
|
+
_ignore_keys = ["mapFlag"]
|
|
291
|
+
|
|
292
|
+
mapFlag: Optional[Any] = None
|
|
281
293
|
add_time: Optional[Any] = None
|
|
282
294
|
length: Optional[Any] = None
|
|
283
295
|
name: Optional[Any] = None
|
|
@@ -286,6 +298,8 @@ class MultiMapsListMapInfo(RoborockBase):
|
|
|
286
298
|
|
|
287
299
|
@dataclass
|
|
288
300
|
class MultiMapsList(RoborockBase):
|
|
301
|
+
_ignore_keys = ["mapFlag"]
|
|
302
|
+
|
|
289
303
|
max_multi_map: Optional[int] = None
|
|
290
304
|
max_bak_map: Optional[int] = None
|
|
291
305
|
multi_map_count: Optional[int] = None
|
|
@@ -60,7 +60,7 @@ class RoborockMessage:
|
|
|
60
60
|
return data_point_response.get("method")
|
|
61
61
|
return None
|
|
62
62
|
|
|
63
|
-
def get_params(self) -> list | None:
|
|
63
|
+
def get_params(self) -> list | dict | None:
|
|
64
64
|
protocol = self.protocol
|
|
65
65
|
if protocol in [4, 101, 102]:
|
|
66
66
|
payload = json.loads(self.payload.decode())
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
from typing import Optional
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from enum import Enum
|
|
6
6
|
|
|
@@ -117,6 +117,12 @@ class RoborockCommand(str, Enum):
|
|
|
117
117
|
GET_ROOM_MAPPING = "get_room_mapping"
|
|
118
118
|
NAME_SEGMENT = "name_segment"
|
|
119
119
|
SET_TIMEZONE = "set_timezone"
|
|
120
|
+
GET_HOMESEC_CONNECT_STATUS = "get_homesec_connect_status"
|
|
121
|
+
START_CAMERA_PREVIEW = "start_camera_preview"
|
|
122
|
+
GET_TURN_SERVER = "get_turn_server"
|
|
123
|
+
GET_DEVICE_ICE = "get_device_ice"
|
|
124
|
+
START_VOICE_CHAT = "start_voice_chat"
|
|
125
|
+
SEND_SDP_TO_ROBOT = "send_sdp_to_robot"
|
|
120
126
|
|
|
121
127
|
|
|
122
128
|
@dataclass
|
|
@@ -200,7 +206,11 @@ CommandInfoMap: dict[RoborockCommand, CommandInfo] = {
|
|
|
200
206
|
RoborockCommand.SET_SERVER_TIMER: CommandInfo(prefix=b"\x00\x00\x00\xc7"),
|
|
201
207
|
RoborockCommand.GET_ROOM_MAPPING: CommandInfo(prefix=b"\x00\x00\x00w"),
|
|
202
208
|
RoborockCommand.NAME_SEGMENT: CommandInfo(prefix=b"\x00\x00\x027"),
|
|
203
|
-
RoborockCommand.SET_TIMEZONE: CommandInfo(prefix=b"\x00\x00\x00\x97")
|
|
209
|
+
RoborockCommand.SET_TIMEZONE: CommandInfo(prefix=b"\x00\x00\x00\x97"),
|
|
210
|
+
RoborockCommand.GET_HOMESEC_CONNECT_STATUS: CommandInfo(prefix=b"\x00\x00\x00\x87"),
|
|
211
|
+
RoborockCommand.START_CAMERA_PREVIEW: CommandInfo(prefix=b"\x00\x00\x00\x87"),
|
|
212
|
+
RoborockCommand.GET_TURN_SERVER: CommandInfo(prefix=b"\x00\x00\x00\x77"),
|
|
213
|
+
RoborockCommand.GET_DEVICE_ICE: CommandInfo(prefix=b"\x00\x00\x00\x77"),
|
|
204
214
|
# TODO discover prefix for following commands
|
|
205
215
|
# RoborockCommand.APP_GET_DRYER_SETTING: CommandInfo(prefix=b'\x00\x00\x00w'),
|
|
206
216
|
# RoborockCommand.APP_SET_DRYER_SETTING: CommandInfo(prefix=b'\x00\x00\x00w'),
|
|
@@ -214,26 +224,21 @@ CommandInfoMap: dict[RoborockCommand, CommandInfo] = {
|
|
|
214
224
|
}
|
|
215
225
|
|
|
216
226
|
|
|
227
|
+
@dataclass
|
|
217
228
|
class RoborockDockSummary:
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
wash_towel_mode: WashTowelMode,
|
|
222
|
-
smart_wash_params: SmartWashParams,
|
|
223
|
-
) -> None:
|
|
224
|
-
self.dust_collection_mode = dust_collection_mode
|
|
225
|
-
self.wash_towel_mode = wash_towel_mode
|
|
226
|
-
self.smart_wash_params = smart_wash_params
|
|
229
|
+
dust_collection_mode: Optional[DustCollectionMode] = None
|
|
230
|
+
wash_towel_mode: Optional[WashTowelMode] = None
|
|
231
|
+
smart_wash_params: Optional[SmartWashParams] = None
|
|
227
232
|
|
|
228
233
|
|
|
229
234
|
@dataclass
|
|
230
235
|
class RoborockDeviceProp:
|
|
231
|
-
status:
|
|
232
|
-
dnd_timer:
|
|
233
|
-
clean_summary:
|
|
234
|
-
consumable:
|
|
235
|
-
last_clean_record:
|
|
236
|
-
dock_summary:
|
|
236
|
+
status: Optional[Status] = None
|
|
237
|
+
dnd_timer: Optional[DNDTimer] = None
|
|
238
|
+
clean_summary: Optional[CleanSummary] = None
|
|
239
|
+
consumable: Optional[Consumable] = None
|
|
240
|
+
last_clean_record: Optional[CleanRecord] = None
|
|
241
|
+
dock_summary: Optional[RoborockDockSummary] = None
|
|
237
242
|
|
|
238
243
|
def update(self, device_prop: "RoborockDeviceProp"):
|
|
239
244
|
if device_prop.status:
|
|
@@ -1,7 +1,14 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import asyncio
|
|
2
4
|
import functools
|
|
3
5
|
from asyncio import AbstractEventLoop
|
|
6
|
+
from typing import TypeVar
|
|
7
|
+
|
|
8
|
+
T = TypeVar("T")
|
|
4
9
|
|
|
10
|
+
def unpack_list(value: list[T], size: int) -> list[T | None]:
|
|
11
|
+
return (value + [None] * size)[:size]
|
|
5
12
|
|
|
6
13
|
def get_running_loop_or_create_one() -> AbstractEventLoop:
|
|
7
14
|
try:
|
|
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
|