Skip to content

Commit 628f4b2

Browse files
author
NOisi-X
committed
feat(zeo): add _discover_features() and supports() with FEATURE_BITS; add DP 243
1 parent 55189c6 commit 628f4b2

2 files changed

Lines changed: 34 additions & 4 deletions

File tree

roborock/devices/traits/a01/__init__.py

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@
2525
from datetime import time
2626
from typing import Any
2727

28-
from roborock.exceptions import RoborockException
29-
from roborock.protocols.a01_protocol import decode_rpc_response
30-
3128
from roborock.data import DyadProductInfo, DyadSndState, HomeDataProduct, RoborockCategory
3229
from roborock.data.dyad.dyad_code_mappings import (
3330
DyadBrushSpeed,
@@ -44,6 +41,7 @@
4441
ZeoDetergentType,
4542
ZeoDryingMode,
4643
ZeoError,
44+
ZeoFeatureBits,
4745
ZeoMode,
4846
ZeoProgram,
4947
ZeoRinse,
@@ -56,6 +54,8 @@
5654
from roborock.devices.traits import Trait
5755
from roborock.devices.traits.common import TraitUpdateListener
5856
from roborock.devices.transport.mqtt_channel import MqttChannel
57+
from roborock.exceptions import RoborockException
58+
from roborock.protocols.a01_protocol import decode_rpc_response
5959
from roborock.roborock_message import (
6060
RoborockDyadDataProtocol,
6161
RoborockMessage,
@@ -179,10 +179,19 @@ def __init__(self, channel: MqttChannel) -> None:
179179
self._channel = channel
180180
self._dps_cache: dict[int, Any] = {}
181181
self._dps_unsub: Callable[[], None] | None = None
182+
self._feature_bits: int = 0
182183

183184
async def start(self) -> None:
184-
"""Subscribe to MQTT push (called once after device connects)."""
185+
"""Subscribe to MQTT push and discover device features.
186+
187+
Subscribes to the DPS MQTT topic, then queries FEATURE_BITS
188+
(DP 237) to wake the device and cache supported capabilities.
189+
"""
185190
await self._ensure_subscribed()
191+
try:
192+
await self._discover_features()
193+
except Exception:
194+
pass
186195

187196
def close(self) -> None:
188197
"""Unsubscribe from MQTT push and release resources."""
@@ -196,6 +205,24 @@ async def _ensure_subscribed(self) -> None:
196205
return
197206
self._dps_unsub = await self._channel.subscribe(self._on_dps_message)
198207

208+
async def _discover_features(self) -> None:
209+
"""Query FEATURE_BITS to wake the device and cache capabilities.
210+
211+
Sending an RPC query after subscribing triggers the device to
212+
start pushing its full state — equivalent to how V1's
213+
``discover_features()`` uses ``device_features.refresh()`` to
214+
initiate the push cycle.
215+
"""
216+
try:
217+
result = await self.query_values([RoborockZeoProtocol.FEATURE_BITS])
218+
self._feature_bits = result.get(RoborockZeoProtocol.FEATURE_BITS, 0)
219+
except Exception:
220+
self._feature_bits = 0
221+
222+
def supports(self, feature: ZeoFeatureBits) -> bool:
223+
"""Check whether the device supports a given feature bit."""
224+
return bool(self._feature_bits & (1 << feature.value))
225+
199226
def _on_dps_message(self, message: RoborockMessage) -> None:
200227
"""Handle unsolicited MQTT push (protocol 102 — RPC_RESPONSE).
201228

roborock/roborock_message.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ class RoborockZeoProtocol(RoborockEnum):
179179
SILENT_MODE_ON = 240 # rw [independent] use set_silent_mode() for bundled set
180180
SILENT_MODE_START_TIME = 241 # rw [independent] minute-of-day
181181
SILENT_MODE_END_TIME = 242 # rw [independent] minute-of-day
182+
UNKNOWN_243 = (
183+
243 # unknown, not found in plugin bundle; present in MQTT push from some devices, increments with each push
184+
)
182185
DRY_CARE_MODE = 244 # rw [startWith]
183186
SOFTENER_EXPANSION_TYPE = 245 # rw [independent]
184187
SMILE_LIGHT_STATUS = 247 # rw [independent]

0 commit comments

Comments
 (0)