Skip to content

Commit 9f372d2

Browse files
committed
feat(q10): add status update listener API
1 parent 26b4b8d commit 9f372d2

File tree

2 files changed

+42
-3
lines changed

2 files changed

+42
-3
lines changed

roborock/devices/traits/b01/q10/status.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
"""Status trait for Q10 B01 devices."""
22

33
import logging
4+
from collections.abc import Callable
5+
from typing import Any
46

7+
from roborock.callbacks import CallbackList
8+
from roborock.data.b01_q10.b01_q10_code_mappings import B01_Q10_DP
59
from roborock.data.b01_q10.b01_q10_containers import Q10Status
610

711
from .common import DpsDataConverter
@@ -19,8 +23,23 @@ class StatusTrait(Q10Status):
1923
New values can be requited through the `Q10PropertiesApi`'s `refresh` method.
2024
"""
2125

22-
def update_from_dps(self, decoded_dps: dict) -> None:
26+
def __init__(self) -> None:
27+
"""Initialize the status trait."""
28+
super().__init__()
29+
self._update_callbacks: CallbackList[dict[B01_Q10_DP, Any]] = CallbackList(
30+
logger=_LOGGER
31+
)
32+
33+
def add_update_listener(
34+
self, callback: Callable[[dict[B01_Q10_DP, Any]], None]
35+
) -> Callable[[], None]:
36+
"""Register a callback for decoded DPS updates.
37+
38+
Returns a callable to remove the listener.
39+
"""
40+
return self._update_callbacks.add_callback(callback)
41+
42+
def update_from_dps(self, decoded_dps: dict[B01_Q10_DP, Any]) -> None:
2343
"""Update the trait from raw DPS data."""
2444
_CONVERTER.update_from_dps(self, decoded_dps)
25-
# In the future we can register listeners and notify them here on update
26-
# if `update_from_dps` performed any updates.
45+
self._update_callbacks(decoded_dps)

tests/devices/traits/b01/q10/test_status.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import pytest
1111

1212
from roborock.data.b01_q10.b01_q10_code_mappings import (
13+
B01_Q10_DP,
1314
YXDeviceCleanTask,
1415
YXDeviceState,
1516
YXFanLevel,
@@ -139,3 +140,22 @@ async def test_status_trait_refresh(
139140
assert q10_api.status.battery == 100
140141
assert q10_api.status.status == YXDeviceState.CHARGING_STATE
141142
assert q10_api.status.fan_level == YXFanLevel.NORMAL
143+
144+
145+
def test_status_trait_update_listener(q10_api: Q10PropertiesApi) -> None:
146+
"""Test that status listeners receive updates and can unsubscribe."""
147+
updates: list[dict[B01_Q10_DP, Any]] = []
148+
149+
unsubscribe = q10_api.status.add_update_listener(updates.append)
150+
151+
first_update = {B01_Q10_DP.BATTERY: 88}
152+
q10_api.status.update_from_dps(first_update)
153+
154+
assert updates == [first_update]
155+
156+
unsubscribe()
157+
158+
second_update = {B01_Q10_DP.BATTERY: 87}
159+
q10_api.status.update_from_dps(second_update)
160+
161+
assert updates == [first_update]

0 commit comments

Comments
 (0)