Skip to content

Commit eb5578b

Browse files
committed
refactor: type simulator status, network info and init status using real dataclasses
1 parent 171d34c commit eb5578b

1 file changed

Lines changed: 130 additions & 104 deletions

File tree

roborock/testing/v1_simulator.py

Lines changed: 130 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,26 @@
1515

1616
from roborock.data import HomeDataDevice, HomeDataProduct
1717
from roborock.data.v1 import RoborockStateCode
18-
from roborock.data.v1.v1_code_mappings import RoborockCleanType, RoborockFinishReason, RoborockStartType
19-
from roborock.data.v1.v1_containers import CleanRecord, CleanSummary, Consumable, DnDTimer
18+
from roborock.data.v1.v1_code_mappings import (
19+
RoborockChargeStatus,
20+
RoborockCleanType,
21+
RoborockDockErrorCode,
22+
RoborockDockTypeCode,
23+
RoborockErrorCode,
24+
RoborockFinishReason,
25+
RoborockInCleaning,
26+
RoborockStartType,
27+
)
28+
from roborock.data.v1.v1_containers import (
29+
AppInitStatus,
30+
AppInitStatusLocalInfo,
31+
CleanRecord,
32+
CleanSummary,
33+
Consumable,
34+
DnDTimer,
35+
NetworkInfo,
36+
StatusV2,
37+
)
2038
from roborock.devices.cache import DeviceCache, InMemoryCache
2139
from roborock.devices.rpc.v1_channel import V1Channel
2240
from roborock.protocols.v1_protocol import SecurityData
@@ -32,53 +50,6 @@ def _serialize_dataclass(obj: Any) -> dict[str, Any]:
3250
return {k: (v.value if isinstance(v, Enum) else v) for k, v in asdict(obj).items() if v is not None}
3351

3452

35-
# Simulated network details
36-
DEFAULT_NETWORK_INFO = {
37-
"ip": "1.1.1.1",
38-
"ssid": "test_wifi",
39-
"mac": "aa:bb:cc:dd:ee:ff",
40-
"bssid": "aa:bb:cc:dd:ee:ff",
41-
"rssi": -50,
42-
}
43-
44-
# Simulated application init parameters
45-
DEFAULT_APP_GET_INIT_STATUS = {
46-
"local_info": {
47-
"name": "custom_A.03.0069_FCC",
48-
"bom": "A.03.0069",
49-
"location": "us",
50-
"language": "en",
51-
"wifiplan": "0x39",
52-
"timezone": "US/Pacific",
53-
"logserver": "awsusor0.fds.api.xiaomi.com",
54-
"featureset": 1,
55-
},
56-
"feature_info": [111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 123, 124, 125],
57-
"new_feature_info": 633887780925447,
58-
"new_feature_info2": 8192,
59-
"new_feature_info_str": "0000000000002000",
60-
"status_info": {
61-
"state": RoborockStateCode.charging,
62-
"battery": 100,
63-
"clean_time": 5610,
64-
"clean_area": 96490000,
65-
"error_code": 0,
66-
"in_cleaning": 0,
67-
"in_returning": 0,
68-
"in_fresh_state": 1,
69-
"lab_status": 1,
70-
"water_box_status": 0,
71-
"map_status": 3,
72-
"is_locating": 0,
73-
"lock_status": 0,
74-
"water_box_mode": 204,
75-
"distance_off": 0,
76-
"water_box_carriage_status": 0,
77-
"mop_forbidden_enable": 0,
78-
},
79-
}
80-
81-
8253
class V1VacuumSimulator(RoborockDeviceSimulator):
8354
"""Firmware simulator for a V1/L01 vacuum device.
8455
@@ -117,6 +88,14 @@ def __init__(
11788
self.dss = dss
11889
self.dock_type = dock_type
11990

91+
self.network_info = NetworkInfo(
92+
ip="1.1.1.1",
93+
ssid="test_wifi",
94+
mac="aa:bb:cc:dd:ee:ff",
95+
bssid="aa:bb:cc:dd:ee:ff",
96+
rssi=-50,
97+
)
98+
12099
self.consumables = Consumable(
121100
main_brush_work_time=74382,
122101
side_brush_work_time=74383,
@@ -196,69 +175,76 @@ def v1_channel(self) -> V1Channel:
196175
return self._v1_channel
197176

198177
@property
199-
def in_cleaning(self) -> int:
200-
"""Return 1 if cleaning, else 0."""
201-
return 1 if self.state == RoborockStateCode.cleaning else 0
178+
def in_cleaning(self) -> RoborockInCleaning:
179+
"""Return global_clean_not_complete if cleaning, else complete."""
180+
return (
181+
RoborockInCleaning.global_clean_not_complete
182+
if self.state == RoborockStateCode.cleaning
183+
else RoborockInCleaning.complete
184+
)
202185

203186
@property
204187
def in_returning(self) -> int:
205188
"""Return 1 if returning, else 0."""
206189
return 1 if self.state == RoborockStateCode.returning_home else 0
207190

208191
@property
209-
def charge_status(self) -> int:
210-
"""Return 1 if charging, else 0."""
211-
return 1 if self.state == RoborockStateCode.charging else 0
192+
def charge_status(self) -> RoborockChargeStatus:
193+
"""Return charging if charging, else charge_waiting."""
194+
return (
195+
RoborockChargeStatus.charging
196+
if self.state == RoborockStateCode.charging
197+
else RoborockChargeStatus.charge_waiting
198+
)
212199

213200
def get_status_dict(self) -> dict[str, Any]:
214201
"""Generate status dict using the current simulated state."""
215-
return {
216-
"msg_ver": 2,
217-
"msg_seq": 458,
218-
"state": self.state,
219-
"battery": self.battery,
220-
"clean_time": 1176,
221-
"clean_area": 20965000,
222-
"error_code": 0,
223-
"map_present": 1,
224-
"in_cleaning": self.in_cleaning,
225-
"in_returning": self.in_returning,
226-
"in_fresh_state": 1,
227-
"lab_status": 1,
228-
"water_box_status": 1,
229-
"back_type": -1,
230-
"wash_phase": 0,
231-
"wash_ready": 0,
232-
"fan_power": self.fan_power,
233-
"dnd_enabled": self.dnd_enabled,
234-
"map_status": 3,
235-
"is_locating": 0,
236-
"lock_status": 0,
237-
"water_box_mode": self.water_box_mode,
238-
"water_box_carriage_status": 1,
239-
"mop_forbidden_enable": 1,
240-
"camera_status": 3457,
241-
"is_exploring": 0,
242-
"home_sec_status": 0,
243-
"home_sec_enable_password": 0,
244-
"adbumper_status": [0, 0, 0],
245-
"water_shortage_status": 0,
246-
"grey_water_box_status": 0,
247-
"dirty_water_box_status": 0,
248-
"dock_type": self.dock_type,
249-
"dust_collection_status": 0,
250-
"auto_dust_collection": 1,
251-
"avoid_count": 19,
252-
"mop_mode": self.mop_mode,
253-
"debug_mode": 0,
254-
"collision_avoid_status": 1,
255-
"switch_map_mode": 0,
256-
"dock_error_status": 0,
257-
"charge_status": self.charge_status,
258-
"unsave_map_reason": 0,
259-
"unsave_map_flag": 0,
260-
"dss": self.dss,
261-
}
202+
status = StatusV2(
203+
msg_ver=2,
204+
msg_seq=458,
205+
state=RoborockStateCode(self.state),
206+
battery=self.battery,
207+
clean_time=1176,
208+
clean_area=20965000,
209+
error_code=RoborockErrorCode(0),
210+
map_present=1,
211+
in_cleaning=self.in_cleaning,
212+
in_returning=self.in_returning,
213+
in_fresh_state=1,
214+
lab_status=1,
215+
water_box_status=1,
216+
back_type=-1,
217+
wash_phase=0,
218+
wash_ready=0,
219+
fan_power=self.fan_power,
220+
dnd_enabled=self.dnd_enabled,
221+
map_status=3,
222+
is_locating=0,
223+
lock_status=0,
224+
water_box_mode=self.water_box_mode,
225+
water_box_carriage_status=1,
226+
mop_forbidden_enable=1,
227+
camera_status=3457,
228+
is_exploring=0,
229+
home_sec_status=0,
230+
home_sec_enable_password=0,
231+
adbumper_status=[0, 0, 0],
232+
water_shortage_status=0,
233+
dock_type=RoborockDockTypeCode(self.dock_type),
234+
dust_collection_status=0,
235+
auto_dust_collection=1,
236+
avoid_count=19,
237+
mop_mode=self.mop_mode,
238+
debug_mode=0,
239+
collision_avoid_status=1,
240+
switch_map_mode=0,
241+
dock_error_status=RoborockDockErrorCode(0),
242+
charge_status=self.charge_status,
243+
unsave_map_reason=0,
244+
unsave_map_flag=0,
245+
dss=self.dss,
246+
)
247+
return _serialize_dataclass(status)
262248

263249
def _handle_app_start(self, params: Any) -> str:
264250
self.state = RoborockStateCode.cleaning
@@ -297,10 +283,50 @@ def _handle_reset_consumable(self, params: Any) -> str:
297283
return "ok"
298284

299285
def _handle_app_get_init_status(self, params: Any) -> list[dict[str, Any]]:
300-
return [DEFAULT_APP_GET_INIT_STATUS]
286+
local_info = AppInitStatusLocalInfo(
287+
location="us",
288+
bom="A.03.0069",
289+
featureset=1,
290+
language="en",
291+
logserver="awsusor0.fds.api.xiaomi.com",
292+
wifiplan="0x39",
293+
timezone="US/Pacific",
294+
name="custom_A.03.0069_FCC",
295+
)
296+
app_init = AppInitStatus(
297+
local_info=local_info,
298+
feature_info=[111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 122, 123, 124, 125],
299+
new_feature_info=633887780925447,
300+
new_feature_info_str="0000000000002000",
301+
new_feature_info_2=8192,
302+
)
303+
payload = _serialize_dataclass(app_init)
304+
if "new_feature_info_2" in payload:
305+
payload["new_feature_info2"] = payload.pop("new_feature_info_2")
306+
307+
payload["status_info"] = {
308+
"state": self.state,
309+
"battery": self.battery,
310+
"clean_time": 5610,
311+
"clean_area": 96490000,
312+
"error_code": 0,
313+
"in_cleaning": self.in_cleaning.value,
314+
"in_returning": self.in_returning,
315+
"in_fresh_state": 1,
316+
"lab_status": 1,
317+
"water_box_status": 0,
318+
"map_status": 3,
319+
"is_locating": 0,
320+
"lock_status": 0,
321+
"water_box_mode": self.water_box_mode,
322+
"distance_off": 0,
323+
"water_box_carriage_status": 0,
324+
"mop_forbidden_enable": 0,
325+
}
326+
return [payload]
301327

302328
def _handle_get_network_info(self, params: Any) -> dict[str, Any]:
303-
return DEFAULT_NETWORK_INFO
329+
return _serialize_dataclass(self.network_info)
304330

305331
async def _handle_publish(self, message: RoborockMessage, channel: FakeChannel) -> None:
306332
if not message.payload:

0 commit comments

Comments
 (0)