roborock.data.b01_q7.b01_q7_containers
1import datetime 2import json 3from dataclasses import dataclass, field 4from functools import cached_property 5 6from ...exceptions import RoborockException 7from ..containers import RoborockBase 8from .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 21class 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 35class OrderTotal(RoborockBase): 36 """Represents the order total information.""" 37 38 total: int 39 enable: int 40 41 42@dataclass 43class 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 61class PvCharging(RoborockBase): 62 """Represents the photovoltaic charging status.""" 63 64 status: int 65 begin_time: int 66 end_time: int 67 68 69@dataclass 70class 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 79class 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 227class 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 260class 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 279class 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 296class 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
21@dataclass 22class NetStatus(RoborockBase): 23 """Represents the network status of the device.""" 24 25 rssi: str 26 loss: int 27 ping: int 28 ip: str 29 mac: str 30 ssid: str 31 frequency: int 32 bssid: str
Represents the network status of the device.
Inherited Members
35@dataclass 36class OrderTotal(RoborockBase): 37 """Represents the order total information.""" 38 39 total: int 40 enable: int
Represents the order total information.
Inherited Members
43@dataclass 44class Privacy(RoborockBase): 45 """Represents the privacy settings of the device.""" 46 47 ai_recognize: int 48 dirt_recognize: int 49 pet_recognize: int 50 carpet_turbo: int 51 carpet_avoid: int 52 carpet_show: int 53 map_uploads: int 54 ai_agent: int 55 ai_avoidance: int 56 record_uploads: int 57 along_floor: int 58 auto_upgrade: int
Represents the privacy settings of the device.
Inherited Members
61@dataclass 62class PvCharging(RoborockBase): 63 """Represents the photovoltaic charging status.""" 64 65 status: int 66 begin_time: int 67 end_time: int
Represents the photovoltaic charging status.
Inherited Members
70@dataclass 71class Recommend(RoborockBase): 72 """Represents cleaning recommendations.""" 73 74 sill: int 75 wall: int 76 room_id: list[int] = field(default_factory=list)
Represents cleaning recommendations.
Inherited Members
79@dataclass 80class B01Props(RoborockBase): 81 """ 82 Represents the complete properties and status for a Roborock B01 model. 83 This dataclass is generated based on the device's status JSON object. 84 """ 85 86 status: WorkStatusMapping | None = None 87 fault: B01Fault | None = None 88 wind: SCWindMapping | None = None 89 water: WaterLevelMapping | None = None 90 mode: CleanTypeMapping | None = None 91 quantity: int | None = None 92 alarm: int | None = None 93 volume: int | None = None 94 hypa: int | None = None 95 main_brush: int | None = None 96 side_brush: int | None = None 97 mop_life: int | None = None 98 main_sensor: int | None = None 99 net_status: NetStatus | None = None 100 repeat_state: CleanRepeatMapping | None = None 101 tank_state: int | None = None 102 sweep_type: int | None = None 103 clean_path_preference: CleanPathPreferenceMapping | None = None 104 cloth_state: int | None = None 105 time_zone: int | None = None 106 time_zone_info: str | None = None 107 language: int | None = None 108 cleaning_time: int | None = None 109 real_clean_time: int | None = None 110 cleaning_area: int | None = None 111 custom_type: int | None = None 112 sound: int | None = None 113 work_mode: WorkModeMapping | None = None 114 station_act: int | None = None 115 charge_state: int | None = None 116 current_map_id: int | None = None 117 map_num: int | None = None 118 dust_action: int | None = None 119 quiet_is_open: int | None = None 120 quiet_begin_time: int | None = None 121 quiet_end_time: int | None = None 122 clean_finish: int | None = None 123 voice_type: int | None = None 124 voice_type_version: int | None = None 125 order_total: OrderTotal | None = None 126 build_map: int | None = None 127 privacy: Privacy | None = None 128 dust_auto_state: int | None = None 129 dust_frequency: int | None = None 130 child_lock: int | None = None 131 multi_floor: int | None = None 132 map_save: int | None = None 133 light_mode: int | None = None 134 green_laser: int | None = None 135 dust_bag_used: int | None = None 136 order_save_mode: int | None = None 137 manufacturer: str | None = None 138 back_to_wash: int | None = None 139 charge_station_type: int | None = None 140 pv_cut_charge: int | None = None 141 pv_charging: PvCharging | None = None 142 serial_number: str | None = None 143 recommend: Recommend | None = None 144 add_sweep_status: int | None = None 145 146 @property 147 def main_brush_time_left(self) -> int | None: 148 """ 149 Returns estimated remaining life of the main brush in minutes. 150 Total life is 300 hours (18000 minutes). 151 """ 152 if self.main_brush is None: 153 return None 154 return max(0, 18000 - self.main_brush) 155 156 @property 157 def side_brush_time_left(self) -> int | None: 158 """ 159 Returns estimated remaining life of the side brush in minutes. 160 Total life is 200 hours (12000 minutes). 161 """ 162 if self.side_brush is None: 163 return None 164 return max(0, 12000 - self.side_brush) 165 166 @property 167 def filter_time_left(self) -> int | None: 168 """ 169 Returns estimated remaining life of the filter (hypa) in minutes. 170 Total life is 150 hours (9000 minutes). 171 """ 172 if self.hypa is None: 173 return None 174 return max(0, 9000 - self.hypa) 175 176 @property 177 def mop_life_time_left(self) -> int | None: 178 """ 179 Returns estimated remaining life of the mop in minutes. 180 Total life is 180 hours (10800 minutes). 181 """ 182 if self.mop_life is None: 183 return None 184 return max(0, 10800 - self.mop_life) 185 186 @property 187 def sensor_dirty_time_left(self) -> int | None: 188 """ 189 Returns estimated time until sensors need cleaning in minutes. 190 Maintenance interval is typically 30 hours (1800 minutes). 191 """ 192 if self.main_sensor is None: 193 return None 194 return max(0, 1800 - self.main_sensor) 195 196 @property 197 def status_name(self) -> str | None: 198 """Returns the name of the current status.""" 199 return self.status.value if self.status is not None else None 200 201 @property 202 def fault_name(self) -> str | None: 203 """Returns the name of the current fault.""" 204 return self.fault.value if self.fault is not None else None 205 206 @property 207 def wind_name(self) -> str | None: 208 """Returns the name of the current fan speed (wind).""" 209 return self.wind.value if self.wind is not None else None 210 211 @property 212 def work_mode_name(self) -> str | None: 213 """Returns the name of the current work mode.""" 214 return self.work_mode.value if self.work_mode is not None else None 215 216 @property 217 def repeat_state_name(self) -> str | None: 218 """Returns the name of the current repeat state.""" 219 return self.repeat_state.value if self.repeat_state is not None else None 220 221 @property 222 def clean_path_preference_name(self) -> str | None: 223 """Returns the name of the current clean path preference.""" 224 return self.clean_path_preference.value if self.clean_path_preference is not None else None
Represents the complete properties and status for a Roborock B01 model. This dataclass is generated based on the device's status JSON object.
146 @property 147 def main_brush_time_left(self) -> int | None: 148 """ 149 Returns estimated remaining life of the main brush in minutes. 150 Total life is 300 hours (18000 minutes). 151 """ 152 if self.main_brush is None: 153 return None 154 return max(0, 18000 - self.main_brush)
Returns estimated remaining life of the main brush in minutes. Total life is 300 hours (18000 minutes).
156 @property 157 def side_brush_time_left(self) -> int | None: 158 """ 159 Returns estimated remaining life of the side brush in minutes. 160 Total life is 200 hours (12000 minutes). 161 """ 162 if self.side_brush is None: 163 return None 164 return max(0, 12000 - self.side_brush)
Returns estimated remaining life of the side brush in minutes. Total life is 200 hours (12000 minutes).
166 @property 167 def filter_time_left(self) -> int | None: 168 """ 169 Returns estimated remaining life of the filter (hypa) in minutes. 170 Total life is 150 hours (9000 minutes). 171 """ 172 if self.hypa is None: 173 return None 174 return max(0, 9000 - self.hypa)
Returns estimated remaining life of the filter (hypa) in minutes. Total life is 150 hours (9000 minutes).
176 @property 177 def mop_life_time_left(self) -> int | None: 178 """ 179 Returns estimated remaining life of the mop in minutes. 180 Total life is 180 hours (10800 minutes). 181 """ 182 if self.mop_life is None: 183 return None 184 return max(0, 10800 - self.mop_life)
Returns estimated remaining life of the mop in minutes. Total life is 180 hours (10800 minutes).
186 @property 187 def sensor_dirty_time_left(self) -> int | None: 188 """ 189 Returns estimated time until sensors need cleaning in minutes. 190 Maintenance interval is typically 30 hours (1800 minutes). 191 """ 192 if self.main_sensor is None: 193 return None 194 return max(0, 1800 - self.main_sensor)
Returns estimated time until sensors need cleaning in minutes. Maintenance interval is typically 30 hours (1800 minutes).
196 @property 197 def status_name(self) -> str | None: 198 """Returns the name of the current status.""" 199 return self.status.value if self.status is not None else None
Returns the name of the current status.
201 @property 202 def fault_name(self) -> str | None: 203 """Returns the name of the current fault.""" 204 return self.fault.value if self.fault is not None else None
Returns the name of the current fault.
206 @property 207 def wind_name(self) -> str | None: 208 """Returns the name of the current fan speed (wind).""" 209 return self.wind.value if self.wind is not None else None
Returns the name of the current fan speed (wind).
211 @property 212 def work_mode_name(self) -> str | None: 213 """Returns the name of the current work mode.""" 214 return self.work_mode.value if self.work_mode is not None else None
Returns the name of the current work mode.
216 @property 217 def repeat_state_name(self) -> str | None: 218 """Returns the name of the current repeat state.""" 219 return self.repeat_state.value if self.repeat_state is not None else None
Returns the name of the current repeat state.
221 @property 222 def clean_path_preference_name(self) -> str | None: 223 """Returns the name of the current clean path preference.""" 224 return self.clean_path_preference.value if self.clean_path_preference is not None else None
Returns the name of the current clean path preference.
Inherited Members
227@dataclass 228class CleanRecordDetail(RoborockBase): 229 """Represents a single clean record detail (from `record_list[].detail`).""" 230 231 record_start_time: int | None = None 232 method: int | None = None 233 record_use_time: int | None = None 234 clean_count: int | None = None 235 # This is seemingly returned in meters (non-squared) 236 record_clean_area: int | None = None 237 record_clean_mode: int | None = None 238 record_clean_way: int | None = None 239 record_task_status: int | None = None 240 record_faultcode: int | None = None 241 record_dust_num: int | None = None 242 clean_current_map: int | None = None 243 record_map_url: str | None = None 244 245 @property 246 def start_datetime(self) -> datetime.datetime | None: 247 """Convert the start datetime into a datetime object.""" 248 if self.record_start_time is not None: 249 return datetime.datetime.fromtimestamp(self.record_start_time).astimezone(datetime.UTC) 250 return None 251 252 @property 253 def square_meters_area_cleaned(self) -> float | None: 254 """Returns the area cleaned in square meters.""" 255 if self.record_clean_area is not None: 256 return self.record_clean_area / 100 257 return None
Represents a single clean record detail (from record_list[].detail).
245 @property 246 def start_datetime(self) -> datetime.datetime | None: 247 """Convert the start datetime into a datetime object.""" 248 if self.record_start_time is not None: 249 return datetime.datetime.fromtimestamp(self.record_start_time).astimezone(datetime.UTC) 250 return None
Convert the start datetime into a datetime object.
252 @property 253 def square_meters_area_cleaned(self) -> float | None: 254 """Returns the area cleaned in square meters.""" 255 if self.record_clean_area is not None: 256 return self.record_clean_area / 100 257 return None
Returns the area cleaned in square meters.
Inherited Members
260@dataclass 261class CleanRecordListItem(RoborockBase): 262 """Represents an entry in the clean record list returned by `service.get_record_list`.""" 263 264 url: str | None = None 265 detail: str | None = None 266 267 @cached_property 268 def detail_parsed(self) -> CleanRecordDetail | None: 269 """Parse and return the detail as a CleanRecordDetail object.""" 270 if self.detail is None: 271 return None 272 try: 273 parsed = json.loads(self.detail) 274 except json.JSONDecodeError as ex: 275 raise RoborockException(f"Invalid B01 record detail JSON: {self.detail!r}") from ex 276 return CleanRecordDetail.from_dict(parsed)
Represents an entry in the clean record list returned by service.get_record_list.
267 @cached_property 268 def detail_parsed(self) -> CleanRecordDetail | None: 269 """Parse and return the detail as a CleanRecordDetail object.""" 270 if self.detail is None: 271 return None 272 try: 273 parsed = json.loads(self.detail) 274 except json.JSONDecodeError as ex: 275 raise RoborockException(f"Invalid B01 record detail JSON: {self.detail!r}") from ex 276 return CleanRecordDetail.from_dict(parsed)
Parse and return the detail as a CleanRecordDetail object.
Inherited Members
279@dataclass 280class CleanRecordList(RoborockBase): 281 """Represents the clean record list response from `service.get_record_list`.""" 282 283 total_area: int | None = None 284 total_time: int | None = None # stored in seconds 285 total_count: int | None = None 286 record_list: list[CleanRecordListItem] = field(default_factory=list) 287 288 @property 289 def square_meters_area_cleaned(self) -> float | None: 290 """Returns the area cleaned in square meters.""" 291 if self.total_area is not None: 292 return self.total_area / 100 293 return None
Represents the clean record list response from service.get_record_list.
288 @property 289 def square_meters_area_cleaned(self) -> float | None: 290 """Returns the area cleaned in square meters.""" 291 if self.total_area is not None: 292 return self.total_area / 100 293 return None
Returns the area cleaned in square meters.
Inherited Members
296@dataclass 297class CleanRecordSummary(RoborockBase): 298 """Represents clean record totals for B01/Q7 devices.""" 299 300 total_time: int | None = None 301 total_area: int | None = None 302 total_count: int | None = None 303 last_record_detail: CleanRecordDetail | None = None
Represents clean record totals for B01/Q7 devices.