Skip to content

Commit 8611c2b

Browse files
authored
Merge branch 'main' into leo/q7-map-content-followup
2 parents 99a63e6 + d762649 commit 8611c2b

26 files changed

+232
-77
lines changed

CHANGELOG.md

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,104 @@
22

33
<!-- version list -->
44

5+
## v5.0.0 (2026-03-22)
6+
7+
### Bug Fixes
8+
9+
- **cli**: Make clean mode option case insensitive
10+
([#794](https://github.com/Python-roborock/python-roborock/pull/794),
11+
[`7baeb65`](https://github.com/Python-roborock/python-roborock/commit/7baeb658fd80b40bfb631dc250b899e659e20210))
12+
13+
- **q10**: Restrict clean mode cli choices
14+
([#794](https://github.com/Python-roborock/python-roborock/pull/794),
15+
[`7baeb65`](https://github.com/Python-roborock/python-roborock/commit/7baeb658fd80b40bfb631dc250b899e659e20210))
16+
17+
### Features
18+
19+
- **api**: Again rename `YXDeviceState` enum members to have consistency with V1 state values
20+
([#795](https://github.com/Python-roborock/python-roborock/pull/795),
21+
[`ad3ceea`](https://github.com/Python-roborock/python-roborock/commit/ad3ceeaea6f1b12dc51513c48476bcdf2756392b))
22+
23+
- **api**: Rename `YXWaterLevel` enum values to mirror v1 values
24+
([#796](https://github.com/Python-roborock/python-roborock/pull/796),
25+
[`c630022`](https://github.com/Python-roborock/python-roborock/commit/c63002264e40beb0f6e51281afd90e10e7b731cc))
26+
27+
### Refactoring
28+
29+
- **q10**: Use readable YXCleanType values with legacy aliases
30+
([#794](https://github.com/Python-roborock/python-roborock/pull/794),
31+
[`7baeb65`](https://github.com/Python-roborock/python-roborock/commit/7baeb658fd80b40bfb631dc250b899e659e20210))
32+
33+
- **YXCleanType**: Move legacy values to a separate dictionary and update from_value method
34+
([#794](https://github.com/Python-roborock/python-roborock/pull/794),
35+
[`7baeb65`](https://github.com/Python-roborock/python-roborock/commit/7baeb658fd80b40bfb631dc250b899e659e20210))
36+
37+
- **YXCleanType**: Remove legacy test for readable public values
38+
([#794](https://github.com/Python-roborock/python-roborock/pull/794),
39+
[`7baeb65`](https://github.com/Python-roborock/python-roborock/commit/7baeb658fd80b40bfb631dc250b899e659e20210))
40+
41+
- **YXCleanType**: Simplify clean type definitions and remove legacy alias support
42+
([#794](https://github.com/Python-roborock/python-roborock/pull/794),
43+
[`7baeb65`](https://github.com/Python-roborock/python-roborock/commit/7baeb658fd80b40bfb631dc250b899e659e20210))
44+
45+
46+
## v4.26.3 (2026-03-22)
47+
48+
### Bug Fixes
49+
50+
- **q10**: Add tests for Q10 status values and code mappings
51+
([#793](https://github.com/Python-roborock/python-roborock/pull/793),
52+
[`dce00a2`](https://github.com/Python-roborock/python-roborock/commit/dce00a2499c3976f1cd25239bc4f81d996d51a79))
53+
54+
- **q10**: Normalize status names to canonical values
55+
([#793](https://github.com/Python-roborock/python-roborock/pull/793),
56+
[`dce00a2`](https://github.com/Python-roborock/python-roborock/commit/dce00a2499c3976f1cd25239bc4f81d996d51a79))
57+
58+
- **q10**: Normalize YXDeviceState status names to canonical values
59+
([#793](https://github.com/Python-roborock/python-roborock/pull/793),
60+
[`dce00a2`](https://github.com/Python-roborock/python-roborock/commit/dce00a2499c3976f1cd25239bc4f81d996d51a79))
61+
62+
- **q10**: Refactor test for canonical status names using a dictionary
63+
([#793](https://github.com/Python-roborock/python-roborock/pull/793),
64+
[`dce00a2`](https://github.com/Python-roborock/python-roborock/commit/dce00a2499c3976f1cd25239bc4f81d996d51a79))
65+
66+
67+
## v4.26.2 (2026-03-21)
68+
69+
### Bug Fixes
70+
71+
- **q10**: Add missing fault field to Q10Status
72+
([#792](https://github.com/Python-roborock/python-roborock/pull/792),
73+
[`66d76fc`](https://github.com/Python-roborock/python-roborock/commit/66d76fc9b3cd6d6d15f5883bfa8a22c688d9b960))
74+
75+
76+
## v4.26.1 (2026-03-21)
77+
78+
### Bug Fixes
79+
80+
- Add missing DPS fields to Q10Status and fix CLEAN_PROGRESS mapping
81+
([#791](https://github.com/Python-roborock/python-roborock/pull/791),
82+
[`526da01`](https://github.com/Python-roborock/python-roborock/commit/526da01d02f6b52cab3674145273448eb602620e))
83+
84+
- Correct comment for fan level in test_status_trait_refresh
85+
([#791](https://github.com/Python-roborock/python-roborock/pull/791),
86+
[`526da01`](https://github.com/Python-roborock/python-roborock/commit/526da01d02f6b52cab3674145273448eb602620e))
87+
88+
### Chores
89+
90+
- Disable commitlint rules for header max length and header full stop.
91+
([#789](https://github.com/Python-roborock/python-roborock/pull/789),
92+
[`711f49e`](https://github.com/Python-roborock/python-roborock/commit/711f49e9a6e4d7fc964b164c7f23265979aa166b))
93+
94+
- Increase commit header maximum length to 200
95+
([#789](https://github.com/Python-roborock/python-roborock/pull/789),
96+
[`711f49e`](https://github.com/Python-roborock/python-roborock/commit/711f49e9a6e4d7fc964b164c7f23265979aa166b))
97+
98+
- Increase commit header maximum length to 200 in commitlint configuration.
99+
([#789](https://github.com/Python-roborock/python-roborock/pull/789),
100+
[`711f49e`](https://github.com/Python-roborock/python-roborock/commit/711f49e9a6e4d7fc964b164c7f23265979aa166b))
101+
102+
5103
## v4.26.0 (2026-03-19)
6104

7105
### Features

commitlint.config.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ export default {
88
// Disable the rule that enforces lowercase in subject
99
"subject-case": [0], // 0 = disable, 1 = warn, 2 = error
1010
// Disable the rule that enforces a maximum line length in the body
11-
"body-max-line-length": [0, "always"]
11+
"body-max-line-length": [0, "always"],
12+
// Disable header max length for AI-generated commits
13+
"header-max-length": [0],
14+
// Disable the rule that prevents periods at the end of subjects
15+
"header-full-stop": [0]
1216
},
1317

1418
};

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "python-roborock"
3-
version = "4.26.0"
3+
version = "5.0.0"
44
description = "A package to control Roborock vacuums."
55
authors = [{ name = "humbertogontijo", email = "humbertogontijo@users.noreply.github.com" }, {name="Lash-L"}, {name="allenporter"}]
66
requires-python = ">=3.11, <4"

roborock/broadcast_protocol.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from __future__ import annotations
2-
31
import asyncio
42
import hashlib
53
import json

roborock/cli.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1275,7 +1275,12 @@ async def q10_empty_dustbin(ctx: click.Context, device_id: str) -> None:
12751275

12761276
@session.command()
12771277
@click.option("--device_id", required=True, help="Device ID")
1278-
@click.option("--mode", required=True, type=click.Choice(["bothwork", "onlysweep", "onlymop"]), help="Clean mode")
1278+
@click.option(
1279+
"--mode",
1280+
required=True,
1281+
type=click.Choice(["vac_and_mop", "vacuum", "mop"], case_sensitive=False),
1282+
help='Clean mode (preferred: "vac_and_mop", "vacuum", "mop")',
1283+
)
12791284
@click.pass_context
12801285
@async_command
12811286
async def q10_set_clean_mode(ctx: click.Context, device_id: str, mode: str) -> None:

roborock/data/b01_q10/b01_q10_code_mappings.py

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,9 @@ class YXFanLevel(RoborockModeEnum):
136136

137137
class YXWaterLevel(RoborockModeEnum):
138138
UNKNOWN = "unknown", -1
139-
CLOSE = "close", 0
139+
OFF = "off", 0 # close
140140
LOW = "low", 1
141-
MIDDLE = "middle", 2
141+
MEDIUM = "medium", 2 # middle
142142
HIGH = "high", 3
143143

144144

@@ -157,31 +157,31 @@ class YXRoomMaterial(RoborockModeEnum):
157157

158158
class YXCleanType(RoborockModeEnum):
159159
UNKNOWN = "unknown", -1
160-
BOTH_WORK = "bothwork", 1
161-
ONLY_SWEEP = "onlysweep", 2
162-
ONLY_MOP = "onlymop", 3
160+
VAC_AND_MOP = "vac_and_mop", 1 # bothwork
161+
VACUUM = "vacuum", 2 # onlysweep
162+
MOP = "mop", 3 # onlymop
163163

164164

165165
class YXDeviceState(RoborockModeEnum):
166166
UNKNOWN = "unknown", -1
167-
SLEEP_STATE = "sleepstate", 2
168-
STANDBY_STATE = "standbystate", 3
169-
CLEANING_STATE = "cleaningstate", 5
170-
TO_CHARGE_STATE = "tochargestate", 6
171-
REMOTEING_STATE = "remoteingstate", 7
172-
CHARGING_STATE = "chargingstate", 8
173-
PAUSE_STATE = "pausestate", 10
174-
FAULT_STATE = "faultstate", 12
175-
UPGRADE_STATE = "upgradestate", 14
176-
DUSTING = "dusting", 22
177-
CREATING_MAP_STATE = "creatingmapstate", 29
178-
MAP_SAVE_STATE = "mapsavestate", 99
179-
RE_LOCATION_STATE = "relocationstate", 101
180-
ROBOT_SWEEPING = "robotsweeping", 102
181-
ROBOT_MOPING = "robotmoping", 103
182-
ROBOT_SWEEP_AND_MOPING = "robotsweepandmoping", 104
183-
ROBOT_TRANSITIONING = "robottransitioning", 105
184-
ROBOT_WAIT_CHARGE = "robotwaitcharge", 108
167+
SLEEPING = "sleeping", 2 # sleepstate
168+
IDLE = "idle", 3 # standbystate
169+
CLEANING = "cleaning", 5 # cleaningstate
170+
RETURNING_HOME = "returning_home", 6 # tochargestate
171+
REMOTE_CONTROL_ACTIVE = "remote_control_active", 7 # remoteingstate
172+
CHARGING = "charging", 8 # chargingstate
173+
PAUSED = "paused", 10 # pausestate
174+
ERROR = "error", 12 # faultstate
175+
UPDATING = "updating", 14 # upgradestate
176+
EMPTYING_THE_BIN = "emptying_the_bin", 22 # dusting
177+
MAPPING = "mapping", 29 # creatingmapstate
178+
SAVING_MAP = "saving_map", 99 # mapsavestate
179+
RELOCATING = "relocating", 101 # relocationstate
180+
SWEEPING = "sweeping", 102 # robotsweeping
181+
MOPPING = "mopping", 103 # robotmoping
182+
SWEEP_AND_MOP = "sweep_and_mop", 104 # robotsweepandmoping
183+
TRANSITIONING = "transitioning", 105 # robottransitioning
184+
WAITING_TO_CHARGE = "waiting_to_charge", 108 # robotwaitcharge
185185

186186

187187
class YXBackType(RoborockModeEnum):

roborock/data/b01_q10/b01_q10_containers.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,15 @@ class Q10Status(RoborockBase):
9696
fan_level: YXFanLevel | None = field(default=None, metadata={"dps": B01_Q10_DP.FAN_LEVEL})
9797
water_level: YXWaterLevel | None = field(default=None, metadata={"dps": B01_Q10_DP.WATER_LEVEL})
9898
clean_count: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_COUNT})
99+
total_clean_area: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_AREA})
100+
total_clean_count: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_COUNT})
101+
total_clean_time: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_TIME})
102+
main_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.MAIN_BRUSH_LIFE})
103+
side_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SIDE_BRUSH_LIFE})
104+
filter_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.FILTER_LIFE})
105+
sensor_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SENSOR_LIFE})
99106
clean_mode: YXDeviceWorkMode | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_MODE})
100107
clean_task_type: YXDeviceCleanTask | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_TASK_TYPE})
101108
back_type: YXBackType | None = field(default=None, metadata={"dps": B01_Q10_DP.BACK_TYPE})
102-
cleaning_progress: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEANING_PROGRESS})
109+
cleaning_progress: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_PROGRESS})
110+
fault: int | None = field(default=None, metadata={"dps": B01_Q10_DP.FAULT})

roborock/data/code_mappings.py

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from __future__ import annotations
2-
31
import logging
42
from collections import namedtuple
53
from enum import Enum, IntEnum, StrEnum
@@ -17,7 +15,7 @@ def name(self) -> str:
1715
return super().name.lower()
1816

1917
@classmethod
20-
def _missing_(cls: type[RoborockEnum], key) -> RoborockEnum:
18+
def _missing_(cls: type[Self], key) -> Self:
2119
if hasattr(cls, "unknown"):
2220
warning = f"Missing {cls.__name__} code: {key} - defaulting to 'unknown'"
2321
if warning not in completed_warnings:
@@ -32,23 +30,23 @@ def _missing_(cls: type[RoborockEnum], key) -> RoborockEnum:
3230
return default_value
3331

3432
@classmethod
35-
def as_dict(cls: type[RoborockEnum]):
33+
def as_dict(cls: type[Self]):
3634
return {i.name: i.value for i in cls if i.name != "missing"}
3735

3836
@classmethod
39-
def as_enum_dict(cls: type[RoborockEnum]):
37+
def as_enum_dict(cls: type[Self]):
4038
return {i.value: i for i in cls if i.name != "missing"}
4139

4240
@classmethod
43-
def values(cls: type[RoborockEnum]) -> list[int]:
41+
def values(cls: type[Self]) -> list[int]:
4442
return list(cls.as_dict().values())
4543

4644
@classmethod
47-
def keys(cls: type[RoborockEnum]) -> list[str]:
45+
def keys(cls: type[Self]) -> list[str]:
4846
return list(cls.as_dict().keys())
4947

5048
@classmethod
51-
def items(cls: type[RoborockEnum]):
49+
def items(cls: type[Self]):
5250
return cls.as_dict().items()
5351

5452

roborock/data/v1/v1_code_mappings.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from typing import Self
2+
13
from ..code_mappings import RoborockEnum
24

35

@@ -91,7 +93,7 @@ class RoborockStartType(RoborockEnum):
9193

9294
class RoborockDssCodes(RoborockEnum):
9395
@classmethod
94-
def _missing_(cls: type[RoborockEnum], key) -> RoborockEnum:
96+
def _missing_(cls: type[Self], key) -> Self:
9597
# If the calculated value is not provided, then it should be viewed as okay.
9698
# As the math will sometimes result in you getting numbers that don't matter.
9799
return cls.okay # type: ignore

roborock/device_features.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
1-
from __future__ import annotations
2-
31
from dataclasses import dataclass, field, fields
42
from enum import IntEnum, StrEnum
5-
from typing import Any
3+
from typing import Any, Self
64

75
from roborock.data.code_mappings import RoborockProductNickname
86
from roborock.data.containers import RoborockBase
@@ -566,7 +564,7 @@ def from_feature_flags(
566564
new_feature_info_str: str,
567565
feature_info: list[int],
568566
product_nickname: RoborockProductNickname | None,
569-
) -> DeviceFeatures:
567+
) -> Self:
570568
"""Creates a DeviceFeatures instance from raw feature flags.
571569
:param new_feature_info: A int from get_init_status (sometimes can be found in homedata, but it is not always)
572570
:param new_feature_info_str: A hex string from get_init_status or home_data.

0 commit comments

Comments
 (0)