python-roborock 4.16.0__tar.gz → 4.17.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.16.0 → python_roborock-4.17.0}/PKG-INFO +1 -1
- {python_roborock-4.16.0 → python_roborock-4.17.0}/pyproject.toml +1 -1
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/code_mappings.py +16 -1
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/v1/v1_clean_modes.py +10 -1
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/v1/v1_containers.py +136 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/device_manager.py +1 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/__init__.py +8 -3
- python_roborock-4.17.0/roborock/devices/traits/v1/status.py +92 -0
- python_roborock-4.16.0/roborock/devices/traits/v1/status.py +0 -24
- {python_roborock-4.16.0 → python_roborock-4.17.0}/.gitignore +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/LICENSE +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/README.md +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/broadcast_protocol.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/callbacks.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/cli.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/const.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q10/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q7/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/containers.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/dyad/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/dyad/dyad_containers.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/v1/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/v1/v1_code_mappings.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/zeo/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/zeo/zeo_containers.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/device_features.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/README.md +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/cache.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/device.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/file_cache.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/rpc/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/rpc/a01_channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/rpc/v1_channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/a01/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/command.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/common.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/status.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q7/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/traits_mixin.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/child_lock.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/command.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/common.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/consumeable.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/device_features.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/home.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/led_status.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/map_content.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/maps.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/network_info.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/rooms.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/routines.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/volume.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/transport/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/transport/channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/transport/local_channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/transport/mqtt_channel.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/diagnostics.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/exceptions.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/map/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/map/map_parser.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/mqtt/health_manager.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/mqtt/roborock_session.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/protocol.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/protocols/__init__.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/protocols/b01_q10_protocol.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/protocols/b01_q7_protocol.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/py.typed +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/roborock_message.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/util.py +0 -0
- {python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/web_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.17.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.17.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"
|
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import logging
|
|
4
4
|
from collections import namedtuple
|
|
5
5
|
from enum import Enum, IntEnum, StrEnum
|
|
6
|
-
from typing import Self
|
|
6
|
+
from typing import Any, Self
|
|
7
7
|
|
|
8
8
|
_LOGGER = logging.getLogger(__name__)
|
|
9
9
|
completed_warnings = set()
|
|
@@ -105,6 +105,21 @@ class RoborockModeEnum(StrEnum):
|
|
|
105
105
|
"""Returns a list of all member values."""
|
|
106
106
|
return [member.value for member in cls]
|
|
107
107
|
|
|
108
|
+
def __eq__(self, other: Any) -> bool:
|
|
109
|
+
if isinstance(other, str):
|
|
110
|
+
return self.value == other or self.name == other
|
|
111
|
+
if isinstance(other, int):
|
|
112
|
+
return self.code == other
|
|
113
|
+
return super().__eq__(other)
|
|
114
|
+
|
|
115
|
+
def __hash__(self) -> int:
|
|
116
|
+
"""Hash a RoborockModeEnum.
|
|
117
|
+
|
|
118
|
+
It is critical that you do not mix RoborockModeEnums with raw strings or ints in hashed situations
|
|
119
|
+
(i.e. sets or keys in dictionaries)
|
|
120
|
+
"""
|
|
121
|
+
return hash((self.code, self._value_))
|
|
122
|
+
|
|
108
123
|
|
|
109
124
|
ProductInfo = namedtuple("ProductInfo", ["nickname", "short_models"])
|
|
110
125
|
|
|
@@ -16,6 +16,8 @@ class VacuumModes(RoborockModeEnum):
|
|
|
16
16
|
TURBO = ("turbo", 103)
|
|
17
17
|
MAX = ("max", 104)
|
|
18
18
|
MAX_PLUS = ("max_plus", 108)
|
|
19
|
+
CARPET = ("carpet", 107)
|
|
20
|
+
OFF_RAISE_MAIN_BRUSH = ("off_raise_main_brush", 109)
|
|
19
21
|
CUSTOMIZED = ("custom", 106)
|
|
20
22
|
SMART_MODE = ("smart_mode", 110)
|
|
21
23
|
|
|
@@ -45,6 +47,8 @@ class WaterModes(RoborockModeEnum):
|
|
|
45
47
|
STANDARD = ("standard", 202)
|
|
46
48
|
HIGH = ("high", 203)
|
|
47
49
|
INTENSE = ("intense", 203)
|
|
50
|
+
MIN = ("min", 205)
|
|
51
|
+
MAX = ("max", 206)
|
|
48
52
|
CUSTOMIZED = ("custom", 204)
|
|
49
53
|
CUSTOM = ("custom_water_flow", 207)
|
|
50
54
|
EXTREME = ("extreme", 208)
|
|
@@ -81,9 +85,14 @@ def get_clean_modes(features: DeviceFeatures) -> list[VacuumModes]:
|
|
|
81
85
|
if features.is_max_plus_mode_supported or features.is_none_pure_clean_mop_with_max_plus:
|
|
82
86
|
# If the vacuum has max plus mode supported
|
|
83
87
|
modes.append(VacuumModes.MAX_PLUS)
|
|
88
|
+
if features.is_carpet_deep_clean_supported:
|
|
89
|
+
modes.append(VacuumModes.CARPET)
|
|
84
90
|
if features.is_pure_clean_mop_supported:
|
|
85
91
|
# If the vacuum is capable of 'pure mop clean' aka no vacuum
|
|
86
|
-
|
|
92
|
+
if features.is_support_main_brush_up_down_supported:
|
|
93
|
+
modes.append(VacuumModes.OFF_RAISE_MAIN_BRUSH)
|
|
94
|
+
else:
|
|
95
|
+
modes.append(VacuumModes.OFF)
|
|
87
96
|
else:
|
|
88
97
|
# If not, we can add gentle
|
|
89
98
|
modes.append(VacuumModes.GENTLE)
|
|
@@ -121,6 +121,8 @@ def _requires_schema_code(requires_schema_code: str, default=None) -> Any:
|
|
|
121
121
|
|
|
122
122
|
@dataclass
|
|
123
123
|
class Status(RoborockBase):
|
|
124
|
+
"""This status will be deprecated in favor of StatusV2."""
|
|
125
|
+
|
|
124
126
|
msg_ver: int | None = None
|
|
125
127
|
msg_seq: int | None = None
|
|
126
128
|
state: RoborockStateCode | None = _requires_schema_code("state", default=None)
|
|
@@ -282,6 +284,140 @@ class Status(RoborockBase):
|
|
|
282
284
|
return _attr_repr(self)
|
|
283
285
|
|
|
284
286
|
|
|
287
|
+
@dataclass
|
|
288
|
+
class StatusV2(RoborockBase):
|
|
289
|
+
"""
|
|
290
|
+
This is a new version of the Status object.
|
|
291
|
+
This is the result of GET_STATUS from the api.
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
msg_ver: int | None = None
|
|
295
|
+
msg_seq: int | None = None
|
|
296
|
+
state: RoborockStateCode | None = None
|
|
297
|
+
battery: int | None = None
|
|
298
|
+
clean_time: int | None = None
|
|
299
|
+
clean_area: int | None = None
|
|
300
|
+
error_code: RoborockErrorCode | None = None
|
|
301
|
+
map_present: int | None = None
|
|
302
|
+
in_cleaning: RoborockInCleaning | None = None
|
|
303
|
+
in_returning: int | None = None
|
|
304
|
+
in_fresh_state: int | None = None
|
|
305
|
+
lab_status: int | None = None
|
|
306
|
+
water_box_status: int | None = None
|
|
307
|
+
back_type: int | None = None
|
|
308
|
+
wash_phase: int | None = None
|
|
309
|
+
wash_ready: int | None = None
|
|
310
|
+
fan_power: int | None = None
|
|
311
|
+
dnd_enabled: int | None = None
|
|
312
|
+
map_status: int | None = None
|
|
313
|
+
is_locating: int | None = None
|
|
314
|
+
lock_status: int | None = None
|
|
315
|
+
water_box_mode: int | None = None
|
|
316
|
+
water_box_carriage_status: int | None = None
|
|
317
|
+
mop_forbidden_enable: int | None = None
|
|
318
|
+
camera_status: int | None = None
|
|
319
|
+
is_exploring: int | None = None
|
|
320
|
+
home_sec_status: int | None = None
|
|
321
|
+
home_sec_enable_password: int | None = None
|
|
322
|
+
adbumper_status: list[int] | None = None
|
|
323
|
+
water_shortage_status: int | None = None
|
|
324
|
+
dock_type: RoborockDockTypeCode | None = None
|
|
325
|
+
dust_collection_status: int | None = None
|
|
326
|
+
auto_dust_collection: int | None = None
|
|
327
|
+
avoid_count: int | None = None
|
|
328
|
+
mop_mode: int | None = None
|
|
329
|
+
debug_mode: int | None = None
|
|
330
|
+
collision_avoid_status: int | None = None
|
|
331
|
+
switch_map_mode: int | None = None
|
|
332
|
+
dock_error_status: RoborockDockErrorCode | None = None
|
|
333
|
+
charge_status: int | None = None
|
|
334
|
+
unsave_map_reason: int | None = None
|
|
335
|
+
unsave_map_flag: int | None = None
|
|
336
|
+
wash_status: int | None = None
|
|
337
|
+
distance_off: int | None = None
|
|
338
|
+
in_warmup: int | None = None
|
|
339
|
+
dry_status: int | None = None
|
|
340
|
+
rdt: int | None = None
|
|
341
|
+
clean_percent: int | None = None
|
|
342
|
+
rss: int | None = None
|
|
343
|
+
dss: int | None = None
|
|
344
|
+
common_status: int | None = None
|
|
345
|
+
corner_clean_mode: int | None = None
|
|
346
|
+
last_clean_t: int | None = None
|
|
347
|
+
replenish_mode: int | None = None
|
|
348
|
+
repeat: int | None = None
|
|
349
|
+
kct: int | None = None
|
|
350
|
+
subdivision_sets: int | None = None
|
|
351
|
+
|
|
352
|
+
@property
|
|
353
|
+
def square_meter_clean_area(self) -> float | None:
|
|
354
|
+
return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None
|
|
355
|
+
|
|
356
|
+
@property
|
|
357
|
+
def error_code_name(self) -> str | None:
|
|
358
|
+
return self.error_code.name if self.error_code is not None else None
|
|
359
|
+
|
|
360
|
+
@property
|
|
361
|
+
def state_name(self) -> str | None:
|
|
362
|
+
return self.state.name if self.state is not None else None
|
|
363
|
+
|
|
364
|
+
@property
|
|
365
|
+
def current_map(self) -> int | None:
|
|
366
|
+
"""Returns the current map ID if the map is present."""
|
|
367
|
+
if self.map_status is not None:
|
|
368
|
+
map_flag = self.map_status >> 2
|
|
369
|
+
if map_flag != NO_MAP:
|
|
370
|
+
return map_flag
|
|
371
|
+
return None
|
|
372
|
+
|
|
373
|
+
@property
|
|
374
|
+
def clear_water_box_status(self) -> ClearWaterBoxStatus | None:
|
|
375
|
+
if self.dss:
|
|
376
|
+
return ClearWaterBoxStatus((self.dss >> 2) & 3)
|
|
377
|
+
return None
|
|
378
|
+
|
|
379
|
+
@property
|
|
380
|
+
def dirty_water_box_status(self) -> DirtyWaterBoxStatus | None:
|
|
381
|
+
if self.dss:
|
|
382
|
+
return DirtyWaterBoxStatus((self.dss >> 4) & 3)
|
|
383
|
+
return None
|
|
384
|
+
|
|
385
|
+
@property
|
|
386
|
+
def dust_bag_status(self) -> DustBagStatus | None:
|
|
387
|
+
if self.dss:
|
|
388
|
+
return DustBagStatus((self.dss >> 6) & 3)
|
|
389
|
+
return None
|
|
390
|
+
|
|
391
|
+
@property
|
|
392
|
+
def water_box_filter_status(self) -> int | None:
|
|
393
|
+
if self.dss:
|
|
394
|
+
return (self.dss >> 8) & 3
|
|
395
|
+
return None
|
|
396
|
+
|
|
397
|
+
@property
|
|
398
|
+
def clean_fluid_status(self) -> CleanFluidStatus | None:
|
|
399
|
+
if self.dss:
|
|
400
|
+
value = (self.dss >> 10) & 3
|
|
401
|
+
if value == 0:
|
|
402
|
+
return None # Feature not supported by this device
|
|
403
|
+
return None
|
|
404
|
+
|
|
405
|
+
@property
|
|
406
|
+
def hatch_door_status(self) -> int | None:
|
|
407
|
+
if self.dss:
|
|
408
|
+
return (self.dss >> 12) & 7
|
|
409
|
+
return None
|
|
410
|
+
|
|
411
|
+
@property
|
|
412
|
+
def dock_cool_fan_status(self) -> int | None:
|
|
413
|
+
if self.dss:
|
|
414
|
+
return (self.dss >> 15) & 3
|
|
415
|
+
return None
|
|
416
|
+
|
|
417
|
+
def __repr__(self) -> str:
|
|
418
|
+
return _attr_repr(self)
|
|
419
|
+
|
|
420
|
+
|
|
285
421
|
@dataclass
|
|
286
422
|
class S4MaxStatus(Status):
|
|
287
423
|
fan_power: RoborockFanSpeedS6Pure | None = None
|
|
@@ -239,6 +239,7 @@ async def create_device_manager(
|
|
|
239
239
|
web_api,
|
|
240
240
|
device_cache=device_cache,
|
|
241
241
|
map_parser_config=map_parser_config,
|
|
242
|
+
region=user_data.region,
|
|
242
243
|
)
|
|
243
244
|
case DeviceVersion.A01:
|
|
244
245
|
channel = create_mqtt_channel(user_data, mqtt_params, mqtt_session, device)
|
|
@@ -54,7 +54,6 @@ code in HomeDataProduct Schema that is required for the field to be supported.
|
|
|
54
54
|
|
|
55
55
|
import logging
|
|
56
56
|
from dataclasses import dataclass, field, fields
|
|
57
|
-
from functools import cache
|
|
58
57
|
from typing import Any, get_args
|
|
59
58
|
|
|
60
59
|
from roborock.data.containers import HomeData, HomeDataProduct, RoborockBase
|
|
@@ -180,6 +179,7 @@ class PropertiesApi(Trait):
|
|
|
180
179
|
web_api: UserWebApiClient,
|
|
181
180
|
device_cache: DeviceCache,
|
|
182
181
|
map_parser_config: MapParserConfig | None = None,
|
|
182
|
+
region: str | None = None,
|
|
183
183
|
) -> None:
|
|
184
184
|
"""Initialize the V1TraitProps."""
|
|
185
185
|
self._device_uid = device_uid
|
|
@@ -188,14 +188,15 @@ class PropertiesApi(Trait):
|
|
|
188
188
|
self._map_rpc_channel = map_rpc_channel
|
|
189
189
|
self._web_api = web_api
|
|
190
190
|
self._device_cache = device_cache
|
|
191
|
+
self._region = region
|
|
191
192
|
|
|
192
|
-
self.
|
|
193
|
+
self.device_features = DeviceFeaturesTrait(product, self._device_cache)
|
|
194
|
+
self.status = StatusTrait(self.device_features, region=self._region)
|
|
193
195
|
self.consumables = ConsumableTrait()
|
|
194
196
|
self.rooms = RoomsTrait(home_data)
|
|
195
197
|
self.maps = MapsTrait(self.status)
|
|
196
198
|
self.map_content = MapContentTrait(map_parser_config)
|
|
197
199
|
self.home = HomeTrait(self.status, self.maps, self.map_content, self.rooms, self._device_cache)
|
|
198
|
-
self.device_features = DeviceFeaturesTrait(product, self._device_cache)
|
|
199
200
|
self.network_info = NetworkInfoTrait(device_uid, self._device_cache)
|
|
200
201
|
self.routines = RoutinesTrait(device_uid, web_api)
|
|
201
202
|
|
|
@@ -206,6 +207,8 @@ class PropertiesApi(Trait):
|
|
|
206
207
|
if (union_args := get_args(item.type)) is None or len(union_args) > 0:
|
|
207
208
|
continue
|
|
208
209
|
_LOGGER.debug("Trait '%s' is supported, initializing", item.name)
|
|
210
|
+
if not callable(item.type):
|
|
211
|
+
continue
|
|
209
212
|
trait = item.type()
|
|
210
213
|
setattr(self, item.name, trait)
|
|
211
214
|
# This is a hack to allow setting the rpc_channel on all traits. This is
|
|
@@ -324,6 +327,7 @@ def create(
|
|
|
324
327
|
web_api: UserWebApiClient,
|
|
325
328
|
device_cache: DeviceCache,
|
|
326
329
|
map_parser_config: MapParserConfig | None = None,
|
|
330
|
+
region: str | None = None,
|
|
327
331
|
) -> PropertiesApi:
|
|
328
332
|
"""Create traits for V1 devices."""
|
|
329
333
|
return PropertiesApi(
|
|
@@ -336,4 +340,5 @@ def create(
|
|
|
336
340
|
web_api,
|
|
337
341
|
device_cache,
|
|
338
342
|
map_parser_config,
|
|
343
|
+
region=region,
|
|
339
344
|
)
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from functools import cached_property
|
|
2
|
+
from typing import Self
|
|
3
|
+
|
|
4
|
+
from roborock import CleanRoutes, StatusV2, VacuumModes, WaterModes, get_clean_modes, get_clean_routes, get_water_modes
|
|
5
|
+
from roborock.roborock_typing import RoborockCommand
|
|
6
|
+
|
|
7
|
+
from . import common
|
|
8
|
+
from .device_features import DeviceFeaturesTrait
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class StatusTrait(StatusV2, common.V1TraitMixin):
|
|
12
|
+
"""Trait for managing the status of Roborock devices.
|
|
13
|
+
|
|
14
|
+
The StatusTrait gives you the access to the state of a Roborock vacuum.
|
|
15
|
+
The various attribute options on state change per each device.
|
|
16
|
+
Values like fan speed, mop mode, etc. have different options for every device
|
|
17
|
+
and are dynamically determined.
|
|
18
|
+
|
|
19
|
+
Usage:
|
|
20
|
+
Before accessing status properties, you should call `refresh()` to fetch
|
|
21
|
+
the latest data from the device. You must pass in the device feature trait
|
|
22
|
+
to this trait so that the dynamic attributes can be pre-determined.
|
|
23
|
+
|
|
24
|
+
The current dynamic attributes are:
|
|
25
|
+
- Fan Speed
|
|
26
|
+
- Water Mode
|
|
27
|
+
- Mop Route
|
|
28
|
+
|
|
29
|
+
You should call the _options() version of the attribute to know which are supported for your device
|
|
30
|
+
(i.e. fan_speed_options())
|
|
31
|
+
Then you can call the _mapping to convert an int value to the actual Enum. (i.e. fan_speed_mapping())
|
|
32
|
+
You can call the _name property to get the str value of the enum. (i.e. fan_speed_name)
|
|
33
|
+
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
command = RoborockCommand.GET_STATUS
|
|
37
|
+
|
|
38
|
+
def __init__(self, device_feature_trait: DeviceFeaturesTrait, region: str | None = None) -> None:
|
|
39
|
+
"""Initialize the StatusTrait."""
|
|
40
|
+
super().__init__()
|
|
41
|
+
self._device_features_trait = device_feature_trait
|
|
42
|
+
self._region = region
|
|
43
|
+
|
|
44
|
+
@cached_property
|
|
45
|
+
def fan_speed_options(self) -> list[VacuumModes]:
|
|
46
|
+
return get_clean_modes(self._device_features_trait)
|
|
47
|
+
|
|
48
|
+
@cached_property
|
|
49
|
+
def fan_speed_mapping(self) -> dict[int, str]:
|
|
50
|
+
return {fan.code: fan.value for fan in self.fan_speed_options}
|
|
51
|
+
|
|
52
|
+
@cached_property
|
|
53
|
+
def water_mode_options(self) -> list[WaterModes]:
|
|
54
|
+
return get_water_modes(self._device_features_trait)
|
|
55
|
+
|
|
56
|
+
@cached_property
|
|
57
|
+
def water_mode_mapping(self) -> dict[int, str]:
|
|
58
|
+
return {mop.code: mop.value for mop in self.water_mode_options}
|
|
59
|
+
|
|
60
|
+
@cached_property
|
|
61
|
+
def mop_route_options(self) -> list[CleanRoutes]:
|
|
62
|
+
return get_clean_routes(self._device_features_trait, self._region or "us")
|
|
63
|
+
|
|
64
|
+
@cached_property
|
|
65
|
+
def mop_route_mapping(self) -> dict[int, str]:
|
|
66
|
+
return {route.code: route.value for route in self.mop_route_options}
|
|
67
|
+
|
|
68
|
+
@property
|
|
69
|
+
def fan_speed_name(self) -> str | None:
|
|
70
|
+
if self.fan_power is None:
|
|
71
|
+
return None
|
|
72
|
+
return self.fan_speed_mapping.get(self.fan_power)
|
|
73
|
+
|
|
74
|
+
@property
|
|
75
|
+
def water_mode_name(self) -> str | None:
|
|
76
|
+
if self.water_box_mode is None:
|
|
77
|
+
return None
|
|
78
|
+
return self.water_mode_mapping.get(self.water_box_mode)
|
|
79
|
+
|
|
80
|
+
@property
|
|
81
|
+
def mop_route_name(self) -> str | None:
|
|
82
|
+
if self.mop_mode is None:
|
|
83
|
+
return None
|
|
84
|
+
return self.mop_route_mapping.get(self.mop_mode)
|
|
85
|
+
|
|
86
|
+
def _parse_response(self, response: common.V1ResponseData) -> Self:
|
|
87
|
+
"""Parse the response from the device into a StatusV2-based status object."""
|
|
88
|
+
if isinstance(response, list):
|
|
89
|
+
response = response[0]
|
|
90
|
+
if isinstance(response, dict):
|
|
91
|
+
return StatusV2.from_dict(response)
|
|
92
|
+
raise ValueError(f"Unexpected status format: {response!r}")
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
from typing import Self
|
|
2
|
-
|
|
3
|
-
from roborock.data import HomeDataProduct, ModelStatus, S7MaxVStatus, Status
|
|
4
|
-
from roborock.devices.traits.v1 import common
|
|
5
|
-
from roborock.roborock_typing import RoborockCommand
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
class StatusTrait(Status, common.V1TraitMixin):
|
|
9
|
-
"""Trait for managing the status of Roborock devices."""
|
|
10
|
-
|
|
11
|
-
command = RoborockCommand.GET_STATUS
|
|
12
|
-
|
|
13
|
-
def __init__(self, product_info: HomeDataProduct) -> None:
|
|
14
|
-
"""Initialize the StatusTrait."""
|
|
15
|
-
self._product_info = product_info
|
|
16
|
-
|
|
17
|
-
def _parse_response(self, response: common.V1ResponseData) -> Self:
|
|
18
|
-
"""Parse the response from the device into a CleanSummary."""
|
|
19
|
-
status_type: type[Status] = ModelStatus.get(self._product_info.model, S7MaxVStatus)
|
|
20
|
-
if isinstance(response, list):
|
|
21
|
-
response = response[0]
|
|
22
|
-
if isinstance(response, dict):
|
|
23
|
-
return status_type.from_dict(response)
|
|
24
|
-
raise ValueError(f"Unexpected status format: {response!r}")
|
|
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.16.0 → python_roborock-4.17.0}/roborock/data/b01_q10/b01_q10_code_mappings.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/data/b01_q10/b01_q10_containers.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.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
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/__init__.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q10/command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q7/__init__.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/b01/q7/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/device_features.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/do_not_disturb.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/dust_collection_mode.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/flow_led_status.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/network_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/smart_wash_params.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/traits/v1/wash_towel_mode.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.0}/roborock/devices/transport/local_channel.py
RENAMED
|
File without changes
|
{python_roborock-4.16.0 → python_roborock-4.17.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
|
|
File without changes
|
|
File without changes
|