roborock.data.v1.v1_containers
1import datetime 2import logging 3from dataclasses import dataclass, field 4from enum import StrEnum 5from typing import Any 6 7from roborock.const import ( 8 CLEANING_BRUSH_REPLACE_TIME, 9 DUST_COLLECTION_REPLACE_TIME, 10 FILTER_REPLACE_TIME, 11 MAIN_BRUSH_REPLACE_TIME, 12 MOP_ROLLER_REPLACE_TIME, 13 NO_MAP, 14 SENSOR_DIRTY_REPLACE_TIME, 15 SIDE_BRUSH_REPLACE_TIME, 16 STRAINER_REPLACE_TIME, 17) 18from roborock.roborock_message import RoborockDataProtocol 19 20from ..containers import NamedRoomMapping, RoborockBase, RoborockBaseTimer, _attr_repr, field_metadata 21from .v1_clean_modes import WashTowelModes 22from .v1_code_mappings import ( 23 CleanFluidStatus, 24 ClearWaterBoxStatus, 25 DirtyWaterBoxStatus, 26 DustBagStatus, 27 RoborockChargeStatus, 28 RoborockCleanType, 29 RoborockDockDustCollectionModeCode, 30 RoborockDockErrorCode, 31 RoborockDockState, 32 RoborockDockTypeCode, 33 RoborockErrorCode, 34 RoborockFinishReason, 35 RoborockInCleaning, 36 RoborockStartType, 37 RoborockStateCode, 38) 39 40_LOGGER = logging.getLogger(__name__) 41 42 43class FieldNameBase(StrEnum): 44 """A base enum class that represents a field name in a RoborockBase dataclass.""" 45 46 47class StatusField(FieldNameBase): 48 """An enum that represents a field in the `StatusV2` class. 49 50 This is used with `roborock.devices.traits.v1.status.DeviceFeaturesTrait` 51 to understand if a feature is supported by the device using `is_field_supported`. 52 53 The enum values are names of fields in the `StatusV2` class. Each field is 54 annotated with `dps` metadata to map the field to a `RoborockDataProtocol` 55 value used to check support against the product schema. 56 """ 57 58 STATE = "state" 59 BATTERY = "battery" 60 FAN_POWER = "fan_power" 61 WATER_BOX_MODE = "water_box_mode" 62 CHARGE_STATUS = "charge_status" 63 DRY_STATUS = "dry_status" 64 ERROR_CODE = "error_code" 65 WATER_BOX_CARRIAGE_STATUS = "water_box_carriage_status" 66 WATER_BOX_STATUS = "water_box_status" 67 WATER_SHORTAGE_STATUS = "water_shortage_status" 68 DIRTY_WATER_BOX_STATUS = "dirty_water_box_status" 69 CLEAR_WATER_BOX_STATUS = "clear_water_box_status" 70 CLEAN_FLUID_STATUS = "clean_fluid_status" 71 CLEAN_PERCENT = "clean_percent" 72 DOCK_ERROR_STATUS = "dock_error_status" 73 RDT = "rdt" 74 75 76@dataclass 77class StatusV2(RoborockBase): 78 """The result of a GET_STATUS API request.""" 79 80 msg_ver: int | None = None 81 msg_seq: int | None = None 82 state: RoborockStateCode | None = field(default=None, metadata={"dps": RoborockDataProtocol.STATE}) 83 battery: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.BATTERY}) 84 clean_time: int | None = None 85 clean_area: int | None = None 86 error_code: RoborockErrorCode | None = field(default=None, metadata={"dps": RoborockDataProtocol.ERROR_CODE}) 87 map_present: int | None = None 88 in_cleaning: RoborockInCleaning | None = None 89 in_returning: int | None = None 90 in_fresh_state: int | None = None 91 lab_status: int | None = None 92 water_box_status: int | None = field(default=None, metadata={"feature": "is_support_water_mode"}) 93 back_type: int | None = None 94 wash_phase: int | None = None 95 wash_ready: int | None = None 96 fan_power: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.FAN_POWER}) 97 dnd_enabled: int | None = None 98 map_status: int | None = None 99 is_locating: int | None = None 100 lock_status: int | None = None 101 water_box_mode: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.WATER_BOX_MODE}) 102 water_box_carriage_status: int | None = field(default=None, metadata={"feature": "is_support_water_mode"}) 103 mop_forbidden_enable: int | None = None 104 camera_status: int | None = None 105 is_exploring: int | None = None 106 home_sec_status: int | None = None 107 home_sec_enable_password: int | None = None 108 adbumper_status: list[int] | None = None 109 water_shortage_status: int | None = field(default=None, metadata={"feature": "is_support_water_mode"}) 110 dock_type: RoborockDockTypeCode | None = None 111 dust_collection_status: int | None = None 112 auto_dust_collection: int | None = None 113 avoid_count: int | None = None 114 mop_mode: int | None = None 115 debug_mode: int | None = None 116 collision_avoid_status: int | None = None 117 switch_map_mode: int | None = None 118 dock_error_status: RoborockDockErrorCode | None = field(default=None, metadata={"dock_feature": "has_dock"}) 119 120 charge_status: RoborockChargeStatus | None = field( 121 default=None, metadata={"dps": RoborockDataProtocol.CHARGE_STATUS} 122 ) 123 unsave_map_reason: int | None = None 124 unsave_map_flag: int | None = None 125 wash_status: int | None = None 126 distance_off: int | None = None 127 in_warmup: int | None = None 128 dry_status: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.DRYING_STATUS}) 129 rdt: int | None = field(default=None, metadata={"feature": "is_supported_drying"}) 130 clean_percent: int | None = field(default=None, metadata={"feature": "is_support_clean_estimate"}) 131 rss: int | None = None 132 dss: int | None = None 133 common_status: int | None = None 134 corner_clean_mode: int | None = None 135 last_clean_t: int | None = None 136 replenish_mode: int | None = None 137 repeat: int | None = None 138 kct: int | None = None 139 subdivision_sets: int | None = None 140 141 @property 142 def square_meter_clean_area(self) -> float | None: 143 return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None 144 145 @property 146 def error_code_name(self) -> str | None: 147 return self.error_code.display_name if self.error_code is not None else None 148 149 @property 150 def state_name(self) -> str | None: 151 return self.state.display_name if self.state is not None else None 152 153 @property 154 def current_map(self) -> int | None: 155 """Returns the current map ID if the map is present.""" 156 if self.map_status is not None: 157 map_flag = self.map_status >> 2 158 if map_flag != NO_MAP: 159 return map_flag 160 return None 161 162 @property 163 def has_am(self) -> bool | None: 164 if self.dss is None: 165 return None 166 return (self.dss & 3) == 2 167 168 @property 169 @field_metadata(dock_feature="is_washable") 170 def clear_water_box_status(self) -> ClearWaterBoxStatus | None: 171 if self.dss: 172 return ClearWaterBoxStatus((self.dss >> 2) & 3) 173 return None 174 175 @property 176 @field_metadata(dock_feature="is_washable") 177 def dirty_water_box_status(self) -> DirtyWaterBoxStatus | None: 178 if self.dss: 179 return DirtyWaterBoxStatus((self.dss >> 4) & 3) 180 return None 181 182 @property 183 def dust_bag_status(self) -> DustBagStatus | None: 184 if self.dss: 185 return DustBagStatus((self.dss >> 6) & 3) 186 return None 187 188 @property 189 def water_box_filter_status(self) -> int | None: 190 if self.dss: 191 return (self.dss >> 8) & 3 192 return None 193 194 @property 195 @field_metadata( 196 dock_feature="is_clean_fluid_auto_delivery_supported", 197 ) 198 def clean_fluid_status(self) -> CleanFluidStatus | None: 199 if self.dss: 200 value = (self.dss >> 10) & 3 201 if value == 0: 202 return None # Feature not supported by this device 203 return CleanFluidStatus(value) 204 return None 205 206 @property 207 def hatch_door_status(self) -> int | None: 208 if self.dss: 209 return (self.dss >> 12) & 7 210 return None 211 212 @property 213 def dock_cool_fan_status(self) -> int | None: 214 if self.dss: 215 return (self.dss >> 15) & 3 216 return None 217 218 @property 219 def dock_state(self) -> RoborockDockState: 220 """A synthesized, high-level dock state reflecting the UI's display. 221 222 This property simplifies integration by handling the complex logic 223 of checking state, charge_status, and battery level simultaneously. It handles 224 newer off-peak charging logic seamlessly while maintaining backwards compatibility 225 with older devices. 226 """ 227 if self.state is None or self.state == RoborockStateCode.unknown: 228 return RoborockDockState.unknown 229 230 # 6. DUSTING 231 if self.state == RoborockStateCode.emptying_the_bin: 232 return RoborockDockState.dusting 233 234 # 5. FULL 235 if self.state == RoborockStateCode.charging_complete or ( 236 self.state == RoborockStateCode.charging and self.battery == 100 237 ): 238 return RoborockDockState.full 239 240 # 3 & 4. CHARGING and CHARGE_WAITING 241 if self.state == RoborockStateCode.charging: 242 if self.charge_status == RoborockChargeStatus.charge_waiting: 243 return RoborockDockState.off_peak_waiting 244 return RoborockDockState.charging 245 246 # 2. RECHARGING 247 if self.state in (RoborockStateCode.returning_home, RoborockStateCode.docking): 248 return RoborockDockState.returning 249 250 # 1. IDLE (Not on dock, or doing something else) 251 return RoborockDockState.idle 252 253 def __repr__(self) -> str: 254 return _attr_repr(self) 255 256 257@dataclass 258class DnDTimer(RoborockBaseTimer): 259 """DnDTimer""" 260 261 262@dataclass 263class ValleyElectricityTimer(RoborockBaseTimer): 264 """ValleyElectricityTimer""" 265 266 267@dataclass 268class CleanSummary(RoborockBase): 269 clean_time: int | None = None 270 clean_area: int | None = None 271 clean_count: int | None = None 272 dust_collection_count: int | None = None 273 records: list[int] | None = None 274 last_clean_t: int | None = None 275 276 @property 277 def square_meter_clean_area(self) -> float | None: 278 """Returns the clean area in square meters.""" 279 if isinstance(self.clean_area, list | str): 280 _LOGGER.warning(f"Clean area is a unexpected type! Please give the following in a issue: {self.clean_area}") 281 return None 282 return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None 283 284 def __repr__(self) -> str: 285 """Return a string representation of the object including all attributes.""" 286 return _attr_repr(self) 287 288 289@dataclass 290class CleanRecord(RoborockBase): 291 begin: int | None = None 292 end: int | None = None 293 duration: int | None = None 294 area: int | None = None 295 error: int | None = None 296 complete: int | None = None 297 start_type: RoborockStartType | None = None 298 clean_type: RoborockCleanType | None = None 299 finish_reason: RoborockFinishReason | None = None 300 dust_collection_status: int | None = None 301 avoid_count: int | None = None 302 wash_count: int | None = None 303 map_flag: int | None = None 304 305 @property 306 def square_meter_area(self) -> float | None: 307 return round(self.area / 1000000, 1) if self.area is not None else None 308 309 @property 310 def begin_datetime(self) -> datetime.datetime | None: 311 return datetime.datetime.fromtimestamp(self.begin).astimezone(datetime.UTC) if self.begin else None 312 313 @property 314 def end_datetime(self) -> datetime.datetime | None: 315 return datetime.datetime.fromtimestamp(self.end).astimezone(datetime.UTC) if self.end else None 316 317 def __repr__(self) -> str: 318 return _attr_repr(self) 319 320 321class CleanSummaryWithDetail(CleanSummary): 322 """CleanSummary with the last CleanRecord included.""" 323 324 last_clean_record: CleanRecord | None = None 325 326 327class ConsumableField(FieldNameBase): 328 """An enum that represents a field in the `Consumable` class. 329 330 This is used with `roborock.devices.traits.v1.status.DeviceFeaturesTrait` 331 to understand if a feature is supported by the device using `is_field_supported`. 332 333 The enum values are names of fields in the `Consumable` class. Each field is 334 annotated with `dps` metadata to map the field to a `RoborockDataProtocol` 335 value used to check support against the product schema. 336 """ 337 338 MAIN_BRUSH_WORK_TIME = "main_brush_work_time" 339 SIDE_BRUSH_WORK_TIME = "side_brush_work_time" 340 FILTER_WORK_TIME = "filter_work_time" 341 342 343@dataclass 344class Consumable(RoborockBase): 345 main_brush_work_time: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.MAIN_BRUSH_WORK_TIME}) 346 side_brush_work_time: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.SIDE_BRUSH_WORK_TIME}) 347 filter_work_time: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.FILTER_WORK_TIME}) 348 filter_element_work_time: int | None = None 349 sensor_dirty_time: int | None = None 350 strainer_work_times: int | None = None 351 dust_collection_work_times: int | None = None 352 cleaning_brush_work_times: int | None = None 353 moproller_work_time: int | None = None 354 355 @property 356 def main_brush_time_left(self) -> int | None: 357 return MAIN_BRUSH_REPLACE_TIME - self.main_brush_work_time if self.main_brush_work_time is not None else None 358 359 @property 360 def side_brush_time_left(self) -> int | None: 361 return SIDE_BRUSH_REPLACE_TIME - self.side_brush_work_time if self.side_brush_work_time is not None else None 362 363 @property 364 def filter_time_left(self) -> int | None: 365 return FILTER_REPLACE_TIME - self.filter_work_time if self.filter_work_time is not None else None 366 367 @property 368 def sensor_time_left(self) -> int | None: 369 return SENSOR_DIRTY_REPLACE_TIME - self.sensor_dirty_time if self.sensor_dirty_time is not None else None 370 371 @property 372 def strainer_time_left(self) -> int | None: 373 return STRAINER_REPLACE_TIME - self.strainer_work_times if self.strainer_work_times is not None else None 374 375 @property 376 def dust_collection_time_left(self) -> int | None: 377 return ( 378 DUST_COLLECTION_REPLACE_TIME - self.dust_collection_work_times 379 if self.dust_collection_work_times is not None 380 else None 381 ) 382 383 @property 384 def cleaning_brush_time_left(self) -> int | None: 385 return ( 386 CLEANING_BRUSH_REPLACE_TIME - self.cleaning_brush_work_times 387 if self.cleaning_brush_work_times is not None 388 else None 389 ) 390 391 @property 392 def mop_roller_time_left(self) -> int | None: 393 return MOP_ROLLER_REPLACE_TIME - self.moproller_work_time if self.moproller_work_time is not None else None 394 395 def __repr__(self) -> str: 396 return _attr_repr(self) 397 398 399@dataclass 400class MultiMapsListRoom(RoborockBase): 401 id: int | None = None 402 tag: int | None = None 403 iot_name_id: str | None = None 404 iot_name: str | None = None 405 406 @property 407 def named_room_mapping(self) -> NamedRoomMapping | None: 408 """Returns a NamedRoomMapping object if valid.""" 409 if self.id is None or self.iot_name_id is None: 410 return None 411 return NamedRoomMapping( 412 segment_id=self.id, 413 iot_id=self.iot_name_id, 414 raw_name=self.iot_name, 415 ) 416 417 418@dataclass 419class MultiMapsListMapInfoBakMaps(RoborockBase): 420 mapflag: Any | None = None 421 add_time: Any | None = None 422 423 424@dataclass 425class MultiMapsListMapInfo(RoborockBase): 426 map_flag: int 427 name: str 428 add_time: Any | None = None 429 length: Any | None = None 430 bak_maps: list[MultiMapsListMapInfoBakMaps] | None = None 431 rooms: list[MultiMapsListRoom] | None = None 432 433 @property 434 def mapFlag(self) -> int: 435 """Alias for map_flag, returns the map flag as an integer.""" 436 return self.map_flag 437 438 @property 439 def rooms_map(self) -> dict[int, NamedRoomMapping]: 440 """Returns a dictionary of room mappings by segment id.""" 441 return { 442 room.id: mapping 443 for room in self.rooms or () 444 if room.id is not None and (mapping := room.named_room_mapping) is not None 445 } 446 447 448@dataclass 449class MultiMapsList(RoborockBase): 450 max_multi_map: int | None = None 451 max_bak_map: int | None = None 452 multi_map_count: int | None = None 453 map_info: list[MultiMapsListMapInfo] | None = None 454 455 456@dataclass 457class SmartWashParams(RoborockBase): 458 smart_wash: int | None = None 459 wash_interval: int | None = None 460 461 462@dataclass 463class DustCollectionMode(RoborockBase): 464 mode: RoborockDockDustCollectionModeCode | None = None 465 466 467@dataclass 468class WashTowelMode(RoborockBase): 469 wash_mode: WashTowelModes | None = None 470 471 472@dataclass 473class NetworkInfo(RoborockBase): 474 ip: str 475 ssid: str | None = None 476 mac: str | None = None 477 bssid: str | None = None 478 rssi: int | None = None 479 480 481@dataclass 482class AppInitStatusLocalInfo(RoborockBase): 483 location: str 484 bom: str | None = None 485 featureset: int | None = None 486 language: str | None = None 487 logserver: str | None = None 488 wifiplan: str | None = None 489 timezone: str | None = None 490 name: str | None = None 491 492 493@dataclass 494class AppInitStatus(RoborockBase): 495 local_info: AppInitStatusLocalInfo 496 feature_info: list[int] 497 new_feature_info: int = 0 498 new_feature_info_str: str = "" 499 new_feature_info_2: int | None = None 500 carriage_type: int | None = None 501 dsp_version: str | None = None 502 503 504@dataclass 505class ChildLockStatus(RoborockBase): 506 lock_status: int = 0 507 508 509@dataclass 510class FlowLedStatus(RoborockBase): 511 status: int = 0 512 513 514@dataclass 515class LedStatus(RoborockBase): 516 status: int = 0
44class FieldNameBase(StrEnum): 45 """A base enum class that represents a field name in a RoborockBase dataclass."""
A base enum class that represents a field name in a RoborockBase dataclass.
48class StatusField(FieldNameBase): 49 """An enum that represents a field in the `StatusV2` class. 50 51 This is used with `roborock.devices.traits.v1.status.DeviceFeaturesTrait` 52 to understand if a feature is supported by the device using `is_field_supported`. 53 54 The enum values are names of fields in the `StatusV2` class. Each field is 55 annotated with `dps` metadata to map the field to a `RoborockDataProtocol` 56 value used to check support against the product schema. 57 """ 58 59 STATE = "state" 60 BATTERY = "battery" 61 FAN_POWER = "fan_power" 62 WATER_BOX_MODE = "water_box_mode" 63 CHARGE_STATUS = "charge_status" 64 DRY_STATUS = "dry_status" 65 ERROR_CODE = "error_code" 66 WATER_BOX_CARRIAGE_STATUS = "water_box_carriage_status" 67 WATER_BOX_STATUS = "water_box_status" 68 WATER_SHORTAGE_STATUS = "water_shortage_status" 69 DIRTY_WATER_BOX_STATUS = "dirty_water_box_status" 70 CLEAR_WATER_BOX_STATUS = "clear_water_box_status" 71 CLEAN_FLUID_STATUS = "clean_fluid_status" 72 CLEAN_PERCENT = "clean_percent" 73 DOCK_ERROR_STATUS = "dock_error_status" 74 RDT = "rdt"
An enum that represents a field in the StatusV2 class.
This is used with roborock.devices.traits.v1.status.DeviceFeaturesTrait
to understand if a feature is supported by the device using is_field_supported.
The enum values are names of fields in the StatusV2 class. Each field is
annotated with dps metadata to map the field to a RoborockDataProtocol
value used to check support against the product schema.
77@dataclass 78class StatusV2(RoborockBase): 79 """The result of a GET_STATUS API request.""" 80 81 msg_ver: int | None = None 82 msg_seq: int | None = None 83 state: RoborockStateCode | None = field(default=None, metadata={"dps": RoborockDataProtocol.STATE}) 84 battery: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.BATTERY}) 85 clean_time: int | None = None 86 clean_area: int | None = None 87 error_code: RoborockErrorCode | None = field(default=None, metadata={"dps": RoborockDataProtocol.ERROR_CODE}) 88 map_present: int | None = None 89 in_cleaning: RoborockInCleaning | None = None 90 in_returning: int | None = None 91 in_fresh_state: int | None = None 92 lab_status: int | None = None 93 water_box_status: int | None = field(default=None, metadata={"feature": "is_support_water_mode"}) 94 back_type: int | None = None 95 wash_phase: int | None = None 96 wash_ready: int | None = None 97 fan_power: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.FAN_POWER}) 98 dnd_enabled: int | None = None 99 map_status: int | None = None 100 is_locating: int | None = None 101 lock_status: int | None = None 102 water_box_mode: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.WATER_BOX_MODE}) 103 water_box_carriage_status: int | None = field(default=None, metadata={"feature": "is_support_water_mode"}) 104 mop_forbidden_enable: int | None = None 105 camera_status: int | None = None 106 is_exploring: int | None = None 107 home_sec_status: int | None = None 108 home_sec_enable_password: int | None = None 109 adbumper_status: list[int] | None = None 110 water_shortage_status: int | None = field(default=None, metadata={"feature": "is_support_water_mode"}) 111 dock_type: RoborockDockTypeCode | None = None 112 dust_collection_status: int | None = None 113 auto_dust_collection: int | None = None 114 avoid_count: int | None = None 115 mop_mode: int | None = None 116 debug_mode: int | None = None 117 collision_avoid_status: int | None = None 118 switch_map_mode: int | None = None 119 dock_error_status: RoborockDockErrorCode | None = field(default=None, metadata={"dock_feature": "has_dock"}) 120 121 charge_status: RoborockChargeStatus | None = field( 122 default=None, metadata={"dps": RoborockDataProtocol.CHARGE_STATUS} 123 ) 124 unsave_map_reason: int | None = None 125 unsave_map_flag: int | None = None 126 wash_status: int | None = None 127 distance_off: int | None = None 128 in_warmup: int | None = None 129 dry_status: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.DRYING_STATUS}) 130 rdt: int | None = field(default=None, metadata={"feature": "is_supported_drying"}) 131 clean_percent: int | None = field(default=None, metadata={"feature": "is_support_clean_estimate"}) 132 rss: int | None = None 133 dss: int | None = None 134 common_status: int | None = None 135 corner_clean_mode: int | None = None 136 last_clean_t: int | None = None 137 replenish_mode: int | None = None 138 repeat: int | None = None 139 kct: int | None = None 140 subdivision_sets: int | None = None 141 142 @property 143 def square_meter_clean_area(self) -> float | None: 144 return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None 145 146 @property 147 def error_code_name(self) -> str | None: 148 return self.error_code.display_name if self.error_code is not None else None 149 150 @property 151 def state_name(self) -> str | None: 152 return self.state.display_name if self.state is not None else None 153 154 @property 155 def current_map(self) -> int | None: 156 """Returns the current map ID if the map is present.""" 157 if self.map_status is not None: 158 map_flag = self.map_status >> 2 159 if map_flag != NO_MAP: 160 return map_flag 161 return None 162 163 @property 164 def has_am(self) -> bool | None: 165 if self.dss is None: 166 return None 167 return (self.dss & 3) == 2 168 169 @property 170 @field_metadata(dock_feature="is_washable") 171 def clear_water_box_status(self) -> ClearWaterBoxStatus | None: 172 if self.dss: 173 return ClearWaterBoxStatus((self.dss >> 2) & 3) 174 return None 175 176 @property 177 @field_metadata(dock_feature="is_washable") 178 def dirty_water_box_status(self) -> DirtyWaterBoxStatus | None: 179 if self.dss: 180 return DirtyWaterBoxStatus((self.dss >> 4) & 3) 181 return None 182 183 @property 184 def dust_bag_status(self) -> DustBagStatus | None: 185 if self.dss: 186 return DustBagStatus((self.dss >> 6) & 3) 187 return None 188 189 @property 190 def water_box_filter_status(self) -> int | None: 191 if self.dss: 192 return (self.dss >> 8) & 3 193 return None 194 195 @property 196 @field_metadata( 197 dock_feature="is_clean_fluid_auto_delivery_supported", 198 ) 199 def clean_fluid_status(self) -> CleanFluidStatus | None: 200 if self.dss: 201 value = (self.dss >> 10) & 3 202 if value == 0: 203 return None # Feature not supported by this device 204 return CleanFluidStatus(value) 205 return None 206 207 @property 208 def hatch_door_status(self) -> int | None: 209 if self.dss: 210 return (self.dss >> 12) & 7 211 return None 212 213 @property 214 def dock_cool_fan_status(self) -> int | None: 215 if self.dss: 216 return (self.dss >> 15) & 3 217 return None 218 219 @property 220 def dock_state(self) -> RoborockDockState: 221 """A synthesized, high-level dock state reflecting the UI's display. 222 223 This property simplifies integration by handling the complex logic 224 of checking state, charge_status, and battery level simultaneously. It handles 225 newer off-peak charging logic seamlessly while maintaining backwards compatibility 226 with older devices. 227 """ 228 if self.state is None or self.state == RoborockStateCode.unknown: 229 return RoborockDockState.unknown 230 231 # 6. DUSTING 232 if self.state == RoborockStateCode.emptying_the_bin: 233 return RoborockDockState.dusting 234 235 # 5. FULL 236 if self.state == RoborockStateCode.charging_complete or ( 237 self.state == RoborockStateCode.charging and self.battery == 100 238 ): 239 return RoborockDockState.full 240 241 # 3 & 4. CHARGING and CHARGE_WAITING 242 if self.state == RoborockStateCode.charging: 243 if self.charge_status == RoborockChargeStatus.charge_waiting: 244 return RoborockDockState.off_peak_waiting 245 return RoborockDockState.charging 246 247 # 2. RECHARGING 248 if self.state in (RoborockStateCode.returning_home, RoborockStateCode.docking): 249 return RoborockDockState.returning 250 251 # 1. IDLE (Not on dock, or doing something else) 252 return RoborockDockState.idle 253 254 def __repr__(self) -> str: 255 return _attr_repr(self)
The result of a GET_STATUS API request.
154 @property 155 def current_map(self) -> int | None: 156 """Returns the current map ID if the map is present.""" 157 if self.map_status is not None: 158 map_flag = self.map_status >> 2 159 if map_flag != NO_MAP: 160 return map_flag 161 return None
Returns the current map ID if the map is present.
195 @property 196 @field_metadata( 197 dock_feature="is_clean_fluid_auto_delivery_supported", 198 ) 199 def clean_fluid_status(self) -> CleanFluidStatus | None: 200 if self.dss: 201 value = (self.dss >> 10) & 3 202 if value == 0: 203 return None # Feature not supported by this device 204 return CleanFluidStatus(value) 205 return None
219 @property 220 def dock_state(self) -> RoborockDockState: 221 """A synthesized, high-level dock state reflecting the UI's display. 222 223 This property simplifies integration by handling the complex logic 224 of checking state, charge_status, and battery level simultaneously. It handles 225 newer off-peak charging logic seamlessly while maintaining backwards compatibility 226 with older devices. 227 """ 228 if self.state is None or self.state == RoborockStateCode.unknown: 229 return RoborockDockState.unknown 230 231 # 6. DUSTING 232 if self.state == RoborockStateCode.emptying_the_bin: 233 return RoborockDockState.dusting 234 235 # 5. FULL 236 if self.state == RoborockStateCode.charging_complete or ( 237 self.state == RoborockStateCode.charging and self.battery == 100 238 ): 239 return RoborockDockState.full 240 241 # 3 & 4. CHARGING and CHARGE_WAITING 242 if self.state == RoborockStateCode.charging: 243 if self.charge_status == RoborockChargeStatus.charge_waiting: 244 return RoborockDockState.off_peak_waiting 245 return RoborockDockState.charging 246 247 # 2. RECHARGING 248 if self.state in (RoborockStateCode.returning_home, RoborockStateCode.docking): 249 return RoborockDockState.returning 250 251 # 1. IDLE (Not on dock, or doing something else) 252 return RoborockDockState.idle
A synthesized, high-level dock state reflecting the UI's display.
This property simplifies integration by handling the complex logic of checking state, charge_status, and battery level simultaneously. It handles newer off-peak charging logic seamlessly while maintaining backwards compatibility with older devices.
Inherited Members
DnDTimer
ValleyElectricityTimer
268@dataclass 269class CleanSummary(RoborockBase): 270 clean_time: int | None = None 271 clean_area: int | None = None 272 clean_count: int | None = None 273 dust_collection_count: int | None = None 274 records: list[int] | None = None 275 last_clean_t: int | None = None 276 277 @property 278 def square_meter_clean_area(self) -> float | None: 279 """Returns the clean area in square meters.""" 280 if isinstance(self.clean_area, list | str): 281 _LOGGER.warning(f"Clean area is a unexpected type! Please give the following in a issue: {self.clean_area}") 282 return None 283 return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None 284 285 def __repr__(self) -> str: 286 """Return a string representation of the object including all attributes.""" 287 return _attr_repr(self)
277 @property 278 def square_meter_clean_area(self) -> float | None: 279 """Returns the clean area in square meters.""" 280 if isinstance(self.clean_area, list | str): 281 _LOGGER.warning(f"Clean area is a unexpected type! Please give the following in a issue: {self.clean_area}") 282 return None 283 return round(self.clean_area / 1000000, 1) if self.clean_area is not None else None
Returns the clean area in square meters.
Inherited Members
290@dataclass 291class CleanRecord(RoborockBase): 292 begin: int | None = None 293 end: int | None = None 294 duration: int | None = None 295 area: int | None = None 296 error: int | None = None 297 complete: int | None = None 298 start_type: RoborockStartType | None = None 299 clean_type: RoborockCleanType | None = None 300 finish_reason: RoborockFinishReason | None = None 301 dust_collection_status: int | None = None 302 avoid_count: int | None = None 303 wash_count: int | None = None 304 map_flag: int | None = None 305 306 @property 307 def square_meter_area(self) -> float | None: 308 return round(self.area / 1000000, 1) if self.area is not None else None 309 310 @property 311 def begin_datetime(self) -> datetime.datetime | None: 312 return datetime.datetime.fromtimestamp(self.begin).astimezone(datetime.UTC) if self.begin else None 313 314 @property 315 def end_datetime(self) -> datetime.datetime | None: 316 return datetime.datetime.fromtimestamp(self.end).astimezone(datetime.UTC) if self.end else None 317 318 def __repr__(self) -> str: 319 return _attr_repr(self)
Inherited Members
322class CleanSummaryWithDetail(CleanSummary): 323 """CleanSummary with the last CleanRecord included.""" 324 325 last_clean_record: CleanRecord | None = None
CleanSummary with the last CleanRecord included.
328class ConsumableField(FieldNameBase): 329 """An enum that represents a field in the `Consumable` class. 330 331 This is used with `roborock.devices.traits.v1.status.DeviceFeaturesTrait` 332 to understand if a feature is supported by the device using `is_field_supported`. 333 334 The enum values are names of fields in the `Consumable` class. Each field is 335 annotated with `dps` metadata to map the field to a `RoborockDataProtocol` 336 value used to check support against the product schema. 337 """ 338 339 MAIN_BRUSH_WORK_TIME = "main_brush_work_time" 340 SIDE_BRUSH_WORK_TIME = "side_brush_work_time" 341 FILTER_WORK_TIME = "filter_work_time"
An enum that represents a field in the Consumable class.
This is used with roborock.devices.traits.v1.status.DeviceFeaturesTrait
to understand if a feature is supported by the device using is_field_supported.
The enum values are names of fields in the Consumable class. Each field is
annotated with dps metadata to map the field to a RoborockDataProtocol
value used to check support against the product schema.
344@dataclass 345class Consumable(RoborockBase): 346 main_brush_work_time: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.MAIN_BRUSH_WORK_TIME}) 347 side_brush_work_time: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.SIDE_BRUSH_WORK_TIME}) 348 filter_work_time: int | None = field(default=None, metadata={"dps": RoborockDataProtocol.FILTER_WORK_TIME}) 349 filter_element_work_time: int | None = None 350 sensor_dirty_time: int | None = None 351 strainer_work_times: int | None = None 352 dust_collection_work_times: int | None = None 353 cleaning_brush_work_times: int | None = None 354 moproller_work_time: int | None = None 355 356 @property 357 def main_brush_time_left(self) -> int | None: 358 return MAIN_BRUSH_REPLACE_TIME - self.main_brush_work_time if self.main_brush_work_time is not None else None 359 360 @property 361 def side_brush_time_left(self) -> int | None: 362 return SIDE_BRUSH_REPLACE_TIME - self.side_brush_work_time if self.side_brush_work_time is not None else None 363 364 @property 365 def filter_time_left(self) -> int | None: 366 return FILTER_REPLACE_TIME - self.filter_work_time if self.filter_work_time is not None else None 367 368 @property 369 def sensor_time_left(self) -> int | None: 370 return SENSOR_DIRTY_REPLACE_TIME - self.sensor_dirty_time if self.sensor_dirty_time is not None else None 371 372 @property 373 def strainer_time_left(self) -> int | None: 374 return STRAINER_REPLACE_TIME - self.strainer_work_times if self.strainer_work_times is not None else None 375 376 @property 377 def dust_collection_time_left(self) -> int | None: 378 return ( 379 DUST_COLLECTION_REPLACE_TIME - self.dust_collection_work_times 380 if self.dust_collection_work_times is not None 381 else None 382 ) 383 384 @property 385 def cleaning_brush_time_left(self) -> int | None: 386 return ( 387 CLEANING_BRUSH_REPLACE_TIME - self.cleaning_brush_work_times 388 if self.cleaning_brush_work_times is not None 389 else None 390 ) 391 392 @property 393 def mop_roller_time_left(self) -> int | None: 394 return MOP_ROLLER_REPLACE_TIME - self.moproller_work_time if self.moproller_work_time is not None else None 395 396 def __repr__(self) -> str: 397 return _attr_repr(self)
Inherited Members
400@dataclass 401class MultiMapsListRoom(RoborockBase): 402 id: int | None = None 403 tag: int | None = None 404 iot_name_id: str | None = None 405 iot_name: str | None = None 406 407 @property 408 def named_room_mapping(self) -> NamedRoomMapping | None: 409 """Returns a NamedRoomMapping object if valid.""" 410 if self.id is None or self.iot_name_id is None: 411 return None 412 return NamedRoomMapping( 413 segment_id=self.id, 414 iot_id=self.iot_name_id, 415 raw_name=self.iot_name, 416 )
407 @property 408 def named_room_mapping(self) -> NamedRoomMapping | None: 409 """Returns a NamedRoomMapping object if valid.""" 410 if self.id is None or self.iot_name_id is None: 411 return None 412 return NamedRoomMapping( 413 segment_id=self.id, 414 iot_id=self.iot_name_id, 415 raw_name=self.iot_name, 416 )
Returns a NamedRoomMapping object if valid.
Inherited Members
419@dataclass 420class MultiMapsListMapInfoBakMaps(RoborockBase): 421 mapflag: Any | None = None 422 add_time: Any | None = None
Inherited Members
425@dataclass 426class MultiMapsListMapInfo(RoborockBase): 427 map_flag: int 428 name: str 429 add_time: Any | None = None 430 length: Any | None = None 431 bak_maps: list[MultiMapsListMapInfoBakMaps] | None = None 432 rooms: list[MultiMapsListRoom] | None = None 433 434 @property 435 def mapFlag(self) -> int: 436 """Alias for map_flag, returns the map flag as an integer.""" 437 return self.map_flag 438 439 @property 440 def rooms_map(self) -> dict[int, NamedRoomMapping]: 441 """Returns a dictionary of room mappings by segment id.""" 442 return { 443 room.id: mapping 444 for room in self.rooms or () 445 if room.id is not None and (mapping := room.named_room_mapping) is not None 446 }
434 @property 435 def mapFlag(self) -> int: 436 """Alias for map_flag, returns the map flag as an integer.""" 437 return self.map_flag
Alias for map_flag, returns the map flag as an integer.
439 @property 440 def rooms_map(self) -> dict[int, NamedRoomMapping]: 441 """Returns a dictionary of room mappings by segment id.""" 442 return { 443 room.id: mapping 444 for room in self.rooms or () 445 if room.id is not None and (mapping := room.named_room_mapping) is not None 446 }
Returns a dictionary of room mappings by segment id.
Inherited Members
449@dataclass 450class MultiMapsList(RoborockBase): 451 max_multi_map: int | None = None 452 max_bak_map: int | None = None 453 multi_map_count: int | None = None 454 map_info: list[MultiMapsListMapInfo] | None = None
Inherited Members
457@dataclass 458class SmartWashParams(RoborockBase): 459 smart_wash: int | None = None 460 wash_interval: int | None = None
Inherited Members
463@dataclass 464class DustCollectionMode(RoborockBase): 465 mode: RoborockDockDustCollectionModeCode | None = None
Inherited Members
Inherited Members
473@dataclass 474class NetworkInfo(RoborockBase): 475 ip: str 476 ssid: str | None = None 477 mac: str | None = None 478 bssid: str | None = None 479 rssi: int | None = None
Inherited Members
482@dataclass 483class AppInitStatusLocalInfo(RoborockBase): 484 location: str 485 bom: str | None = None 486 featureset: int | None = None 487 language: str | None = None 488 logserver: str | None = None 489 wifiplan: str | None = None 490 timezone: str | None = None 491 name: str | None = None
Inherited Members
494@dataclass 495class AppInitStatus(RoborockBase): 496 local_info: AppInitStatusLocalInfo 497 feature_info: list[int] 498 new_feature_info: int = 0 499 new_feature_info_str: str = "" 500 new_feature_info_2: int | None = None 501 carriage_type: int | None = None 502 dsp_version: str | None = None