Skip to content

Commit 8e681a2

Browse files
committed
clean up duplicated traits
1 parent 64f9d2e commit 8e681a2

3 files changed

Lines changed: 5 additions & 80 deletions

File tree

roborock/devices/traits/v1/common.py

Lines changed: 1 addition & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,12 @@
55

66
import logging
77
from abc import ABC, abstractmethod
8-
from collections.abc import Callable
98
from dataclasses import fields
10-
from typing import Any, ClassVar
9+
from typing import ClassVar
1110

12-
from roborock.callbacks import CallbackList
1311
from roborock.data import RoborockBase
1412
from roborock.exceptions import RoborockParsingException
1513
from roborock.protocols.v1_protocol import V1RpcChannel
16-
from roborock.roborock_message import RoborockDataProtocol
1714
from roborock.roborock_typing import RoborockCommand
1815

1916
_LOGGER = logging.getLogger(__name__)
@@ -185,74 +182,3 @@ def wrapper(*args, **kwargs):
185182

186183
cls.map_rpc_channel = True # type: ignore[attr-defined]
187184
return wrapper
188-
189-
190-
# TODO(allenporter): Merge with roborock.devices.traits.b01.q10.common.TraitUpdateListener
191-
class TraitUpdateListener(ABC):
192-
"""Trait update listener.
193-
194-
This is a base class for traits to support notifying listeners when they
195-
have been updated. Clients may register callbacks to be notified when the
196-
trait has been updated. When the listener callback is invoked, the client
197-
should read the trait's properties to get the updated values.
198-
"""
199-
200-
def __init__(self, logger: logging.Logger) -> None:
201-
"""Initialize the trait update listener."""
202-
self._update_callbacks: CallbackList[None] = CallbackList(logger=logger)
203-
204-
def add_update_listener(self, callback: Callable[[], None]) -> Callable[[], None]:
205-
"""Register a callback when the trait has been updated.
206-
207-
Returns a callable to remove the listener.
208-
"""
209-
# We wrap the callback to ignore the value passed to it.
210-
return self._update_callbacks.add_callback(lambda _: callback())
211-
212-
def _notify_update(self) -> None:
213-
"""Notify all update listeners."""
214-
self._update_callbacks(None)
215-
216-
217-
class DpsDataConverter:
218-
"""Utility to handle the transformation and merging of DPS data into models.
219-
220-
This class pre-calculates the mapping between Data Point IDs and dataclass fields
221-
to optimize repeated updates from device streams.
222-
"""
223-
224-
def __init__(self, dps_type_map: dict[RoborockDataProtocol, type], dps_field_map: dict[RoborockDataProtocol, str]):
225-
"""Initialize the converter for a specific RoborockBase-derived class."""
226-
self._dps_type_map = dps_type_map
227-
self._dps_field_map = dps_field_map
228-
229-
@classmethod
230-
def from_dataclass(cls, dataclass_type: type[RoborockBase]):
231-
"""Initialize the converter for a specific RoborockBase-derived class."""
232-
dps_type_map: dict[RoborockDataProtocol, type] = {}
233-
dps_field_map: dict[RoborockDataProtocol, str] = {}
234-
for field_obj in fields(dataclass_type):
235-
if field_obj.metadata and "dps" in field_obj.metadata:
236-
dps_id = field_obj.metadata["dps"]
237-
dps_type_map[dps_id] = field_obj.type
238-
dps_field_map[dps_id] = field_obj.name
239-
return cls(dps_type_map, dps_field_map)
240-
241-
def update_from_dps(self, target: RoborockBase, decoded_dps: dict[RoborockDataProtocol, Any]) -> bool:
242-
"""Convert and merge raw DPS data into the target object.
243-
244-
Uses the pre-calculated type mapping to ensure values are converted to the
245-
correct Python types before being updated on the target.
246-
247-
Args:
248-
target: The target object to update.
249-
decoded_dps: The decoded DPS data to convert.
250-
251-
Returns:
252-
True if any values were updated, False otherwise.
253-
"""
254-
conversions = RoborockBase.convert_dict(self._dps_type_map, decoded_dps)
255-
for dps_id, value in conversions.items():
256-
field_name = self._dps_field_map[dps_id]
257-
setattr(target, field_name, value)
258-
return bool(conversions)

roborock/devices/traits/v1/consumeable.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,18 @@
99
from typing import Any, Self
1010

1111
from roborock.data import Consumable
12+
from roborock.devices.traits.common import DpsDataConverter, TraitUpdateListener
1213
from roborock.devices.traits.v1 import common
1314
from roborock.roborock_message import RoborockDataProtocol
1415
from roborock.roborock_typing import RoborockCommand
1516

16-
from .common import TraitUpdateListener
17-
1817
__all__ = [
1918
"ConsumableTrait",
2019
]
2120

2221
_LOGGER = logging.getLogger(__name__)
2322

24-
_DPS_CONVERTER = common.DpsDataConverter.from_dataclass(Consumable)
23+
_DPS_CONVERTER = DpsDataConverter.from_dataclass(Consumable)
2524

2625

2726
class ConsumableAttribute(StrEnum):

roborock/devices/traits/v1/status.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,16 @@
1212
get_water_mode_mapping,
1313
get_water_modes,
1414
)
15+
from roborock.devices.traits.common import DpsDataConverter, TraitUpdateListener
1516
from roborock.roborock_message import RoborockDataProtocol
1617
from roborock.roborock_typing import RoborockCommand
1718

1819
from . import common
19-
from .common import TraitUpdateListener
2020
from .device_features import DeviceFeaturesTrait
2121

2222
_LOGGER = logging.getLogger(__name__)
2323

24-
_DPS_CONVERTER = common.DpsDataConverter.from_dataclass(StatusV2)
24+
_DPS_CONVERTER = DpsDataConverter.from_dataclass(StatusV2)
2525

2626

2727
class StatusTrait(StatusV2, common.V1TraitMixin, TraitUpdateListener):

0 commit comments

Comments
 (0)