Skip to content

Commit 2764f2e

Browse files
author
NOisi-X
committed
feat(zeo): add pause(), resume(), shutdown() and split start param DPs by device type
Add pause() (DP 201), shutdown() (DP 202), and update resume() to align with the official app's WasherDpsManager module 727. Split _START_PARAM_DPS into _START_PARAM_DPS_WASHER (10 DPs) and _START_PARAM_DPS_DRYER (7 DPs) so fallback queries only request DPs the device actually supports, avoiding send_decoded_command timeouts on partial responses.
1 parent 4eccebf commit 2764f2e

1 file changed

Lines changed: 31 additions & 12 deletions

File tree

roborock/devices/traits/a01/command.py

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
_LOGGER = logging.getLogger(__name__)
1515

16-
_START_PARAM_DPS: list[RoborockZeoProtocol] = [
16+
_START_PARAM_DPS_WASHER: list[RoborockZeoProtocol] = [
1717
RoborockZeoProtocol.MODE,
1818
RoborockZeoProtocol.PROGRAM,
1919
RoborockZeoProtocol.TEMP,
@@ -24,9 +24,16 @@
2424
RoborockZeoProtocol.SOFTENER_SET,
2525
RoborockZeoProtocol.COUNTDOWN,
2626
RoborockZeoProtocol.SOAK,
27+
]
28+
29+
_START_PARAM_DPS_DRYER: list[RoborockZeoProtocol] = [
30+
RoborockZeoProtocol.MODE,
31+
RoborockZeoProtocol.PROGRAM,
32+
RoborockZeoProtocol.DRYING_MODE,
2733
RoborockZeoProtocol.TOTAL_TIME,
2834
RoborockZeoProtocol.DRYING_METHOD,
2935
RoborockZeoProtocol.STEAM_VOLUME,
36+
RoborockZeoProtocol.COUNTDOWN,
3037
]
3138

3239
_FIELD_TO_DP: dict[str, RoborockZeoProtocol] = {
@@ -50,7 +57,7 @@
5057
}
5158

5259
class ZeoCommandTrait:
53-
"""Trait for sending wash-programme commands to Zeo devices."""
60+
"""Trait for sending commands to Zeo devices."""
5461

5562
def __init__(
5663
self,
@@ -79,7 +86,6 @@ def _convert_value(self, protocol: RoborockZeoProtocol, value: Any) -> Any:
7986

8087
async def start_program(self) -> dict[RoborockZeoProtocol, Any]:
8188
"""Start the device, bundling the current programme parameters."""
82-
_LOGGER.debug("Start command: discovering features and building payload")
8389
features = self._feature_trait.features
8490
p = await self._get_start_params()
8591
dps: dict[RoborockZeoProtocol, Any] = {RoborockZeoProtocol.START: "True"}
@@ -102,33 +108,46 @@ async def start_program(self) -> dict[RoborockZeoProtocol, Any]:
102108
self._dps_cache[int(dp)] = v
103109
return {proto: self._convert_value(proto, dps.get(proto)) for proto in dps}
104110

111+
async def pause(self) -> dict[RoborockZeoProtocol, Any]:
112+
"""Pause the current programme (DP 201 = "True")."""
113+
dps = {RoborockZeoProtocol.PAUSE: "True"}
114+
result = await send_decoded_command(self._channel, dps)
115+
self._dps_cache[int(RoborockZeoProtocol.PAUSE)] = 1
116+
return result
117+
105118
async def resume(self) -> dict[RoborockZeoProtocol, Any]:
106-
"""Resume a paused programme or start without rebundling).
107-
Only works while the device is powered on."""
108-
_LOGGER.debug("Resume command")
119+
"""Start/continue a paused programme (DP 200 = "True").
120+
Only works while the device is powered on.
121+
"""
109122
dps = {RoborockZeoProtocol.START: "True"}
110-
result = await send_decoded_command(
111-
self._channel,
112-
dps,
113-
)
123+
result = await send_decoded_command(self._channel, dps)
114124
self._dps_cache[int(RoborockZeoProtocol.START)] = 1
115125
return result
116126

127+
async def shutdown(self) -> dict[RoborockZeoProtocol, Any]:
128+
"""Power off the device (DP 202 = "True").
129+
Only works while the device is powered on.
130+
"""
131+
dps = {RoborockZeoProtocol.SHUTDOWN: "True"}
132+
result = await send_decoded_command(self._channel, dps)
133+
self._dps_cache[int(RoborockZeoProtocol.SHUTDOWN)] = 1
134+
return result
117135

118136
async def _get_start_params(self) -> ZeoStartParams:
119137
"""Read programme settings, querying the device on cache miss."""
120138
cache = self._dps_cache
139+
wanted = _START_PARAM_DPS_DRYER if self._feature_trait.is_dryer else _START_PARAM_DPS_WASHER
121140
need_refresh = (
122141
int(RoborockZeoProtocol.MODE) not in cache
123142
or int(RoborockZeoProtocol.PROGRAM) not in cache
124143
)
125144
if need_refresh:
126145
raw = await send_decoded_command(
127146
self._channel,
128-
{RoborockZeoProtocol.ID_QUERY: [RoborockZeoProtocol.MODE, RoborockZeoProtocol.PROGRAM]},
147+
{RoborockZeoProtocol.ID_QUERY: wanted},
129148
value_encoder=json.dumps,
130149
)
131-
for dp in (RoborockZeoProtocol.MODE, RoborockZeoProtocol.PROGRAM):
150+
for dp in wanted:
132151
if (val := raw.get(dp)) is not None:
133152
cache[int(dp)] = val
134153
return ZeoStartParams(

0 commit comments

Comments
 (0)