Skip to content

Commit ae7450e

Browse files
committed
chore: do dynamic status
1 parent b48121f commit ae7450e

File tree

3 files changed

+184
-10
lines changed

3 files changed

+184
-10
lines changed

roborock/data/v1/v1_containers.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,8 @@
9292

9393
@dataclass
9494
class Status(RoborockBase):
95+
"""This status will be depreciated in favor of StatusV2."""
96+
9597
msg_ver: int | None = None
9698
msg_seq: int | None = None
9799
state: RoborockStateCode | None = None
@@ -250,6 +252,137 @@ def __repr__(self) -> str:
250252
return _attr_repr(self)
251253

252254

255+
class StatusV2(RoborockBase):
256+
"""
257+
This is a new version of the Status object.
258+
This is the result of GET_STATUS from the api.
259+
"""
260+
261+
msg_ver: int | None = None
262+
msg_seq: int | None = None
263+
state: RoborockStateCode | None = None
264+
battery: int | None = None
265+
clean_time: int | None = None
266+
clean_area: int | None = None
267+
error_code: RoborockErrorCode | None = None
268+
map_present: int | None = None
269+
in_cleaning: RoborockInCleaning | None = None
270+
in_returning: int | None = None
271+
in_fresh_state: int | None = None
272+
lab_status: int | None = None
273+
water_box_status: int | None = None
274+
back_type: int | None = None
275+
wash_phase: int | None = None
276+
wash_ready: int | None = None
277+
fan_power: int | None = None
278+
dnd_enabled: int | None = None
279+
map_status: int | None = None
280+
is_locating: int | None = None
281+
lock_status: int | None = None
282+
water_box_mode: int | None = None
283+
water_box_carriage_status: int | None = None
284+
mop_forbidden_enable: int | None = None
285+
camera_status: int | None = None
286+
is_exploring: int | None = None
287+
home_sec_status: int | None = None
288+
home_sec_enable_password: int | None = None
289+
adbumper_status: list[int] | None = None
290+
water_shortage_status: int | None = None
291+
dock_type: RoborockDockTypeCode | None = None
292+
dust_collection_status: int | None = None
293+
auto_dust_collection: int | None = None
294+
avoid_count: int | None = None
295+
mop_mode: int | None = None
296+
debug_mode: int | None = None
297+
collision_avoid_status: int | None = None
298+
switch_map_mode: int | None = None
299+
dock_error_status: RoborockDockErrorCode | None = None
300+
charge_status: int | None = None
301+
unsave_map_reason: int | None = None
302+
unsave_map_flag: int | None = None
303+
wash_status: int | None = None
304+
distance_off: int | None = None
305+
in_warmup: int | None = None
306+
dry_status: int | None = None
307+
rdt: int | None = None
308+
clean_percent: int | None = None
309+
rss: int | None = None
310+
dss: int | None = None
311+
common_status: int | None = None
312+
corner_clean_mode: int | None = None
313+
last_clean_t: int | None = None
314+
replenish_mode: int | None = None
315+
repeat: int | None = None
316+
kct: int | None = None
317+
subdivision_sets: int | None = None
318+
319+
@property
320+
def square_meter_clean_area(self) -> float | None:
321+
return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None
322+
323+
@property
324+
def error_code_name(self) -> str | None:
325+
return self.error_code.name if self.error_code is not None else None
326+
327+
@property
328+
def state_name(self) -> str | None:
329+
return self.state.name if self.state is not None else None
330+
331+
@property
332+
def current_map(self) -> int | None:
333+
"""Returns the current map ID if the map is present."""
334+
if self.map_status is not None:
335+
map_flag = self.map_status >> 2
336+
if map_flag != NO_MAP:
337+
return map_flag
338+
return None
339+
340+
@property
341+
def clear_water_box_status(self) -> ClearWaterBoxStatus | None:
342+
if self.dss:
343+
return ClearWaterBoxStatus((self.dss >> 2) & 3)
344+
return None
345+
346+
@property
347+
def dirty_water_box_status(self) -> DirtyWaterBoxStatus | None:
348+
if self.dss:
349+
return DirtyWaterBoxStatus((self.dss >> 4) & 3)
350+
return None
351+
352+
@property
353+
def dust_bag_status(self) -> DustBagStatus | None:
354+
if self.dss:
355+
return DustBagStatus((self.dss >> 6) & 3)
356+
return None
357+
358+
@property
359+
def water_box_filter_status(self) -> int | None:
360+
if self.dss:
361+
return (self.dss >> 8) & 3
362+
return None
363+
364+
@property
365+
def clean_fluid_status(self) -> int | None:
366+
if self.dss:
367+
return (self.dss >> 10) & 3
368+
return None
369+
370+
@property
371+
def hatch_door_status(self) -> int | None:
372+
if self.dss:
373+
return (self.dss >> 12) & 7
374+
return None
375+
376+
@property
377+
def dock_cool_fan_status(self) -> int | None:
378+
if self.dss:
379+
return (self.dss >> 15) & 3
380+
return None
381+
382+
def __repr__(self) -> str:
383+
return _attr_repr(self)
384+
385+
253386
@dataclass
254387
class S4MaxStatus(Status):
255388
fan_power: RoborockFanSpeedS6Pure | None = None

roborock/devices/traits/v1/__init__.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,13 @@ def __init__(
141141
self._map_rpc_channel = map_rpc_channel
142142
self._web_api = web_api
143143
self._cache = cache
144-
145-
self.status = StatusTrait(product)
144+
self.device_features = DeviceFeaturesTrait(product.product_nickname, cache)
145+
self.status = StatusTrait(self.device_features)
146146
self.consumables = ConsumableTrait()
147147
self.rooms = RoomsTrait(home_data)
148148
self.maps = MapsTrait(self.status)
149149
self.map_content = MapContentTrait(map_parser_config)
150150
self.home = HomeTrait(self.status, self.maps, self.map_content, self.rooms, cache)
151-
self.device_features = DeviceFeaturesTrait(product.product_nickname, cache)
152151
self.network_info = NetworkInfoTrait(device_uid, cache)
153152
self.routines = RoutinesTrait(device_uid, web_api)
154153

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,66 @@
1+
from functools import cached_property
12
from typing import Self
23

3-
from roborock.data import HomeDataProduct, ModelStatus, S7MaxVStatus, Status
4-
from roborock.devices.traits.v1 import common
4+
from roborock import CleanRoutes, StatusV2, VacuumModes, WaterModes, get_clean_modes, get_clean_routes, get_water_modes
5+
from roborock.devices.traits.v1 import DeviceFeaturesTrait, common
56
from roborock.roborock_typing import RoborockCommand
67

78

8-
class StatusTrait(Status, common.V1TraitMixin):
9+
class StatusTrait(StatusV2, common.V1TraitMixin):
910
"""Trait for managing the status of Roborock devices."""
1011

1112
command = RoborockCommand.GET_STATUS
1213

13-
def __init__(self, product_info: HomeDataProduct) -> None:
14+
def __init__(self, device_feature_trait: DeviceFeaturesTrait) -> None:
1415
"""Initialize the StatusTrait."""
15-
self._product_info = product_info
16+
self._device_features_trait = device_feature_trait
17+
18+
@cached_property
19+
def fan_speed_options(self) -> list[VacuumModes]:
20+
return get_clean_modes(self._device_features_trait)
21+
22+
@cached_property
23+
def fan_speed_mapping(self) -> dict[int, str]:
24+
return {fan.code: fan.name for fan in self.fan_speed_options}
25+
26+
@cached_property
27+
def water_mode_options(self) -> list[WaterModes]:
28+
return get_water_modes(self._device_features_trait)
29+
30+
@cached_property
31+
def water_mode_mapping(self) -> dict[int, str]:
32+
return {mop.code: mop.name for mop in self.water_mode_options}
33+
34+
@cached_property
35+
def mop_route_options(self) -> list[CleanRoutes]:
36+
return get_clean_routes(self._device_features_trait, "US") # TODO: find best place to get region
37+
38+
@cached_property
39+
def mop_route_mapping(self) -> dict[int, str]:
40+
return {route.code: route.name for route in self.mop_route_options}
41+
42+
@property
43+
def fan_speed_name(self) -> str | None:
44+
if self.fan_power is None:
45+
return None
46+
return self.fan_speed_mapping.get(self.fan_power)
47+
48+
@property
49+
def water_mode_name(self) -> str | None:
50+
if self.water_box_mode is None:
51+
return None
52+
return self.water_mode_mapping.get(self.water_box_mode)
53+
54+
@property
55+
def mop_route_name(self) -> str | None:
56+
if self.mop_mode is None:
57+
return None
58+
return self.mop_route_mapping.get(self.mop_mode)
1659

1760
def _parse_response(self, response: common.V1ResponseData) -> Self:
1861
"""Parse the response from the device into a CleanSummary."""
19-
status_type: type[Status] = ModelStatus.get(self._product_info.model, S7MaxVStatus)
2062
if isinstance(response, list):
2163
response = response[0]
2264
if isinstance(response, dict):
23-
return status_type.from_dict(response)
65+
return StatusV2.from_dict(response)
2466
raise ValueError(f"Unexpected status format: {response!r}")

0 commit comments

Comments
 (0)