roborock-cli 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. roborock_cli/__init__.py +3 -0
  2. roborock_cli/__main__.py +76 -0
  3. roborock_cli/_vendor/VERSION +6 -0
  4. roborock_cli/_vendor/__init__.py +0 -0
  5. roborock_cli/_vendor/roborock/__init__.py +27 -0
  6. roborock_cli/_vendor/roborock/broadcast_protocol.py +114 -0
  7. roborock_cli/_vendor/roborock/callbacks.py +130 -0
  8. roborock_cli/_vendor/roborock/cli.py +1338 -0
  9. roborock_cli/_vendor/roborock/const.py +84 -0
  10. roborock_cli/_vendor/roborock/data/__init__.py +9 -0
  11. roborock_cli/_vendor/roborock/data/b01_q10/__init__.py +2 -0
  12. roborock_cli/_vendor/roborock/data/b01_q10/b01_q10_code_mappings.py +213 -0
  13. roborock_cli/_vendor/roborock/data/b01_q10/b01_q10_containers.py +102 -0
  14. roborock_cli/_vendor/roborock/data/b01_q7/__init__.py +2 -0
  15. roborock_cli/_vendor/roborock/data/b01_q7/b01_q7_code_mappings.py +303 -0
  16. roborock_cli/_vendor/roborock/data/b01_q7/b01_q7_containers.py +302 -0
  17. roborock_cli/_vendor/roborock/data/code_mappings.py +198 -0
  18. roborock_cli/_vendor/roborock/data/containers.py +530 -0
  19. roborock_cli/_vendor/roborock/data/dyad/__init__.py +2 -0
  20. roborock_cli/_vendor/roborock/data/dyad/dyad_code_mappings.py +102 -0
  21. roborock_cli/_vendor/roborock/data/dyad/dyad_containers.py +28 -0
  22. roborock_cli/_vendor/roborock/data/v1/__init__.py +3 -0
  23. roborock_cli/_vendor/roborock/data/v1/v1_clean_modes.py +192 -0
  24. roborock_cli/_vendor/roborock/data/v1/v1_code_mappings.py +644 -0
  25. roborock_cli/_vendor/roborock/data/v1/v1_containers.py +800 -0
  26. roborock_cli/_vendor/roborock/data/zeo/__init__.py +2 -0
  27. roborock_cli/_vendor/roborock/data/zeo/zeo_code_mappings.py +138 -0
  28. roborock_cli/_vendor/roborock/data/zeo/zeo_containers.py +0 -0
  29. roborock_cli/_vendor/roborock/device_features.py +668 -0
  30. roborock_cli/_vendor/roborock/devices/README.md +41 -0
  31. roborock_cli/_vendor/roborock/devices/__init__.py +11 -0
  32. roborock_cli/_vendor/roborock/devices/cache.py +143 -0
  33. roborock_cli/_vendor/roborock/devices/device.py +240 -0
  34. roborock_cli/_vendor/roborock/devices/device_manager.py +269 -0
  35. roborock_cli/_vendor/roborock/devices/file_cache.py +79 -0
  36. roborock_cli/_vendor/roborock/devices/rpc/__init__.py +14 -0
  37. roborock_cli/_vendor/roborock/devices/rpc/a01_channel.py +94 -0
  38. roborock_cli/_vendor/roborock/devices/rpc/b01_q10_channel.py +57 -0
  39. roborock_cli/_vendor/roborock/devices/rpc/b01_q7_channel.py +101 -0
  40. roborock_cli/_vendor/roborock/devices/rpc/v1_channel.py +457 -0
  41. roborock_cli/_vendor/roborock/devices/traits/__init__.py +28 -0
  42. roborock_cli/_vendor/roborock/devices/traits/a01/__init__.py +191 -0
  43. roborock_cli/_vendor/roborock/devices/traits/b01/__init__.py +12 -0
  44. roborock_cli/_vendor/roborock/devices/traits/b01/q10/__init__.py +76 -0
  45. roborock_cli/_vendor/roborock/devices/traits/b01/q10/command.py +32 -0
  46. roborock_cli/_vendor/roborock/devices/traits/b01/q10/common.py +115 -0
  47. roborock_cli/_vendor/roborock/devices/traits/b01/q10/status.py +32 -0
  48. roborock_cli/_vendor/roborock/devices/traits/b01/q10/vacuum.py +81 -0
  49. roborock_cli/_vendor/roborock/devices/traits/b01/q7/__init__.py +136 -0
  50. roborock_cli/_vendor/roborock/devices/traits/b01/q7/clean_summary.py +75 -0
  51. roborock_cli/_vendor/roborock/devices/traits/traits_mixin.py +64 -0
  52. roborock_cli/_vendor/roborock/devices/traits/v1/__init__.py +344 -0
  53. roborock_cli/_vendor/roborock/devices/traits/v1/child_lock.py +29 -0
  54. roborock_cli/_vendor/roborock/devices/traits/v1/clean_summary.py +83 -0
  55. roborock_cli/_vendor/roborock/devices/traits/v1/command.py +38 -0
  56. roborock_cli/_vendor/roborock/devices/traits/v1/common.py +172 -0
  57. roborock_cli/_vendor/roborock/devices/traits/v1/consumeable.py +48 -0
  58. roborock_cli/_vendor/roborock/devices/traits/v1/device_features.py +74 -0
  59. roborock_cli/_vendor/roborock/devices/traits/v1/do_not_disturb.py +41 -0
  60. roborock_cli/_vendor/roborock/devices/traits/v1/dust_collection_mode.py +13 -0
  61. roborock_cli/_vendor/roborock/devices/traits/v1/flow_led_status.py +29 -0
  62. roborock_cli/_vendor/roborock/devices/traits/v1/home.py +285 -0
  63. roborock_cli/_vendor/roborock/devices/traits/v1/led_status.py +43 -0
  64. roborock_cli/_vendor/roborock/devices/traits/v1/map_content.py +83 -0
  65. roborock_cli/_vendor/roborock/devices/traits/v1/maps.py +80 -0
  66. roborock_cli/_vendor/roborock/devices/traits/v1/network_info.py +55 -0
  67. roborock_cli/_vendor/roborock/devices/traits/v1/rooms.py +105 -0
  68. roborock_cli/_vendor/roborock/devices/traits/v1/routines.py +26 -0
  69. roborock_cli/_vendor/roborock/devices/traits/v1/smart_wash_params.py +13 -0
  70. roborock_cli/_vendor/roborock/devices/traits/v1/status.py +101 -0
  71. roborock_cli/_vendor/roborock/devices/traits/v1/valley_electricity_timer.py +44 -0
  72. roborock_cli/_vendor/roborock/devices/traits/v1/volume.py +27 -0
  73. roborock_cli/_vendor/roborock/devices/traits/v1/wash_towel_mode.py +13 -0
  74. roborock_cli/_vendor/roborock/devices/transport/__init__.py +8 -0
  75. roborock_cli/_vendor/roborock/devices/transport/channel.py +32 -0
  76. roborock_cli/_vendor/roborock/devices/transport/local_channel.py +295 -0
  77. roborock_cli/_vendor/roborock/devices/transport/mqtt_channel.py +118 -0
  78. roborock_cli/_vendor/roborock/diagnostics.py +166 -0
  79. roborock_cli/_vendor/roborock/exceptions.py +95 -0
  80. roborock_cli/_vendor/roborock/map/__init__.py +7 -0
  81. roborock_cli/_vendor/roborock/map/map_parser.py +123 -0
  82. roborock_cli/_vendor/roborock/mqtt/__init__.py +10 -0
  83. roborock_cli/_vendor/roborock/mqtt/health_manager.py +60 -0
  84. roborock_cli/_vendor/roborock/mqtt/roborock_session.py +463 -0
  85. roborock_cli/_vendor/roborock/mqtt/session.py +108 -0
  86. roborock_cli/_vendor/roborock/protocol.py +558 -0
  87. roborock_cli/_vendor/roborock/protocols/__init__.py +3 -0
  88. roborock_cli/_vendor/roborock/protocols/a01_protocol.py +74 -0
  89. roborock_cli/_vendor/roborock/protocols/b01_q10_protocol.py +87 -0
  90. roborock_cli/_vendor/roborock/protocols/b01_q7_protocol.py +81 -0
  91. roborock_cli/_vendor/roborock/protocols/v1_protocol.py +271 -0
  92. roborock_cli/_vendor/roborock/py.typed +0 -0
  93. roborock_cli/_vendor/roborock/roborock_message.py +246 -0
  94. roborock_cli/_vendor/roborock/roborock_typing.py +382 -0
  95. roborock_cli/_vendor/roborock/util.py +54 -0
  96. roborock_cli/_vendor/roborock/web_api.py +761 -0
  97. roborock_cli/cli.py +715 -0
  98. roborock_cli/connection.py +202 -0
  99. roborock_cli/helpers.py +71 -0
  100. roborock_cli/server.py +759 -0
  101. roborock_cli/setup_auth.py +92 -0
  102. roborock_cli-0.1.1.dist-info/METADATA +172 -0
  103. roborock_cli-0.1.1.dist-info/RECORD +106 -0
  104. roborock_cli-0.1.1.dist-info/WHEEL +4 -0
  105. roborock_cli-0.1.1.dist-info/entry_points.txt +2 -0
  106. roborock_cli-0.1.1.dist-info/licenses/LICENSE +674 -0
@@ -0,0 +1,303 @@
1
+ from ..code_mappings import RoborockModeEnum
2
+
3
+
4
+ class WorkStatusMapping(RoborockModeEnum):
5
+ """Maps the general status of the robot."""
6
+
7
+ SLEEPING = ("sleeping", 0)
8
+ WAITING_FOR_ORDERS = ("waiting_for_orders", 1)
9
+ PAUSED = ("paused", 2)
10
+ DOCKING = ("docking", 3)
11
+ CHARGING = ("charging", 4)
12
+ SWEEP_MOPING = ("sweep_moping", 5)
13
+ SWEEP_MOPING_2 = ("sweep_moping_2", 6)
14
+ MOPING = ("moping", 7)
15
+ UPDATING = ("updating", 8)
16
+ MOP_CLEANING = ("mop_cleaning", 9)
17
+ MOP_AIRDRYING = ("mop_airdrying", 10)
18
+
19
+
20
+ class SCWindMapping(RoborockModeEnum):
21
+ """Maps suction power levels."""
22
+
23
+ SILENCE = ("quiet", 1)
24
+ STANDARD = ("balanced", 2)
25
+ STRONG = ("turbo", 3)
26
+ SUPER_STRONG = ("max", 4)
27
+ SUPER_STRONG_PLUS = ("max_plus", 5)
28
+
29
+
30
+ class WaterLevelMapping(RoborockModeEnum):
31
+ """Maps water flow levels."""
32
+
33
+ LOW = ("low", 1)
34
+ MEDIUM = ("medium", 2)
35
+ HIGH = ("high", 3)
36
+
37
+
38
+ class CleanTypeMapping(RoborockModeEnum):
39
+ """Maps the type of cleaning (Vacuum, Mop, or both)."""
40
+
41
+ VACUUM = ("vacuum", 0)
42
+ VAC_AND_MOP = ("vac_and_mop", 1)
43
+ MOP = ("mop", 2)
44
+
45
+
46
+ class CleanRepeatMapping(RoborockModeEnum):
47
+ """Maps the cleaning repeat parameter."""
48
+
49
+ ONE = ("one", 0)
50
+ TWO = ("two", 1)
51
+
52
+
53
+ class CleanPathPreferenceMapping(RoborockModeEnum):
54
+ """Maps the cleaning path preference parameter."""
55
+
56
+ BALANCED = ("balanced", 0)
57
+ DEEP = ("deep", 1)
58
+
59
+
60
+ class SCDeviceCleanParam(RoborockModeEnum):
61
+ """Maps the control values for cleaning tasks."""
62
+
63
+ STOP = ("stop", 0)
64
+ START = ("start", 1)
65
+ PAUSE = ("pause", 2)
66
+
67
+
68
+ class WorkModeMapping(RoborockModeEnum):
69
+ """Maps the detailed work modes of the robot."""
70
+
71
+ IDLE = ("idle", 0)
72
+ AUTO = ("auto", 1)
73
+ MANUAL = ("manual", 2)
74
+ AREA = ("area", 3)
75
+ AUTO_PAUSE = ("auto_pause", 4)
76
+ BACK_CHARGE = ("back_charge", 5)
77
+ POINT = ("point", 6)
78
+ NAVI = ("navi", 7)
79
+ AREA_PAUSE = ("area_pause", 8)
80
+ NAVI_PAUSE = ("navi_pause", 9)
81
+ GLOBAL_GO_HOME = ("global_go_home", 10)
82
+ GLOBAL_BROKEN = ("global_broken", 11)
83
+ NAVI_GO_HOME = ("navi_go_home", 12)
84
+ POINT_GO_HOME = ("point_go_home", 13)
85
+ NAVI_IDLE = ("navi_idle", 14)
86
+ SCREW = ("screw", 20)
87
+ SCREW_GO_HOME = ("screw_go_home", 21)
88
+ POINT_IDLE = ("point_idle", 22)
89
+ SCREW_IDLE = ("screw_idle", 23)
90
+ BORDER = ("border", 25)
91
+ BORDER_GO_HOME = ("border_go_home", 26)
92
+ BORDER_PAUSE = ("border_pause", 27)
93
+ BORDER_BROKEN = ("border_broken", 28)
94
+ BORDER_IDLE = ("border_idle", 29)
95
+ PLAN_AREA = ("plan_area", 30)
96
+ PLAN_AREA_PAUSE = ("plan_area_pause", 31)
97
+ PLAN_AREA_GO_HOME = ("plan_area_go_home", 32)
98
+ PLAN_AREA_BROKEN = ("plan_area_broken", 33)
99
+ PLAN_AREA_IDLE = ("plan_area_idle", 35)
100
+ MOPPING = ("mopping", 36)
101
+ MOPPING_PAUSE = ("mopping_pause", 37)
102
+ MOPPING_GO_HOME = ("mopping_go_home", 38)
103
+ MOPPING_BROKEN = ("mopping_broken", 39)
104
+ MOPPING_IDLE = ("mopping_idle", 40)
105
+ EXPLORING = ("exploring", 45)
106
+ EXPLORE_PAUSE = ("explore_pause", 46)
107
+ EXPLORE_GO_HOME = ("explore_go_home", 47)
108
+ EXPLORE_BROKEN = ("explore_broken", 48)
109
+ EXPLORE_IDLE = ("explore_idle", 49)
110
+
111
+
112
+ class StationActionMapping(RoborockModeEnum):
113
+ """Maps actions for the cleaning/drying station."""
114
+
115
+ STOP_CLEAN_OR_AIRDRY = ("stop_clean_or_airdry", 0)
116
+ MOP_CLEAN = ("mop_clean", 1)
117
+ MOP_AIRDRY = ("mop_airdry", 2)
118
+
119
+
120
+ class CleanTaskTypeMapping(RoborockModeEnum):
121
+ """Maps the high-level type of cleaning task selected."""
122
+
123
+ ALL = ("full", 0)
124
+ ROOM = ("room", 1)
125
+ AREA = ("zones", 4)
126
+ ROOM_NORMAL = ("room_normal", 5)
127
+ CUSTOM_MODE = ("customize", 6)
128
+ ALL_CUSTOM = ("all_custom", 11)
129
+ AREA_CUSTOM = ("area_custom", 99)
130
+
131
+
132
+ class CarpetModeMapping(RoborockModeEnum):
133
+ """Maps carpet handling parameters."""
134
+
135
+ FOLLOW_GLOBAL = ("follow_global", 0)
136
+ ON = ("on", 1)
137
+ OFF = ("off", 2)
138
+
139
+
140
+ class B01Fault(RoborockModeEnum):
141
+ """B01 fault codes and their descriptions."""
142
+
143
+ F_0 = ("fault_0", 0)
144
+ F_407 = ("cleaning_in_progress", 407) # Cleaning in progress. Scheduled cleanup ignored.
145
+ F_500 = (
146
+ "lidar_blocked",
147
+ 500,
148
+ ) # LiDAR turret or laser blocked. Check for obstruction and retry. LiDAR sensor obstructed or stuck.
149
+ # Remove foreign objects if any. If the problem persists, move the robot away and restart.
150
+ F_501 = (
151
+ "robot_suspended",
152
+ 501,
153
+ ) # Robot suspended. Move the robot away and restart. Cliff sensors dirty. Wipe them clean.
154
+ F_502 = (
155
+ "low_battery",
156
+ 502,
157
+ ) # Low battery. Recharge now. Battery low. Put the robot on the dock to charge it to 20% before starting.
158
+ F_503 = (
159
+ "dustbin_not_installed",
160
+ 503,
161
+ ) # Check that the dustbin and filter are installed properly. Reinstall the dustbin and filter in place.
162
+ # If the problem persists, replace the filter.
163
+ F_504 = ("fault_504", 504)
164
+ F_505 = ("fault_505", 505)
165
+ F_506 = ("fault_506", 506)
166
+ F_507 = ("fault_507", 507)
167
+ F_508 = ("fault_508", 508)
168
+ F_509 = ("cliff_sensor_error", 509) # Cliff sensors error. Clean them, move the robot away from drops, and restart.
169
+ F_510 = (
170
+ "bumper_stuck",
171
+ 510,
172
+ ) # Bumper stuck. Clean it and lightly tap to release it. Tap it repeatedly to release it. If no foreign object
173
+ # exists, move the robot away and restart.
174
+ F_511 = (
175
+ "docking_error",
176
+ 511,
177
+ ) # Docking error. Put the robot on the dock. Clear obstacles around the dock, clean charging contacts, and put
178
+ # the robot on the dock.
179
+ F_512 = (
180
+ "docking_error",
181
+ 512,
182
+ ) # Docking error. Put the robot on the dock. Clear obstacles around the dock, clean charging contacts, and put
183
+ # the robot on the dock.
184
+ F_513 = (
185
+ "robot_trapped",
186
+ 513,
187
+ ) # Robot trapped. Move the robot away and restart. Clear obstacles around robot or move robot away and restart.
188
+ F_514 = (
189
+ "robot_trapped",
190
+ 514,
191
+ ) # Robot trapped. Move the robot away and restart. Clear obstacles around robot or move robot away and restart.
192
+ F_515 = ("fault_515", 515)
193
+ F_517 = ("fault_517", 517)
194
+ F_518 = (
195
+ "low_battery",
196
+ 518,
197
+ ) # Low battery. Recharge now. Battery low. Put the robot on the dock to charge it to 20% before starting.
198
+ F_519 = ("fault_519", 519)
199
+ F_520 = ("fault_520", 520)
200
+ F_521 = ("fault_521", 521)
201
+ F_522 = ("mop_not_installed", 522) # Check that the mop is properly installed. Mop not installed. Reinstall it.
202
+ F_523 = ("fault_523", 523)
203
+ F_525 = ("fault_525", 525)
204
+ F_526 = ("fault_526", 526)
205
+ F_527 = ("fault_527", 527)
206
+ F_528 = ("fault_528", 528)
207
+ F_529 = ("fault_529", 529)
208
+ F_530 = ("fault_530", 530)
209
+ F_531 = ("fault_531", 531)
210
+ F_532 = ("fault_532", 532)
211
+ F_533 = ("long_sleep", 533) # About to shut down after a long time of sleep. Charge the robot.
212
+ F_534 = (
213
+ "low_battery_shutdown",
214
+ 534,
215
+ ) # Low battery. Turning off. About to shut down due to low battery. Charge the robot.
216
+ F_535 = ("fault_535", 535)
217
+ F_536 = ("fault_536", 536)
218
+ F_540 = ("fault_540", 540)
219
+ F_541 = ("fault_541", 541)
220
+ F_542 = ("fault_542", 542)
221
+ F_550 = ("fault_550", 550)
222
+ F_551 = ("fault_551", 551)
223
+ F_559 = ("fault_559", 559)
224
+ F_560 = ("side_brush_entangled", 560) # Side brush entangled. Remove and clean it.
225
+ F_561 = ("fault_561", 561)
226
+ F_562 = ("fault_562", 562)
227
+ F_563 = ("fault_563", 563)
228
+ F_564 = ("fault_564", 564)
229
+ F_565 = ("fault_565", 565)
230
+ F_566 = ("fault_566", 566)
231
+ F_567 = ("fault_567", 567)
232
+ F_568 = ("main_wheels_entangled", 568) # Clean main wheels, move the robot away and restart.
233
+ F_569 = ("main_wheels_entangled", 569) # Clean main wheels, move the robot away and restart.
234
+ F_570 = ("main_brush_entangled", 570) # Main brush entangled. Remove and clean it and its bearing.
235
+ F_571 = ("fault_571", 571)
236
+ F_572 = ("main_brush_entangled", 572) # Main brush entangled. Remove and clean it and its bearing.
237
+ F_573 = ("fault_573", 573)
238
+ F_574 = ("fault_574", 574)
239
+ F_580 = ("fault_580", 580)
240
+ F_581 = ("fault_581", 581)
241
+ F_582 = ("fault_582", 582)
242
+ F_583 = ("fault_583", 583)
243
+ F_584 = ("fault_584", 584)
244
+ F_585 = ("fault_585", 585)
245
+ F_586 = ("fault_586", 586)
246
+ F_587 = ("fault_587", 587)
247
+ F_588 = ("fault_588", 588)
248
+ F_589 = ("fault_589", 589)
249
+ F_590 = ("fault_590", 590)
250
+ F_591 = ("fault_591", 591)
251
+ F_592 = ("fault_592", 592)
252
+ F_593 = ("fault_593", 593)
253
+ F_594 = (
254
+ "dust_bag_not_installed",
255
+ 594,
256
+ ) # Make sure the dust bag is properly installed. Dust bag not installed. Check that it is installed properly.
257
+ F_601 = ("fault_601", 601)
258
+ F_602 = ("fault_602", 602)
259
+ F_603 = ("fault_603", 603)
260
+ F_604 = ("fault_604", 604)
261
+ F_605 = ("fault_605", 605)
262
+ F_611 = ("positioning_failed", 611) # Positioning failed. Move the robot back to the dock and remap.
263
+ F_612 = (
264
+ "map_changed",
265
+ 612,
266
+ ) # Map changed. Positioning failed. Try again. New environment detected. Map changed. Positioning failed.
267
+ # Try again after remapping.
268
+ F_629 = ("mop_mount_fell_off", 629) # Mop cloth mount fell off. Reinstall it to resume working.
269
+ F_668 = (
270
+ "system_error",
271
+ 668,
272
+ ) # Robot error. Reset the system. Fan error. Reset the system. If the problem persists, contact customer service.
273
+ F_2000 = ("fault_2000", 2000)
274
+ F_2003 = ("low_battery_schedule_canceled", 2003) # Battery level below 20%. Scheduled task canceled.
275
+ F_2007 = (
276
+ "cannot_reach_target",
277
+ 2007,
278
+ ) # Unable to reach the target. Cleaning ended. Ensure the door to the target area is open or unobstructed.
279
+ F_2012 = (
280
+ "cannot_reach_target",
281
+ 2012,
282
+ ) # Unable to reach the target. Cleaning ended. Ensure the door to the target area is open or unobstructed.
283
+ F_2013 = ("fault_2013", 2013)
284
+ F_2015 = ("fault_2015", 2015)
285
+ F_2017 = ("fault_2017", 2017)
286
+ F_2100 = (
287
+ "low_battery_resume_later",
288
+ 2100,
289
+ ) # Low battery. Resume cleaning after recharging. Low battery. Starting to recharge. Resume cleaning after
290
+ # charging.
291
+ F_2101 = ("fault_2101", 2101)
292
+ F_2102 = ("cleaning_complete", 2102) # Cleaning completed. Returning to the dock.
293
+ F_2103 = ("fault_2103", 2103)
294
+ F_2104 = ("fault_2104", 2104)
295
+ F_2105 = ("fault_2105", 2105)
296
+ F_2108 = ("fault_2108", 2108)
297
+ F_2109 = ("fault_2109", 2109)
298
+ F_2110 = ("fault_2110", 2110)
299
+ F_2111 = ("fault_2111", 2111)
300
+ F_2112 = ("fault_2112", 2112)
301
+ F_2113 = ("fault_2113", 2113)
302
+ F_2114 = ("fault_2114", 2114)
303
+ F_2115 = ("fault_2115", 2115)
@@ -0,0 +1,302 @@
1
+ import datetime
2
+ import json
3
+ from dataclasses import dataclass, field
4
+ from functools import cached_property
5
+
6
+ from ...exceptions import RoborockException
7
+ from ..containers import RoborockBase
8
+ from .b01_q7_code_mappings import (
9
+ B01Fault,
10
+ CleanPathPreferenceMapping,
11
+ CleanRepeatMapping,
12
+ CleanTypeMapping,
13
+ SCWindMapping,
14
+ WaterLevelMapping,
15
+ WorkModeMapping,
16
+ WorkStatusMapping,
17
+ )
18
+
19
+
20
+ @dataclass
21
+ class NetStatus(RoborockBase):
22
+ """Represents the network status of the device."""
23
+
24
+ rssi: str
25
+ loss: int
26
+ ping: int
27
+ ip: str
28
+ mac: str
29
+ ssid: str
30
+ frequency: int
31
+ bssid: str
32
+
33
+
34
+ @dataclass
35
+ class OrderTotal(RoborockBase):
36
+ """Represents the order total information."""
37
+
38
+ total: int
39
+ enable: int
40
+
41
+
42
+ @dataclass
43
+ class Privacy(RoborockBase):
44
+ """Represents the privacy settings of the device."""
45
+
46
+ ai_recognize: int
47
+ dirt_recognize: int
48
+ pet_recognize: int
49
+ carpet_turbo: int
50
+ carpet_avoid: int
51
+ carpet_show: int
52
+ map_uploads: int
53
+ ai_agent: int
54
+ ai_avoidance: int
55
+ record_uploads: int
56
+ along_floor: int
57
+ auto_upgrade: int
58
+
59
+
60
+ @dataclass
61
+ class PvCharging(RoborockBase):
62
+ """Represents the photovoltaic charging status."""
63
+
64
+ status: int
65
+ begin_time: int
66
+ end_time: int
67
+
68
+
69
+ @dataclass
70
+ class Recommend(RoborockBase):
71
+ """Represents cleaning recommendations."""
72
+
73
+ sill: int
74
+ wall: int
75
+ room_id: list[int] = field(default_factory=list)
76
+
77
+
78
+ @dataclass
79
+ class B01Props(RoborockBase):
80
+ """
81
+ Represents the complete properties and status for a Roborock B01 model.
82
+ This dataclass is generated based on the device's status JSON object.
83
+ """
84
+
85
+ status: WorkStatusMapping | None = None
86
+ fault: B01Fault | None = None
87
+ wind: SCWindMapping | None = None
88
+ water: WaterLevelMapping | None = None
89
+ mode: CleanTypeMapping | None = None
90
+ quantity: int | None = None
91
+ alarm: int | None = None
92
+ volume: int | None = None
93
+ hypa: int | None = None
94
+ main_brush: int | None = None
95
+ side_brush: int | None = None
96
+ mop_life: int | None = None
97
+ main_sensor: int | None = None
98
+ net_status: NetStatus | None = None
99
+ repeat_state: CleanRepeatMapping | None = None
100
+ tank_state: int | None = None
101
+ sweep_type: int | None = None
102
+ clean_path_preference: CleanPathPreferenceMapping | None = None
103
+ cloth_state: int | None = None
104
+ time_zone: int | None = None
105
+ time_zone_info: str | None = None
106
+ language: int | None = None
107
+ cleaning_time: int | None = None
108
+ real_clean_time: int | None = None
109
+ cleaning_area: int | None = None
110
+ custom_type: int | None = None
111
+ sound: int | None = None
112
+ work_mode: WorkModeMapping | None = None
113
+ station_act: int | None = None
114
+ charge_state: int | None = None
115
+ current_map_id: int | None = None
116
+ map_num: int | None = None
117
+ dust_action: int | None = None
118
+ quiet_is_open: int | None = None
119
+ quiet_begin_time: int | None = None
120
+ quiet_end_time: int | None = None
121
+ clean_finish: int | None = None
122
+ voice_type: int | None = None
123
+ voice_type_version: int | None = None
124
+ order_total: OrderTotal | None = None
125
+ build_map: int | None = None
126
+ privacy: Privacy | None = None
127
+ dust_auto_state: int | None = None
128
+ dust_frequency: int | None = None
129
+ child_lock: int | None = None
130
+ multi_floor: int | None = None
131
+ map_save: int | None = None
132
+ light_mode: int | None = None
133
+ green_laser: int | None = None
134
+ dust_bag_used: int | None = None
135
+ order_save_mode: int | None = None
136
+ manufacturer: str | None = None
137
+ back_to_wash: int | None = None
138
+ charge_station_type: int | None = None
139
+ pv_cut_charge: int | None = None
140
+ pv_charging: PvCharging | None = None
141
+ serial_number: str | None = None
142
+ recommend: Recommend | None = None
143
+ add_sweep_status: int | None = None
144
+
145
+ @property
146
+ def main_brush_time_left(self) -> int | None:
147
+ """
148
+ Returns estimated remaining life of the main brush in minutes.
149
+ Total life is 300 hours (18000 minutes).
150
+ """
151
+ if self.main_brush is None:
152
+ return None
153
+ return max(0, 18000 - self.main_brush)
154
+
155
+ @property
156
+ def side_brush_time_left(self) -> int | None:
157
+ """
158
+ Returns estimated remaining life of the side brush in minutes.
159
+ Total life is 200 hours (12000 minutes).
160
+ """
161
+ if self.side_brush is None:
162
+ return None
163
+ return max(0, 12000 - self.side_brush)
164
+
165
+ @property
166
+ def filter_time_left(self) -> int | None:
167
+ """
168
+ Returns estimated remaining life of the filter (hypa) in minutes.
169
+ Total life is 150 hours (9000 minutes).
170
+ """
171
+ if self.hypa is None:
172
+ return None
173
+ return max(0, 9000 - self.hypa)
174
+
175
+ @property
176
+ def mop_life_time_left(self) -> int | None:
177
+ """
178
+ Returns estimated remaining life of the mop in minutes.
179
+ Total life is 180 hours (10800 minutes).
180
+ """
181
+ if self.mop_life is None:
182
+ return None
183
+ return max(0, 10800 - self.mop_life)
184
+
185
+ @property
186
+ def sensor_dirty_time_left(self) -> int | None:
187
+ """
188
+ Returns estimated time until sensors need cleaning in minutes.
189
+ Maintenance interval is typically 30 hours (1800 minutes).
190
+ """
191
+ if self.main_sensor is None:
192
+ return None
193
+ return max(0, 1800 - self.main_sensor)
194
+
195
+ @property
196
+ def status_name(self) -> str | None:
197
+ """Returns the name of the current status."""
198
+ return self.status.value if self.status is not None else None
199
+
200
+ @property
201
+ def fault_name(self) -> str | None:
202
+ """Returns the name of the current fault."""
203
+ return self.fault.value if self.fault is not None else None
204
+
205
+ @property
206
+ def wind_name(self) -> str | None:
207
+ """Returns the name of the current fan speed (wind)."""
208
+ return self.wind.value if self.wind is not None else None
209
+
210
+ @property
211
+ def work_mode_name(self) -> str | None:
212
+ """Returns the name of the current work mode."""
213
+ return self.work_mode.value if self.work_mode is not None else None
214
+
215
+ @property
216
+ def repeat_state_name(self) -> str | None:
217
+ """Returns the name of the current repeat state."""
218
+ return self.repeat_state.value if self.repeat_state is not None else None
219
+
220
+ @property
221
+ def clean_path_preference_name(self) -> str | None:
222
+ """Returns the name of the current clean path preference."""
223
+ return self.clean_path_preference.value if self.clean_path_preference is not None else None
224
+
225
+
226
+ @dataclass
227
+ class CleanRecordDetail(RoborockBase):
228
+ """Represents a single clean record detail (from `record_list[].detail`)."""
229
+
230
+ record_start_time: int | None = None
231
+ method: int | None = None
232
+ record_use_time: int | None = None
233
+ clean_count: int | None = None
234
+ # This is seemingly returned in meters (non-squared)
235
+ record_clean_area: int | None = None
236
+ record_clean_mode: int | None = None
237
+ record_clean_way: int | None = None
238
+ record_task_status: int | None = None
239
+ record_faultcode: int | None = None
240
+ record_dust_num: int | None = None
241
+ clean_current_map: int | None = None
242
+ record_map_url: str | None = None
243
+
244
+ @property
245
+ def start_datetime(self) -> datetime.datetime | None:
246
+ """Convert the start datetime into a datetime object."""
247
+ if self.record_start_time is not None:
248
+ return datetime.datetime.fromtimestamp(self.record_start_time).astimezone(datetime.UTC)
249
+ return None
250
+
251
+ @property
252
+ def square_meters_area_cleaned(self) -> float | None:
253
+ """Returns the area cleaned in square meters."""
254
+ if self.record_clean_area is not None:
255
+ return self.record_clean_area / 100
256
+ return None
257
+
258
+
259
+ @dataclass
260
+ class CleanRecordListItem(RoborockBase):
261
+ """Represents an entry in the clean record list returned by `service.get_record_list`."""
262
+
263
+ url: str | None = None
264
+ detail: str | None = None
265
+
266
+ @cached_property
267
+ def detail_parsed(self) -> CleanRecordDetail | None:
268
+ """Parse and return the detail as a CleanRecordDetail object."""
269
+ if self.detail is None:
270
+ return None
271
+ try:
272
+ parsed = json.loads(self.detail)
273
+ except json.JSONDecodeError as ex:
274
+ raise RoborockException(f"Invalid B01 record detail JSON: {self.detail!r}") from ex
275
+ return CleanRecordDetail.from_dict(parsed)
276
+
277
+
278
+ @dataclass
279
+ class CleanRecordList(RoborockBase):
280
+ """Represents the clean record list response from `service.get_record_list`."""
281
+
282
+ total_area: int | None = None
283
+ total_time: int | None = None # stored in seconds
284
+ total_count: int | None = None
285
+ record_list: list[CleanRecordListItem] = field(default_factory=list)
286
+
287
+ @property
288
+ def square_meters_area_cleaned(self) -> float | None:
289
+ """Returns the area cleaned in square meters."""
290
+ if self.total_area is not None:
291
+ return self.total_area / 100
292
+ return None
293
+
294
+
295
+ @dataclass
296
+ class CleanRecordSummary(RoborockBase):
297
+ """Represents clean record totals for B01/Q7 devices."""
298
+
299
+ total_time: int | None = None
300
+ total_area: int | None = None
301
+ total_count: int | None = None
302
+ last_record_detail: CleanRecordDetail | None = None