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 ,
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 ] = {
5057}
5158
5259class 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