4444 ZeoDetergentType ,
4545 ZeoDryingMode ,
4646 ZeoError ,
47+ ZeoFeatureBits ,
4748 ZeoMode ,
4849 ZeoProgram ,
4950 ZeoRinse ,
@@ -179,10 +180,16 @@ def __init__(self, channel: MqttChannel) -> None:
179180 self ._channel = channel
180181 self ._dps_cache : dict [int , Any ] = {}
181182 self ._dps_unsub : Callable [[], None ] | None = None
183+ self ._feature_bits : int = 0
182184
183185 async def start (self ) -> None :
184- """Subscribe to MQTT push (called once after device connects)."""
186+ """Subscribe to MQTT push and discover device features.
187+
188+ Subscribes to the DPS MQTT topic, then queries FEATURE_BITS
189+ (DP 237) to wake the device and cache supported capabilities.
190+ """
185191 await self ._ensure_subscribed ()
192+ await self ._discover_features ()
186193
187194 def close (self ) -> None :
188195 """Unsubscribe from MQTT push and release resources."""
@@ -196,6 +203,24 @@ async def _ensure_subscribed(self) -> None:
196203 return
197204 self ._dps_unsub = await self ._channel .subscribe (self ._on_dps_message )
198205
206+ async def _discover_features (self ) -> None :
207+ """Query FEATURE_BITS to wake the device and cache capabilities.
208+
209+ Sending an RPC query after subscribing triggers the device to
210+ start pushing its full state — equivalent to how V1's
211+ ``discover_features()`` uses ``device_features.refresh()`` to
212+ initiate the push cycle.
213+ """
214+ try :
215+ result = await self .query_values ([RoborockZeoProtocol .FEATURE_BITS ])
216+ self ._feature_bits = result .get (RoborockZeoProtocol .FEATURE_BITS , 0 )
217+ except Exception :
218+ self ._feature_bits = 0
219+
220+ def supports (self , feature : ZeoFeatureBits ) -> bool :
221+ """Check whether the device supports a given feature bit."""
222+ return bool (self ._feature_bits & (1 << feature .value ))
223+
199224 def _on_dps_message (self , message : RoborockMessage ) -> None :
200225 """Handle unsolicited MQTT push (protocol 102 — RPC_RESPONSE).
201226
0 commit comments