python-roborock 5.24.0__tar.gz → 5.25.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-5.24.0 → python_roborock-5.25.0}/PKG-INFO +1 -1
- {python_roborock-5.24.0 → python_roborock-5.25.0}/pyproject.toml +1 -1
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/__init__.py +1 -0
- python_roborock-5.25.0/roborock/data/mower/__init__.py +3 -0
- python_roborock-5.25.0/roborock/data/mower/mower_containers.py +43 -0
- python_roborock-5.25.0/roborock/data/v1/v1_clean_modes.py +361 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/status.py +36 -4
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/roborock_message.py +39 -0
- python_roborock-5.24.0/roborock/data/v1/v1_clean_modes.py +0 -192
- {python_roborock-5.24.0 → python_roborock-5.25.0}/.gitignore +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/LICENSE +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/README.md +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/broadcast_protocol.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/callbacks.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/cli.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/const.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q10/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q10/b01_q10_code_mappings.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q10/b01_q10_containers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q7/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q7/b01_q7_code_mappings.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q7/b01_q7_containers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/code_mappings.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/containers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/dyad/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/dyad/dyad_code_mappings.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/dyad/dyad_containers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/v1/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/v1/v1_code_mappings.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/v1/v1_containers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/zeo/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/zeo/zeo_code_mappings.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/zeo/zeo_containers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/device_features.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/README.md +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/cache.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/device.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/device_manager.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/file_cache.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/rpc/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/rpc/a01_channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/rpc/b01_q10_channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/rpc/b01_q7_channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/rpc/v1_channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/a01/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/button_light.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/child_lock.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/clean_history.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/command.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/common.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/consumable.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/do_not_disturb.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/dust_collection.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/map.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/network_info.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/remote.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/status.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/vacuum.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/volume.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/clean_summary.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/map.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/map_content.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/common.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/traits_mixin.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/child_lock.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/clean_summary.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/command.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/common.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/consumeable.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/device_features.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/do_not_disturb.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/dust_collection_mode.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/flow_led_status.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/home.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/led_status.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/map_content.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/maps.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/network_info.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/rooms.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/routines.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/smart_wash_params.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/valley_electricity_timer.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/volume.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/wash_towel_mode.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/transport/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/transport/channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/transport/local_channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/transport/mqtt_channel.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/diagnostics.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/exceptions.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/b01_grid_layers.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/b01_map_parser.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/b01_q10_map_parser.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/b01_q10_overlays.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/map_parser.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/proto/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/proto/b01_scmap.proto +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/map/proto/b01_scmap_pb2.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/mqtt/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/mqtt/health_manager.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/mqtt/roborock_session.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/mqtt/session.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/protocol.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/protocols/__init__.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/protocols/a01_protocol.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/protocols/b01_q10_protocol.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/protocols/b01_q7_protocol.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/protocols/v1_protocol.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/py.typed +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/roborock_typing.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/util.py +0 -0
- {python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/web_api.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-roborock
|
|
3
|
-
Version: 5.
|
|
3
|
+
Version: 5.25.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/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "python-roborock"
|
|
3
|
-
version = "5.
|
|
3
|
+
version = "5.25.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"
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Data containers for Roborock mower devices."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from roborock.data.containers import RoborockBase
|
|
7
|
+
from roborock.roborock_message import RoborockMowerDataProtocol
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class MowerStatus(RoborockBase):
|
|
12
|
+
"""Core mower status backed by mower DPS updates."""
|
|
13
|
+
|
|
14
|
+
error_code: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.ERROR_CODE})
|
|
15
|
+
battery: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.BATTERY})
|
|
16
|
+
mow_type: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_TYPE})
|
|
17
|
+
mow_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_STATE})
|
|
18
|
+
mapping_type: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MAPPING_TYPE})
|
|
19
|
+
mapping_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MAPPING_STATE})
|
|
20
|
+
ota_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.OTA_STATE})
|
|
21
|
+
charge_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.CHARGE_STATE})
|
|
22
|
+
dock_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.DOCK_STATE})
|
|
23
|
+
charge_type: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.CHARGE_TYPE})
|
|
24
|
+
pend_type: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.PEND_TYPE})
|
|
25
|
+
remote_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.REMOTE_STATE})
|
|
26
|
+
mow_start_type: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_START_TYPE})
|
|
27
|
+
mow_eff_mode: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_EFF_MODE})
|
|
28
|
+
mow_height: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_HEIGHT})
|
|
29
|
+
mow_direction_angle: int | None = field(
|
|
30
|
+
default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_DIRECTION_ANGLE}
|
|
31
|
+
)
|
|
32
|
+
mow_pattern: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_PATTERN})
|
|
33
|
+
mow_conf_mode: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_CONF_MODE})
|
|
34
|
+
offline_status: Any | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.OFFLINE_STATUS})
|
|
35
|
+
mow_progress: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.MOW_PROGRESS})
|
|
36
|
+
blade_lifespan: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.BLADE_LIFESPAN})
|
|
37
|
+
fc_state: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.FC_STATE})
|
|
38
|
+
gps_coordinate: Any | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.GPS_COORDINATE})
|
|
39
|
+
off_dock_no_task_status: int | None = field(
|
|
40
|
+
default=None, metadata={"dps": RoborockMowerDataProtocol.OFF_DOCK_NO_TASK_STATUS}
|
|
41
|
+
)
|
|
42
|
+
afs_status: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.AFS_STATUS})
|
|
43
|
+
network_channel: int | None = field(default=None, metadata={"dps": RoborockMowerDataProtocol.NETWORK_CHANNEL})
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
from enum import StrEnum
|
|
5
|
+
from typing import TypeVar
|
|
6
|
+
|
|
7
|
+
from ...exceptions import RoborockUnsupportedFeature
|
|
8
|
+
from ..code_mappings import RoborockModeEnum
|
|
9
|
+
|
|
10
|
+
if typing.TYPE_CHECKING:
|
|
11
|
+
from roborock.device_features import DeviceFeatures
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class VacuumModes(RoborockModeEnum):
|
|
15
|
+
GENTLE = ("gentle", 105)
|
|
16
|
+
OFF = ("off", 105)
|
|
17
|
+
QUIET = ("quiet", 101)
|
|
18
|
+
BALANCED = ("balanced", 102)
|
|
19
|
+
TURBO = ("turbo", 103)
|
|
20
|
+
MAX = ("max", 104)
|
|
21
|
+
MAX_PLUS = ("max_plus", 108)
|
|
22
|
+
OFF_RAISE_MAIN_BRUSH = ("off_raise_main_brush", 109)
|
|
23
|
+
CUSTOMIZED = ("custom", 106)
|
|
24
|
+
SMART_MODE = ("smart_mode", 110)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class CleanRoutes(RoborockModeEnum):
|
|
28
|
+
STANDARD = ("standard", 300)
|
|
29
|
+
DEEP = ("deep", 301)
|
|
30
|
+
DEEP_PLUS = ("deep_plus", 303)
|
|
31
|
+
FAST = ("fast", 304)
|
|
32
|
+
DEEP_PLUS_CN = ("deep_plus", 305)
|
|
33
|
+
SMART_MODE = ("smart_mode", 306)
|
|
34
|
+
CUSTOMIZED = ("custom", 302)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class VacuumModesOld(RoborockModeEnum):
|
|
38
|
+
QUIET = ("quiet", 38)
|
|
39
|
+
BALANCED = ("balanced", 60)
|
|
40
|
+
TURBO = ("turbo", 75)
|
|
41
|
+
MAX = ("max", 100)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class WaterModes(RoborockModeEnum):
|
|
45
|
+
OFF = ("off", 200)
|
|
46
|
+
LOW = ("low", 201)
|
|
47
|
+
MILD = ("mild", 201)
|
|
48
|
+
MEDIUM = ("medium", 202)
|
|
49
|
+
STANDARD = ("standard", 202)
|
|
50
|
+
HIGH = ("high", 203)
|
|
51
|
+
INTENSE = ("intense", 203)
|
|
52
|
+
MIN = ("min", 205)
|
|
53
|
+
MAX = ("max", 206)
|
|
54
|
+
CUSTOMIZED = ("custom", 204)
|
|
55
|
+
CUSTOM = ("custom_water_flow", 207)
|
|
56
|
+
EXTREME = ("extreme", 208)
|
|
57
|
+
SMART_MODE = ("smart_mode", 209)
|
|
58
|
+
PURE_WATER_FLOW_START = ("slight", 221)
|
|
59
|
+
PURE_WATER_FLOW_SMALL = ("low", 225)
|
|
60
|
+
PURE_WATER_FLOW_MIDDLE = ("medium", 235)
|
|
61
|
+
PURE_WATER_FLOW_LARGE = ("moderate", 245)
|
|
62
|
+
PURE_WATER_SUPER_BEGIN = ("high", 248)
|
|
63
|
+
PURE_WATER_FLOW_END = ("extreme", 250)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class WashTowelModes(RoborockModeEnum):
|
|
67
|
+
SMART = ("smart", 10)
|
|
68
|
+
LIGHT = ("light", 0)
|
|
69
|
+
BALANCED = ("balanced", 1)
|
|
70
|
+
DEEP = ("deep", 2)
|
|
71
|
+
SUPER_DEEP = ("super_deep", 8)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class CleaningMode(StrEnum):
|
|
75
|
+
"""High-level cleaning intent derived from the lower-level motor settings.
|
|
76
|
+
|
|
77
|
+
Prefer this abstraction when you want to present or switch between the
|
|
78
|
+
user-facing cleaning behaviors exposed by the app. The lower-level
|
|
79
|
+
`VacuumModes`, `WaterModes`, and `CleanRoutes` enums are still useful for
|
|
80
|
+
fine-grained selection.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
VACUUM = "vacuum"
|
|
84
|
+
VAC_AND_MOP = "vac_and_mop"
|
|
85
|
+
MOP = "mop"
|
|
86
|
+
CUSTOM = "custom"
|
|
87
|
+
SMART_MODE = "smart_mode"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
WATER_SLIDE_MODE_MAPPING: dict[int, WaterModes] = {
|
|
91
|
+
200: WaterModes.OFF,
|
|
92
|
+
221: WaterModes.PURE_WATER_FLOW_START,
|
|
93
|
+
225: WaterModes.PURE_WATER_FLOW_SMALL,
|
|
94
|
+
235: WaterModes.PURE_WATER_FLOW_MIDDLE,
|
|
95
|
+
245: WaterModes.PURE_WATER_FLOW_LARGE,
|
|
96
|
+
248: WaterModes.PURE_WATER_SUPER_BEGIN,
|
|
97
|
+
250: WaterModes.PURE_WATER_FLOW_END,
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
ModeEnumT = TypeVar("ModeEnumT", bound=RoborockModeEnum)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def get_wash_towel_modes(features: DeviceFeatures) -> list[WashTowelModes]:
|
|
104
|
+
"""Get the valid wash towel modes for the device"""
|
|
105
|
+
modes = [WashTowelModes.LIGHT, WashTowelModes.BALANCED, WashTowelModes.DEEP]
|
|
106
|
+
if features.is_super_deep_wash_supported and not features.is_dirty_replenish_clean_supported:
|
|
107
|
+
modes.append(WashTowelModes.SUPER_DEEP)
|
|
108
|
+
elif features.is_dirty_replenish_clean_supported:
|
|
109
|
+
modes.append(WashTowelModes.SMART)
|
|
110
|
+
return modes
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def get_clean_modes(features: DeviceFeatures) -> list[VacuumModes]:
|
|
114
|
+
"""Get the valid clean modes for the device - also known as 'fan power' or 'suction mode'"""
|
|
115
|
+
modes = [VacuumModes.QUIET, VacuumModes.BALANCED, VacuumModes.TURBO, VacuumModes.MAX]
|
|
116
|
+
if features.is_max_plus_mode_supported or features.is_none_pure_clean_mop_with_max_plus:
|
|
117
|
+
# If the vacuum has max plus mode supported
|
|
118
|
+
modes.append(VacuumModes.MAX_PLUS)
|
|
119
|
+
if features.is_pure_clean_mop_supported:
|
|
120
|
+
# If the vacuum is capable of 'pure mop clean' aka no vacuum
|
|
121
|
+
if features.is_support_main_brush_up_down_supported:
|
|
122
|
+
modes.append(VacuumModes.OFF_RAISE_MAIN_BRUSH)
|
|
123
|
+
else:
|
|
124
|
+
modes.append(VacuumModes.OFF)
|
|
125
|
+
else:
|
|
126
|
+
# If not, we can add gentle
|
|
127
|
+
modes.append(VacuumModes.GENTLE)
|
|
128
|
+
if features.is_smart_clean_mode_set_supported:
|
|
129
|
+
modes.append(VacuumModes.SMART_MODE)
|
|
130
|
+
if features.is_customized_clean_supported:
|
|
131
|
+
modes.append(VacuumModes.CUSTOMIZED)
|
|
132
|
+
return modes
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
def get_clean_routes(features: DeviceFeatures, region: str) -> list[CleanRoutes]:
|
|
136
|
+
"""The routes that the vacuum will take while mopping"""
|
|
137
|
+
if features.is_none_pure_clean_mop_with_max_plus:
|
|
138
|
+
return [CleanRoutes.FAST, CleanRoutes.STANDARD]
|
|
139
|
+
supported = [CleanRoutes.STANDARD, CleanRoutes.DEEP]
|
|
140
|
+
if features.is_careful_slow_mop_supported:
|
|
141
|
+
if not (
|
|
142
|
+
features.is_corner_clean_mode_supported
|
|
143
|
+
and features.is_clean_route_deep_slow_plus_supported
|
|
144
|
+
and region == "cn"
|
|
145
|
+
):
|
|
146
|
+
# for some reason there is a china specific deep plus mode
|
|
147
|
+
supported.append(CleanRoutes.DEEP_PLUS_CN)
|
|
148
|
+
else:
|
|
149
|
+
supported.append(CleanRoutes.DEEP_PLUS)
|
|
150
|
+
|
|
151
|
+
if features.is_clean_route_fast_mode_supported:
|
|
152
|
+
supported.append(CleanRoutes.FAST)
|
|
153
|
+
if features.is_smart_clean_mode_set_supported:
|
|
154
|
+
supported.append(CleanRoutes.SMART_MODE)
|
|
155
|
+
if features.is_customized_clean_supported:
|
|
156
|
+
supported.append(CleanRoutes.CUSTOMIZED)
|
|
157
|
+
|
|
158
|
+
return supported
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def get_water_modes(features: DeviceFeatures) -> list[WaterModes]:
|
|
162
|
+
"""Get the valid water modes for the device - also known as 'water flow' or 'water level'"""
|
|
163
|
+
# Water slide mode supports a separate set of water flow codes.
|
|
164
|
+
if features.is_water_slide_mode_supported:
|
|
165
|
+
return list(WATER_SLIDE_MODE_MAPPING.values())
|
|
166
|
+
|
|
167
|
+
supported_modes = [WaterModes.OFF]
|
|
168
|
+
if features.is_mop_shake_module_supported:
|
|
169
|
+
# For mops that have the vibrating mop pad, they do mild standard intense
|
|
170
|
+
supported_modes.extend([WaterModes.MILD, WaterModes.STANDARD, WaterModes.INTENSE])
|
|
171
|
+
else:
|
|
172
|
+
supported_modes.extend([WaterModes.LOW, WaterModes.MEDIUM, WaterModes.HIGH])
|
|
173
|
+
if features.is_custom_water_box_distance_supported:
|
|
174
|
+
# This is for devices that allow you to set a custom water flow from 0-100
|
|
175
|
+
supported_modes.append(WaterModes.CUSTOM)
|
|
176
|
+
if features.is_mop_shake_module_supported and features.is_mop_shake_water_max_supported:
|
|
177
|
+
supported_modes.append(WaterModes.EXTREME)
|
|
178
|
+
if features.is_smart_clean_mode_set_supported:
|
|
179
|
+
supported_modes.append(WaterModes.SMART_MODE)
|
|
180
|
+
if features.is_customized_clean_supported:
|
|
181
|
+
supported_modes.append(WaterModes.CUSTOMIZED)
|
|
182
|
+
|
|
183
|
+
return supported_modes
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def get_water_mode_mapping(features: DeviceFeatures) -> dict[int, str]:
|
|
187
|
+
"""Get water mode mapping by supported feature set.
|
|
188
|
+
|
|
189
|
+
WaterModes contains aliases for multiple codes that share the same value
|
|
190
|
+
string (e.g. low can be 201 or 225). For water slide mode devices we need
|
|
191
|
+
explicit code mapping to preserve those slide-specific codes.
|
|
192
|
+
"""
|
|
193
|
+
if features.is_water_slide_mode_supported:
|
|
194
|
+
return {code: mode.value for code, mode in WATER_SLIDE_MODE_MAPPING.items()}
|
|
195
|
+
return {mode.code: mode.value for mode in get_water_modes(features)}
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_cleaning_mode_options(features: DeviceFeatures) -> list[CleaningMode]:
|
|
199
|
+
"""Return the supported high-level cleaning modes for the device.
|
|
200
|
+
|
|
201
|
+
These options are the preferred user-facing choices because they bundle the
|
|
202
|
+
correct fan, water, and mop-route settings together for the device. Callers
|
|
203
|
+
should generally present these instead of mixing lower-level mode enums
|
|
204
|
+
unless they explicitly need fine-grained control.
|
|
205
|
+
"""
|
|
206
|
+
if not features.is_support_water_mode:
|
|
207
|
+
return []
|
|
208
|
+
|
|
209
|
+
supported_water_modes = get_water_modes(features)
|
|
210
|
+
options = [CleaningMode.VACUUM, CleaningMode.VAC_AND_MOP]
|
|
211
|
+
if features.is_pure_clean_mop_supported:
|
|
212
|
+
options.append(CleaningMode.MOP)
|
|
213
|
+
if features.is_customized_clean_supported and WaterModes.CUSTOMIZED in supported_water_modes:
|
|
214
|
+
options.append(CleaningMode.CUSTOM)
|
|
215
|
+
if features.is_smart_clean_mode_set_supported and WaterModes.SMART_MODE in supported_water_modes:
|
|
216
|
+
options.append(CleaningMode.SMART_MODE)
|
|
217
|
+
return options
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_mop_only_vacuum_mode(features: DeviceFeatures) -> VacuumModes:
|
|
221
|
+
"""Determine the vacuum mode to use when you just want to mop.
|
|
222
|
+
|
|
223
|
+
There are three cases that must be handled:
|
|
224
|
+
1. The device does not support only mopping.
|
|
225
|
+
2. The device supports raising the vacuum brush while mopping
|
|
226
|
+
3. All other cases.
|
|
227
|
+
"""
|
|
228
|
+
if not features.is_pure_clean_mop_supported:
|
|
229
|
+
raise RoborockUnsupportedFeature("Mop-only cleaning is not supported")
|
|
230
|
+
if features.is_support_main_brush_up_down_supported:
|
|
231
|
+
return VacuumModes.OFF_RAISE_MAIN_BRUSH
|
|
232
|
+
return VacuumModes.OFF
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _get_default_mopping_water_mode(features: DeviceFeatures) -> WaterModes:
|
|
236
|
+
"""Pick a sensible default water mode when mopping for the device."""
|
|
237
|
+
# Water-slide devices use a disjoint set of water codes; pick a mid-flow
|
|
238
|
+
# slide code instead of the standard 202, which they don't accept.
|
|
239
|
+
if features.is_water_slide_mode_supported:
|
|
240
|
+
return WaterModes.PURE_WATER_FLOW_MIDDLE
|
|
241
|
+
return WaterModes.STANDARD
|
|
242
|
+
|
|
243
|
+
|
|
244
|
+
def _get_clean_motor_mode_params(
|
|
245
|
+
mode: CleaningMode,
|
|
246
|
+
features: DeviceFeatures,
|
|
247
|
+
) -> tuple[VacuumModes, WaterModes, CleanRoutes]:
|
|
248
|
+
"""Return (fan_power, water_box_mode, mop_mode) enums for the high-level mode."""
|
|
249
|
+
if mode == CleaningMode.VACUUM:
|
|
250
|
+
return (VacuumModes.BALANCED, WaterModes.OFF, CleanRoutes.STANDARD)
|
|
251
|
+
if mode == CleaningMode.VAC_AND_MOP:
|
|
252
|
+
return (VacuumModes.BALANCED, _get_default_mopping_water_mode(features), CleanRoutes.STANDARD)
|
|
253
|
+
if mode == CleaningMode.MOP:
|
|
254
|
+
return (
|
|
255
|
+
get_mop_only_vacuum_mode(features),
|
|
256
|
+
_get_default_mopping_water_mode(features),
|
|
257
|
+
CleanRoutes.STANDARD,
|
|
258
|
+
)
|
|
259
|
+
if mode == CleaningMode.CUSTOM:
|
|
260
|
+
return (VacuumModes.CUSTOMIZED, WaterModes.CUSTOMIZED, CleanRoutes.CUSTOMIZED)
|
|
261
|
+
if mode == CleaningMode.SMART_MODE:
|
|
262
|
+
return (VacuumModes.SMART_MODE, WaterModes.SMART_MODE, CleanRoutes.SMART_MODE)
|
|
263
|
+
raise RoborockUnsupportedFeature(f"Cleaning mode {mode.value!r} is not supported")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def resolve_cleaning_mode(cleaning_mode: str | CleaningMode) -> CleaningMode:
|
|
267
|
+
"""Resolve a string or enum into a CleaningMode value."""
|
|
268
|
+
if isinstance(cleaning_mode, CleaningMode):
|
|
269
|
+
return cleaning_mode
|
|
270
|
+
try:
|
|
271
|
+
return CleaningMode(cleaning_mode)
|
|
272
|
+
except ValueError as err:
|
|
273
|
+
raise RoborockUnsupportedFeature(f"Cleaning mode {cleaning_mode!r} is not supported") from err
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def get_cleaning_mode_parameters(cleaning_mode: CleaningMode, features: DeviceFeatures) -> list[dict[str, int]]:
|
|
277
|
+
"""Get the RPC payload for switching the high-level cleaning mode."""
|
|
278
|
+
if cleaning_mode not in get_cleaning_mode_options(features):
|
|
279
|
+
raise RoborockUnsupportedFeature(f"Cleaning mode {cleaning_mode.value!r} is not supported")
|
|
280
|
+
|
|
281
|
+
fan_power, water_box_mode, mop_mode = _get_clean_motor_mode_params(cleaning_mode, features)
|
|
282
|
+
params: dict[str, int] = {"fan_power": fan_power.code, "water_box_mode": water_box_mode.code}
|
|
283
|
+
if features.is_clean_route_setting_supported:
|
|
284
|
+
params["mop_mode"] = mop_mode.code
|
|
285
|
+
return [params]
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
def _resolve_mode_code(value: int | ModeEnumT | None, mode_cls: type[ModeEnumT]) -> ModeEnumT | None:
|
|
289
|
+
"""Resolve a raw code or enum into a RoborockModeEnum."""
|
|
290
|
+
if value is None:
|
|
291
|
+
return None
|
|
292
|
+
if isinstance(value, mode_cls):
|
|
293
|
+
return value
|
|
294
|
+
return mode_cls.from_code_optional(int(value))
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def _resolve_clean_mode(value: int | VacuumModes | None, features: DeviceFeatures) -> VacuumModes | None:
|
|
298
|
+
"""Resolve a vacuum mode code, accounting for feature-specific code aliases."""
|
|
299
|
+
if value is None or isinstance(value, VacuumModes):
|
|
300
|
+
return value
|
|
301
|
+
if value == VacuumModes.OFF.code:
|
|
302
|
+
if features.is_pure_clean_mop_supported:
|
|
303
|
+
return get_mop_only_vacuum_mode(features)
|
|
304
|
+
return VacuumModes.GENTLE
|
|
305
|
+
return VacuumModes.from_code_optional(value)
|
|
306
|
+
|
|
307
|
+
|
|
308
|
+
def get_current_cleaning_mode(
|
|
309
|
+
clean_mode: int | VacuumModes | None,
|
|
310
|
+
water_mode: int | WaterModes | None,
|
|
311
|
+
mop_mode: int | CleanRoutes | None,
|
|
312
|
+
features: DeviceFeatures,
|
|
313
|
+
) -> CleaningMode | None:
|
|
314
|
+
"""Classify the current high-level cleaning mode from individual mode codes."""
|
|
315
|
+
if not features.is_support_water_mode:
|
|
316
|
+
return None
|
|
317
|
+
clean_mode_enum = _resolve_clean_mode(clean_mode, features)
|
|
318
|
+
water_mode_enum = _resolve_mode_code(water_mode, WaterModes)
|
|
319
|
+
mop_mode_enum = _resolve_mode_code(mop_mode, CleanRoutes)
|
|
320
|
+
if clean_mode_enum is None or water_mode_enum is None:
|
|
321
|
+
return None
|
|
322
|
+
|
|
323
|
+
if is_smart_mode_set(water_mode_enum, clean_mode_enum, mop_mode_enum):
|
|
324
|
+
return CleaningMode.SMART_MODE
|
|
325
|
+
if is_mode_customized(clean_mode_enum, water_mode_enum, mop_mode_enum):
|
|
326
|
+
return CleaningMode.CUSTOM
|
|
327
|
+
if water_mode_enum != WaterModes.OFF:
|
|
328
|
+
try:
|
|
329
|
+
if clean_mode_enum == get_mop_only_vacuum_mode(features):
|
|
330
|
+
return CleaningMode.MOP
|
|
331
|
+
except RoborockUnsupportedFeature:
|
|
332
|
+
pass
|
|
333
|
+
if water_mode_enum == WaterModes.OFF:
|
|
334
|
+
return CleaningMode.VACUUM
|
|
335
|
+
return CleaningMode.VAC_AND_MOP
|
|
336
|
+
|
|
337
|
+
|
|
338
|
+
def is_mode_customized(
|
|
339
|
+
clean_mode: VacuumModes | None,
|
|
340
|
+
water_mode: WaterModes | None,
|
|
341
|
+
mop_mode: CleanRoutes | None,
|
|
342
|
+
) -> bool:
|
|
343
|
+
"""Check if any of the cleaning modes are set to a custom value."""
|
|
344
|
+
return (
|
|
345
|
+
clean_mode == VacuumModes.CUSTOMIZED
|
|
346
|
+
or water_mode == WaterModes.CUSTOMIZED
|
|
347
|
+
or mop_mode == CleanRoutes.CUSTOMIZED
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def is_smart_mode_set(
|
|
352
|
+
water_mode: WaterModes | None,
|
|
353
|
+
clean_mode: VacuumModes | None,
|
|
354
|
+
mop_mode: CleanRoutes | None,
|
|
355
|
+
) -> bool:
|
|
356
|
+
"""Check if the smart mode is set for the given water mode and clean mode"""
|
|
357
|
+
return (
|
|
358
|
+
water_mode == WaterModes.SMART_MODE
|
|
359
|
+
or clean_mode == VacuumModes.SMART_MODE
|
|
360
|
+
or mop_mode == CleanRoutes.SMART_MODE
|
|
361
|
+
)
|
|
@@ -3,14 +3,19 @@ from functools import cached_property
|
|
|
3
3
|
from typing import Any
|
|
4
4
|
|
|
5
5
|
from roborock import (
|
|
6
|
+
CleaningMode,
|
|
6
7
|
CleanRoutes,
|
|
7
8
|
StatusV2,
|
|
8
9
|
VacuumModes,
|
|
9
10
|
WaterModes,
|
|
10
11
|
get_clean_modes,
|
|
11
12
|
get_clean_routes,
|
|
13
|
+
get_cleaning_mode_options,
|
|
14
|
+
get_cleaning_mode_parameters,
|
|
15
|
+
get_current_cleaning_mode,
|
|
12
16
|
get_water_mode_mapping,
|
|
13
17
|
get_water_modes,
|
|
18
|
+
resolve_cleaning_mode,
|
|
14
19
|
)
|
|
15
20
|
from roborock.devices.traits.common import DpsDataConverter, TraitUpdateListener
|
|
16
21
|
from roborock.roborock_message import RoborockDataProtocol
|
|
@@ -42,10 +47,11 @@ class StatusTrait(StatusV2, common.V1TraitMixin, TraitUpdateListener):
|
|
|
42
47
|
- Water Mode
|
|
43
48
|
- Mop Route
|
|
44
49
|
|
|
45
|
-
You should
|
|
46
|
-
(i.e. fan_speed_options
|
|
47
|
-
Then you can
|
|
48
|
-
|
|
50
|
+
You should use the _options version of the attribute to know which are
|
|
51
|
+
supported for your device (i.e. fan_speed_options)
|
|
52
|
+
Then you can use the _mapping to convert an int value to the actual Enum.
|
|
53
|
+
(i.e. fan_speed_mapping)
|
|
54
|
+
You can use the _name property to get the str value of the enum. (i.e. fan_speed_name)
|
|
49
55
|
|
|
50
56
|
"""
|
|
51
57
|
|
|
@@ -83,6 +89,10 @@ class StatusTrait(StatusV2, common.V1TraitMixin, TraitUpdateListener):
|
|
|
83
89
|
def mop_route_mapping(self) -> dict[int, str]:
|
|
84
90
|
return {route.code: route.value for route in self.mop_route_options}
|
|
85
91
|
|
|
92
|
+
@cached_property
|
|
93
|
+
def cleaning_mode_options(self) -> list[CleaningMode]:
|
|
94
|
+
return get_cleaning_mode_options(self._device_features_trait)
|
|
95
|
+
|
|
86
96
|
@property
|
|
87
97
|
def fan_speed_name(self) -> str | None:
|
|
88
98
|
if self.fan_power is None:
|
|
@@ -101,6 +111,28 @@ class StatusTrait(StatusV2, common.V1TraitMixin, TraitUpdateListener):
|
|
|
101
111
|
return None
|
|
102
112
|
return self.mop_route_mapping.get(self.mop_mode)
|
|
103
113
|
|
|
114
|
+
@property
|
|
115
|
+
def current_cleaning_mode(self) -> CleaningMode | None:
|
|
116
|
+
return get_current_cleaning_mode(
|
|
117
|
+
clean_mode=self.fan_power,
|
|
118
|
+
water_mode=self.water_box_mode,
|
|
119
|
+
mop_mode=self.mop_mode,
|
|
120
|
+
features=self._device_features_trait,
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
@property
|
|
124
|
+
def current_cleaning_mode_name(self) -> str | None:
|
|
125
|
+
if (cleaning_mode := self.current_cleaning_mode) is None:
|
|
126
|
+
return None
|
|
127
|
+
return cleaning_mode.value
|
|
128
|
+
|
|
129
|
+
async def set_cleaning_mode(self, cleaning_mode: str | CleaningMode) -> None:
|
|
130
|
+
"""Set the preferred high-level cleaning mode for the device."""
|
|
131
|
+
await self.rpc_channel.send_command(
|
|
132
|
+
RoborockCommand.SET_CLEAN_MOTOR_MODE,
|
|
133
|
+
params=get_cleaning_mode_parameters(resolve_cleaning_mode(cleaning_mode), self._device_features_trait),
|
|
134
|
+
)
|
|
135
|
+
|
|
104
136
|
def update_from_dps(self, decoded_dps: dict[RoborockDataProtocol, Any]) -> None:
|
|
105
137
|
"""Update the trait from data protocol push message data.
|
|
106
138
|
|
|
@@ -40,6 +40,45 @@ class RoborockDataProtocol(RoborockEnum):
|
|
|
40
40
|
raise ValueError(f"{key} not a valid key for Data Protocol")
|
|
41
41
|
|
|
42
42
|
|
|
43
|
+
class RoborockMowerDataProtocol(RoborockEnum):
|
|
44
|
+
UNKNOWN = 0
|
|
45
|
+
ERROR_CODE = 120
|
|
46
|
+
BATTERY = 121
|
|
47
|
+
MOW_TYPE = 122
|
|
48
|
+
MOW_STATE = 123
|
|
49
|
+
MAPPING_TYPE = 124
|
|
50
|
+
MAPPING_STATE = 125
|
|
51
|
+
OTA_STATE = 126
|
|
52
|
+
CHARGE_STATE = 127
|
|
53
|
+
DOCK_STATE = 128
|
|
54
|
+
CHARGE_TYPE = 129
|
|
55
|
+
PEND_TYPE = 130
|
|
56
|
+
REMOTE_STATE = 131
|
|
57
|
+
MOW_START_TYPE = 132
|
|
58
|
+
MOW_EFF_MODE = 133
|
|
59
|
+
MOW_HEIGHT = 134
|
|
60
|
+
MOW_DIRECTION_ANGLE = 135
|
|
61
|
+
MOW_PATTERN = 136
|
|
62
|
+
MOW_CONF_MODE = 137
|
|
63
|
+
OFFLINE_STATUS = 138
|
|
64
|
+
MOW_PROGRESS = 139
|
|
65
|
+
BLADE_LIFESPAN = 140
|
|
66
|
+
FC_STATE = 141
|
|
67
|
+
GPS_COORDINATE = 142
|
|
68
|
+
OFF_DOCK_NO_TASK_STATUS = 143
|
|
69
|
+
AFS_STATUS = 144
|
|
70
|
+
NETWORK_CHANNEL = 145
|
|
71
|
+
START = 201
|
|
72
|
+
DOCK = 202
|
|
73
|
+
PAUSE = 203
|
|
74
|
+
RESUME = 204
|
|
75
|
+
STOP = 205
|
|
76
|
+
|
|
77
|
+
@classmethod
|
|
78
|
+
def _missing_(cls: type[Self], key) -> Self:
|
|
79
|
+
raise ValueError(f"{key} not a valid key for Mower Data Protocol")
|
|
80
|
+
|
|
81
|
+
|
|
43
82
|
class RoborockDyadDataProtocol(RoborockEnum):
|
|
44
83
|
DRYING_STATUS = 134
|
|
45
84
|
START = 200
|
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
import typing
|
|
4
|
-
|
|
5
|
-
from ..code_mappings import RoborockModeEnum
|
|
6
|
-
|
|
7
|
-
if typing.TYPE_CHECKING:
|
|
8
|
-
from roborock.device_features import DeviceFeatures
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class VacuumModes(RoborockModeEnum):
|
|
12
|
-
GENTLE = ("gentle", 105)
|
|
13
|
-
OFF = ("off", 105)
|
|
14
|
-
QUIET = ("quiet", 101)
|
|
15
|
-
BALANCED = ("balanced", 102)
|
|
16
|
-
TURBO = ("turbo", 103)
|
|
17
|
-
MAX = ("max", 104)
|
|
18
|
-
MAX_PLUS = ("max_plus", 108)
|
|
19
|
-
OFF_RAISE_MAIN_BRUSH = ("off_raise_main_brush", 109)
|
|
20
|
-
CUSTOMIZED = ("custom", 106)
|
|
21
|
-
SMART_MODE = ("smart_mode", 110)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
class CleanRoutes(RoborockModeEnum):
|
|
25
|
-
STANDARD = ("standard", 300)
|
|
26
|
-
DEEP = ("deep", 301)
|
|
27
|
-
DEEP_PLUS = ("deep_plus", 303)
|
|
28
|
-
FAST = ("fast", 304)
|
|
29
|
-
DEEP_PLUS_CN = ("deep_plus", 305)
|
|
30
|
-
SMART_MODE = ("smart_mode", 306)
|
|
31
|
-
CUSTOMIZED = ("custom", 302)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
class VacuumModesOld(RoborockModeEnum):
|
|
35
|
-
QUIET = ("quiet", 38)
|
|
36
|
-
BALANCED = ("balanced", 60)
|
|
37
|
-
TURBO = ("turbo", 75)
|
|
38
|
-
MAX = ("max", 100)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class WaterModes(RoborockModeEnum):
|
|
42
|
-
OFF = ("off", 200)
|
|
43
|
-
LOW = ("low", 201)
|
|
44
|
-
MILD = ("mild", 201)
|
|
45
|
-
MEDIUM = ("medium", 202)
|
|
46
|
-
STANDARD = ("standard", 202)
|
|
47
|
-
HIGH = ("high", 203)
|
|
48
|
-
INTENSE = ("intense", 203)
|
|
49
|
-
MIN = ("min", 205)
|
|
50
|
-
MAX = ("max", 206)
|
|
51
|
-
CUSTOMIZED = ("custom", 204)
|
|
52
|
-
CUSTOM = ("custom_water_flow", 207)
|
|
53
|
-
EXTREME = ("extreme", 208)
|
|
54
|
-
SMART_MODE = ("smart_mode", 209)
|
|
55
|
-
PURE_WATER_FLOW_START = ("slight", 221)
|
|
56
|
-
PURE_WATER_FLOW_SMALL = ("low", 225)
|
|
57
|
-
PURE_WATER_FLOW_MIDDLE = ("medium", 235)
|
|
58
|
-
PURE_WATER_FLOW_LARGE = ("moderate", 245)
|
|
59
|
-
PURE_WATER_SUPER_BEGIN = ("high", 248)
|
|
60
|
-
PURE_WATER_FLOW_END = ("extreme", 250)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class WashTowelModes(RoborockModeEnum):
|
|
64
|
-
SMART = ("smart", 10)
|
|
65
|
-
LIGHT = ("light", 0)
|
|
66
|
-
BALANCED = ("balanced", 1)
|
|
67
|
-
DEEP = ("deep", 2)
|
|
68
|
-
SUPER_DEEP = ("super_deep", 8)
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
WATER_SLIDE_MODE_MAPPING: dict[int, WaterModes] = {
|
|
72
|
-
200: WaterModes.OFF,
|
|
73
|
-
221: WaterModes.PURE_WATER_FLOW_START,
|
|
74
|
-
225: WaterModes.PURE_WATER_FLOW_SMALL,
|
|
75
|
-
235: WaterModes.PURE_WATER_FLOW_MIDDLE,
|
|
76
|
-
245: WaterModes.PURE_WATER_FLOW_LARGE,
|
|
77
|
-
248: WaterModes.PURE_WATER_SUPER_BEGIN,
|
|
78
|
-
250: WaterModes.PURE_WATER_FLOW_END,
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def get_wash_towel_modes(features: DeviceFeatures) -> list[WashTowelModes]:
|
|
83
|
-
"""Get the valid wash towel modes for the device"""
|
|
84
|
-
modes = [WashTowelModes.LIGHT, WashTowelModes.BALANCED, WashTowelModes.DEEP]
|
|
85
|
-
if features.is_super_deep_wash_supported and not features.is_dirty_replenish_clean_supported:
|
|
86
|
-
modes.append(WashTowelModes.SUPER_DEEP)
|
|
87
|
-
elif features.is_dirty_replenish_clean_supported:
|
|
88
|
-
modes.append(WashTowelModes.SMART)
|
|
89
|
-
return modes
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
def get_clean_modes(features: DeviceFeatures) -> list[VacuumModes]:
|
|
93
|
-
"""Get the valid clean modes for the device - also known as 'fan power' or 'suction mode'"""
|
|
94
|
-
modes = [VacuumModes.QUIET, VacuumModes.BALANCED, VacuumModes.TURBO, VacuumModes.MAX]
|
|
95
|
-
if features.is_max_plus_mode_supported or features.is_none_pure_clean_mop_with_max_plus:
|
|
96
|
-
# If the vacuum has max plus mode supported
|
|
97
|
-
modes.append(VacuumModes.MAX_PLUS)
|
|
98
|
-
if features.is_pure_clean_mop_supported:
|
|
99
|
-
# If the vacuum is capable of 'pure mop clean' aka no vacuum
|
|
100
|
-
if features.is_support_main_brush_up_down_supported:
|
|
101
|
-
modes.append(VacuumModes.OFF_RAISE_MAIN_BRUSH)
|
|
102
|
-
else:
|
|
103
|
-
modes.append(VacuumModes.OFF)
|
|
104
|
-
else:
|
|
105
|
-
# If not, we can add gentle
|
|
106
|
-
modes.append(VacuumModes.GENTLE)
|
|
107
|
-
if features.is_smart_clean_mode_set_supported:
|
|
108
|
-
modes.append(VacuumModes.SMART_MODE)
|
|
109
|
-
if features.is_customized_clean_supported:
|
|
110
|
-
modes.append(VacuumModes.CUSTOMIZED)
|
|
111
|
-
return modes
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def get_clean_routes(features: DeviceFeatures, region: str) -> list[CleanRoutes]:
|
|
115
|
-
"""The routes that the vacuum will take while mopping"""
|
|
116
|
-
if features.is_none_pure_clean_mop_with_max_plus:
|
|
117
|
-
return [CleanRoutes.FAST, CleanRoutes.STANDARD]
|
|
118
|
-
supported = [CleanRoutes.STANDARD, CleanRoutes.DEEP]
|
|
119
|
-
if features.is_careful_slow_mop_supported:
|
|
120
|
-
if not (
|
|
121
|
-
features.is_corner_clean_mode_supported
|
|
122
|
-
and features.is_clean_route_deep_slow_plus_supported
|
|
123
|
-
and region == "cn"
|
|
124
|
-
):
|
|
125
|
-
# for some reason there is a china specific deep plus mode
|
|
126
|
-
supported.append(CleanRoutes.DEEP_PLUS_CN)
|
|
127
|
-
else:
|
|
128
|
-
supported.append(CleanRoutes.DEEP_PLUS)
|
|
129
|
-
|
|
130
|
-
if features.is_clean_route_fast_mode_supported:
|
|
131
|
-
supported.append(CleanRoutes.FAST)
|
|
132
|
-
if features.is_smart_clean_mode_set_supported:
|
|
133
|
-
supported.append(CleanRoutes.SMART_MODE)
|
|
134
|
-
if features.is_customized_clean_supported:
|
|
135
|
-
supported.append(CleanRoutes.CUSTOMIZED)
|
|
136
|
-
|
|
137
|
-
return supported
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
def get_water_modes(features: DeviceFeatures) -> list[WaterModes]:
|
|
141
|
-
"""Get the valid water modes for the device - also known as 'water flow' or 'water level'"""
|
|
142
|
-
# Water slide mode supports a separate set of water flow codes.
|
|
143
|
-
if features.is_water_slide_mode_supported:
|
|
144
|
-
return list(WATER_SLIDE_MODE_MAPPING.values())
|
|
145
|
-
|
|
146
|
-
supported_modes = [WaterModes.OFF]
|
|
147
|
-
if features.is_mop_shake_module_supported:
|
|
148
|
-
# For mops that have the vibrating mop pad, they do mild standard intense
|
|
149
|
-
supported_modes.extend([WaterModes.MILD, WaterModes.STANDARD, WaterModes.INTENSE])
|
|
150
|
-
else:
|
|
151
|
-
supported_modes.extend([WaterModes.LOW, WaterModes.MEDIUM, WaterModes.HIGH])
|
|
152
|
-
if features.is_custom_water_box_distance_supported:
|
|
153
|
-
# This is for devices that allow you to set a custom water flow from 0-100
|
|
154
|
-
supported_modes.append(WaterModes.CUSTOM)
|
|
155
|
-
if features.is_mop_shake_module_supported and features.is_mop_shake_water_max_supported:
|
|
156
|
-
supported_modes.append(WaterModes.EXTREME)
|
|
157
|
-
if features.is_smart_clean_mode_set_supported:
|
|
158
|
-
supported_modes.append(WaterModes.SMART_MODE)
|
|
159
|
-
if features.is_customized_clean_supported:
|
|
160
|
-
supported_modes.append(WaterModes.CUSTOMIZED)
|
|
161
|
-
|
|
162
|
-
return supported_modes
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
def get_water_mode_mapping(features: DeviceFeatures) -> dict[int, str]:
|
|
166
|
-
"""Get water mode mapping by supported feature set.
|
|
167
|
-
|
|
168
|
-
WaterModes contains aliases for multiple codes that share the same value
|
|
169
|
-
string (e.g. low can be 201 or 225). For water slide mode devices we need
|
|
170
|
-
explicit code mapping to preserve those slide-specific codes.
|
|
171
|
-
"""
|
|
172
|
-
if features.is_water_slide_mode_supported:
|
|
173
|
-
return {code: mode.value for code, mode in WATER_SLIDE_MODE_MAPPING.items()}
|
|
174
|
-
return {mode.code: mode.value for mode in get_water_modes(features)}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
def is_mode_customized(clean_mode: VacuumModes, water_mode: WaterModes, mop_mode: CleanRoutes) -> bool:
|
|
178
|
-
"""Check if any of the cleaning modes are set to a custom value."""
|
|
179
|
-
return (
|
|
180
|
-
clean_mode == VacuumModes.CUSTOMIZED
|
|
181
|
-
or water_mode == WaterModes.CUSTOMIZED
|
|
182
|
-
or mop_mode == CleanRoutes.CUSTOMIZED
|
|
183
|
-
)
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
def is_smart_mode_set(water_mode: WaterModes, clean_mode: VacuumModes, mop_mode: CleanRoutes) -> bool:
|
|
187
|
-
"""Check if the smart mode is set for the given water mode and clean mode"""
|
|
188
|
-
return (
|
|
189
|
-
water_mode == WaterModes.SMART_MODE
|
|
190
|
-
or clean_mode == VacuumModes.SMART_MODE
|
|
191
|
-
or mop_mode == CleanRoutes.SMART_MODE
|
|
192
|
-
)
|
|
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-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q10/b01_q10_code_mappings.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/data/b01_q10/b01_q10_containers.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.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
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/__init__.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/button_light.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/child_lock.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/clean_history.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/command.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/consumable.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/do_not_disturb.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/dust_collection.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q10/network_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/__init__.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/b01/q7/map_content.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/clean_summary.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/device_features.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/do_not_disturb.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/dust_collection_mode.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.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-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/network_info.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/smart_wash_params.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/traits/v1/wash_towel_mode.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.0}/roborock/devices/transport/local_channel.py
RENAMED
|
File without changes
|
{python_roborock-5.24.0 → python_roborock-5.25.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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|