roborock.data.b01_q10.b01_q10_containers

Data container classes for Q10 B01 devices.

Many of these classes use the field(metadata={"dps": ...}) convention to map dataclass fields to device Data Points (DPS). This metadata is utilized by the UpdatableTrait helper in roborock.devices.traits.b01.q10.common to automatically update objects from raw device responses.

  1"""Data container classes for Q10 B01 devices.
  2
  3Many of these classes use the `field(metadata={"dps": ...})` convention to map
  4dataclass fields to device Data Points (DPS). This metadata is utilized by the
  5`UpdatableTrait` helper in `roborock.devices.traits.b01.q10.common` to
  6automatically update objects from raw device responses.
  7"""
  8
  9import datetime
 10from dataclasses import dataclass, field
 11
 12from ..containers import RoborockBase
 13from .b01_q10_code_mappings import (
 14    B01_Q10_DP,
 15    YXAreaUnit,
 16    YXBackType,
 17    YXCarpetCleanType,
 18    YXCleaningResult,
 19    YXCleanLine,
 20    YXCleanScope,
 21    YXCleanType,
 22    YXDeviceCleanTask,
 23    YXDeviceDustCollectionFrequency,
 24    YXDeviceState,
 25    YXFanLevel,
 26    YXFault,
 27    YXStartMethod,
 28    YXWaterLevel,
 29)
 30
 31
 32@dataclass
 33class dpCleanRecord(RoborockBase):
 34    op: str
 35    result: int
 36    id: str
 37    data: list
 38
 39
 40@dataclass
 41class Q10CleanRecord(RoborockBase):
 42    """A single Q10 (ss07) clean record decoded from a ``dpCleanRecord`` (DP 52) entry.
 43
 44    The device returns each record as a 12-field underscore-delimited string in the
 45    ``data`` list of a ``{"op": "list"}`` query (or the ``id`` of an ``{"op": "notify"}``
 46    push). The ``*_len`` values are internal blob-length metrics whose units aren't
 47    confirmed; the original ``raw`` string is always retained. The enum fields resolve
 48    an unmapped/unset code to ``None`` rather than guessing.
 49    """
 50
 51    raw: str
 52    record_id: str | None = None
 53    start_time: int | None = None
 54    """Clean start time, Unix seconds."""
 55    clean_time: int | None = None
 56    """Cleaning time, minutes."""
 57    clean_area: int | None = None
 58    """Cleaned area in square meters."""
 59    map_len: int | None = None
 60    """Length of the saved map blob for this record (0 = none stored)."""
 61    path_len: int | None = None
 62    """Length of the saved path blob for this record (0 = none stored)."""
 63    virtual_len: int | None = None
 64    """Length of the saved virtual-restriction blob for this record (0 = none stored)."""
 65    clean_mode: YXCleanScope | None = None
 66    """Clean scope/type (full / selective-room / zone / spot). Same axis as the live
 67    :class:`YXDeviceCleanTask` but a different record encoding -- see :class:`YXCleanScope`."""
 68    work_mode: YXCleanType | None = None
 69    """Actual work performed (vac+mop / vacuum / mop) -- the same enum :class:`Q10Status`
 70    uses for the live clean-mode DP. Records only ever carry 1/2/3 here."""
 71    cleaning_result: YXCleaningResult | None = None
 72    """How the clean ended: 0 interrupted (fault), 1 completed, 2 stopped (no fault)."""
 73    start_method: YXStartMethod | None = None
 74    """What initiated the clean: 0 remote, 1 app, 2 timer, 3 button."""
 75    collect_dust_count: int | None = None
 76    """Number of dock auto-empties during the clean."""
 77
 78    @property
 79    def start_datetime(self) -> datetime.datetime | None:
 80        """The start time as a timezone-aware (UTC) datetime."""
 81        if self.start_time is not None:
 82            return datetime.datetime.fromtimestamp(self.start_time).astimezone(datetime.UTC)
 83        return None
 84
 85
 86@dataclass
 87class dpMultiMap(RoborockBase):
 88    op: str
 89    result: int
 90    data: list
 91
 92
 93@dataclass
 94class dpGetCarpet(RoborockBase):
 95    op: str
 96    result: int
 97    data: str
 98
 99
100@dataclass
101class dpSelfIdentifyingCarpet(RoborockBase):
102    op: str
103    result: int
104    data: str
105
106
107@dataclass
108class dpNetInfo(RoborockBase):
109    wifi_name: str | None = None
110    # "ip_adress" intentionally mirrors the device's "ipAdress" key (sic).
111    ip_adress: str | None = None
112    mac: str | None = None
113    signal: int | None = None
114
115    @property
116    def ip_address(self) -> str | None:
117        """Correctly-spelled alias for :attr:`ip_adress`."""
118        return self.ip_adress
119
120
121@dataclass
122class dpNotDisturbExpand(RoborockBase):
123    disturb_dust_enable: int | None = None
124    disturb_light: int | None = None
125    disturb_resume_clean: int | None = None
126    disturb_voice: int | None = None
127
128
129@dataclass
130class dpCurrentCleanRoomIds(RoborockBase):
131    room_id_list: list
132
133
134@dataclass
135class dpVoiceVersion(RoborockBase):
136    version: int
137
138
139@dataclass
140class dpTimeZone(RoborockBase):
141    time_zone_city: str | None = None
142    time_zone_sec: int | None = None
143
144
145@dataclass
146class Q10Status(RoborockBase):
147    """Core vacuum status for Q10 devices.
148
149    Fields are mapped to DPS values using metadata. Objects of this class can be
150    automatically updated using the `UpdatableTrait` helper. Settings that have
151    their own trait (volume, child lock, do-not-disturb, dust collection,
152    network info, consumables) live on those traits instead of here.
153    """
154
155    clean_time: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_TIME})
156    clean_area: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_AREA})
157    battery: int | None = field(default=None, metadata={"dps": B01_Q10_DP.BATTERY})
158    status: YXDeviceState | None = field(default=None, metadata={"dps": B01_Q10_DP.STATUS})
159    fan_level: YXFanLevel | None = field(default=None, metadata={"dps": B01_Q10_DP.FAN_LEVEL})
160    water_level: YXWaterLevel | None = field(default=None, metadata={"dps": B01_Q10_DP.WATER_LEVEL})
161    clean_count: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_COUNT})
162    total_clean_area: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_AREA})
163    total_clean_count: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_COUNT})
164    total_clean_time: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_TIME})
165    clean_mode: YXCleanType | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_MODE})
166    clean_task_type: YXDeviceCleanTask | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_TASK_TYPE})
167    back_type: YXBackType | None = field(default=None, metadata={"dps": B01_Q10_DP.BACK_TYPE})
168    cleaning_progress: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_PROGRESS})
169    fault: YXFault | None = field(default=None, metadata={"dps": B01_Q10_DP.FAULT})
170
171    # Additional state reported in the device's full status dump.
172    clean_line: YXCleanLine | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_LINE})
173    carpet_clean_type: YXCarpetCleanType | None = field(default=None, metadata={"dps": B01_Q10_DP.CARPET_CLEAN_TYPE})
174    area_unit: YXAreaUnit | None = field(default=None, metadata={"dps": B01_Q10_DP.AREA_UNIT})
175    auto_boost: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.AUTO_BOOST})
176    multi_map_switch: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.MULTI_MAP_SWITCH})
177    map_save_switch: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.MAP_SAVE_SWITCH})
178    recent_clean_record: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.RECENT_CLEAN_RECORD})
179    valley_point_charging: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.VALLEY_POINT_CHARGING})
180    line_laser_obstacle_avoidance: bool | None = field(
181        default=None, metadata={"dps": B01_Q10_DP.LINE_LASER_OBSTACLE_AVOIDANCE}
182    )
183    # Whether a mop module is attached, and whether "clean along floor direction" is on.
184    mop_state: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.MOP_STATE})
185    ground_clean: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.GROUND_CLEAN})
186    # True while an "add area" / re-clean (the app's draw-a-rectangle "re cleaning")
187    # request is in progress; pulses back to False once the robot has the area.
188    add_clean_state: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.ADD_CLEAN_STATE})
189    robot_country_code: str | None = field(default=None, metadata={"dps": B01_Q10_DP.ROBOT_COUNTRY_CODE})
190    time_zone: dpTimeZone | None = field(default=None, metadata={"dps": B01_Q10_DP.TIME_ZONE})
191
192    # TODO(#846): value mappings for these ints are not yet decoded (no app
193    # control found / internal / constant); keep as int until reverse-engineered.
194    breakpoint_clean: int | None = field(default=None, metadata={"dps": B01_Q10_DP.BREAKPOINT_CLEAN})
195    timer_type: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TIMER_TYPE})
196    user_plan: int | None = field(default=None, metadata={"dps": B01_Q10_DP.USER_PLAN})
197    robot_type: int | None = field(default=None, metadata={"dps": B01_Q10_DP.ROBOT_TYPE})
198
199    # DEPRECATED: consumable/accessory remaining-life now lives on the
200    # ``Q10Consumable`` trait. These aliases are kept here for backwards
201    # compatibility and will be removed in a follow-up release. See PR #846.
202    main_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.MAIN_BRUSH_LIFE})
203    side_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SIDE_BRUSH_LIFE})
204    filter_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.FILTER_LIFE})
205    sensor_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SENSOR_LIFE})
206
207    @property
208    def fault_name(self) -> str | None:
209        """Returns the name of the current fault."""
210        return self.fault.value if self.fault is not None else None
211
212
213@dataclass
214class SoundVolume(RoborockBase):
215    """Speaker volume read-model (0-100)."""
216
217    volume: int | None = field(default=None, metadata={"dps": B01_Q10_DP.VOLUME})
218
219
220@dataclass
221class ChildLock(RoborockBase):
222    """Child-lock read-model."""
223
224    child_lock: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.CHILD_LOCK})
225
226
227@dataclass
228class DoNotDisturb(RoborockBase):
229    """Do Not Disturb read-model."""
230
231    not_disturb: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.NOT_DISTURB})
232    not_disturb_expand: dpNotDisturbExpand | None = field(default=None, metadata={"dps": B01_Q10_DP.NOT_DISTURB_EXPAND})
233
234
235@dataclass
236class DustCollection(RoborockBase):
237    """Dock auto-empty (dust collection) read-model."""
238
239    dust_switch: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.DUST_SWITCH})
240    dust_setting: YXDeviceDustCollectionFrequency | None = field(
241        default=None, metadata={"dps": B01_Q10_DP.DUST_SETTING}
242    )
243
244
245@dataclass
246class Q10Consumable(RoborockBase):
247    """Consumable / accessory remaining-life read-model.
248
249    Named with a ``Q10`` prefix to avoid shadowing the v1 ``Consumable`` when both
250    are star-imported into the ``roborock.data`` namespace.
251    """
252
253    main_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.MAIN_BRUSH_LIFE})
254    side_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SIDE_BRUSH_LIFE})
255    filter_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.FILTER_LIFE})
256    sensor_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SENSOR_LIFE})
257
258
259@dataclass
260class Q10NetworkInfo(RoborockBase):
261    """Network information read-model.
262
263    Named with a ``Q10`` prefix to avoid shadowing the v1 ``NetworkInfo`` when both
264    are star-imported into the ``roborock.data`` namespace.
265    """
266
267    net_info: dpNetInfo | None = field(default=None, metadata={"dps": B01_Q10_DP.NET_INFO})
@dataclass
class dpCleanRecord(roborock.data.containers.RoborockBase):
33@dataclass
34class dpCleanRecord(RoborockBase):
35    op: str
36    result: int
37    id: str
38    data: list
dpCleanRecord(op: str, result: int, id: str, data: list)
op: str
result: int
id: str
data: list
@dataclass
class Q10CleanRecord(roborock.data.containers.RoborockBase):
41@dataclass
42class Q10CleanRecord(RoborockBase):
43    """A single Q10 (ss07) clean record decoded from a ``dpCleanRecord`` (DP 52) entry.
44
45    The device returns each record as a 12-field underscore-delimited string in the
46    ``data`` list of a ``{"op": "list"}`` query (or the ``id`` of an ``{"op": "notify"}``
47    push). The ``*_len`` values are internal blob-length metrics whose units aren't
48    confirmed; the original ``raw`` string is always retained. The enum fields resolve
49    an unmapped/unset code to ``None`` rather than guessing.
50    """
51
52    raw: str
53    record_id: str | None = None
54    start_time: int | None = None
55    """Clean start time, Unix seconds."""
56    clean_time: int | None = None
57    """Cleaning time, minutes."""
58    clean_area: int | None = None
59    """Cleaned area in square meters."""
60    map_len: int | None = None
61    """Length of the saved map blob for this record (0 = none stored)."""
62    path_len: int | None = None
63    """Length of the saved path blob for this record (0 = none stored)."""
64    virtual_len: int | None = None
65    """Length of the saved virtual-restriction blob for this record (0 = none stored)."""
66    clean_mode: YXCleanScope | None = None
67    """Clean scope/type (full / selective-room / zone / spot). Same axis as the live
68    :class:`YXDeviceCleanTask` but a different record encoding -- see :class:`YXCleanScope`."""
69    work_mode: YXCleanType | None = None
70    """Actual work performed (vac+mop / vacuum / mop) -- the same enum :class:`Q10Status`
71    uses for the live clean-mode DP. Records only ever carry 1/2/3 here."""
72    cleaning_result: YXCleaningResult | None = None
73    """How the clean ended: 0 interrupted (fault), 1 completed, 2 stopped (no fault)."""
74    start_method: YXStartMethod | None = None
75    """What initiated the clean: 0 remote, 1 app, 2 timer, 3 button."""
76    collect_dust_count: int | None = None
77    """Number of dock auto-empties during the clean."""
78
79    @property
80    def start_datetime(self) -> datetime.datetime | None:
81        """The start time as a timezone-aware (UTC) datetime."""
82        if self.start_time is not None:
83            return datetime.datetime.fromtimestamp(self.start_time).astimezone(datetime.UTC)
84        return None

A single Q10 (ss07) clean record decoded from a dpCleanRecord (DP 52) entry.

The device returns each record as a 12-field underscore-delimited string in the data list of a {"op": "list"} query (or the id of an {"op": "notify"} push). The *_len values are internal blob-length metrics whose units aren't confirmed; the original raw string is always retained. The enum fields resolve an unmapped/unset code to None rather than guessing.

Q10CleanRecord( raw: str, record_id: str | None = None, start_time: int | None = None, clean_time: int | None = None, clean_area: int | None = None, map_len: int | None = None, path_len: int | None = None, virtual_len: int | None = None, clean_mode: roborock.data.b01_q10.b01_q10_code_mappings.YXCleanScope | None = None, work_mode: roborock.data.b01_q10.b01_q10_code_mappings.YXCleanType | None = None, cleaning_result: roborock.data.b01_q10.b01_q10_code_mappings.YXCleaningResult | None = None, start_method: roborock.data.b01_q10.b01_q10_code_mappings.YXStartMethod | None = None, collect_dust_count: int | None = None)
raw: str
record_id: str | None = None
start_time: int | None = None

Clean start time, Unix seconds.

clean_time: int | None = None

Cleaning time, minutes.

clean_area: int | None = None

Cleaned area in square meters.

map_len: int | None = None

Length of the saved map blob for this record (0 = none stored).

path_len: int | None = None

Length of the saved path blob for this record (0 = none stored).

virtual_len: int | None = None

Length of the saved virtual-restriction blob for this record (0 = none stored).

Clean scope/type (full / selective-room / zone / spot). Same axis as the live YXDeviceCleanTask but a different record encoding -- see YXCleanScope.

Actual work performed (vac+mop / vacuum / mop) -- the same enum Q10Status uses for the live clean-mode DP. Records only ever carry 1/2/3 here.

How the clean ended: 0 interrupted (fault), 1 completed, 2 stopped (no fault).

What initiated the clean: 0 remote, 1 app, 2 timer, 3 button.

collect_dust_count: int | None = None

Number of dock auto-empties during the clean.

start_datetime: datetime.datetime | None
79    @property
80    def start_datetime(self) -> datetime.datetime | None:
81        """The start time as a timezone-aware (UTC) datetime."""
82        if self.start_time is not None:
83            return datetime.datetime.fromtimestamp(self.start_time).astimezone(datetime.UTC)
84        return None

The start time as a timezone-aware (UTC) datetime.

@dataclass
class dpMultiMap(roborock.data.containers.RoborockBase):
87@dataclass
88class dpMultiMap(RoborockBase):
89    op: str
90    result: int
91    data: list
dpMultiMap(op: str, result: int, data: list)
op: str
result: int
data: list
@dataclass
class dpGetCarpet(roborock.data.containers.RoborockBase):
94@dataclass
95class dpGetCarpet(RoborockBase):
96    op: str
97    result: int
98    data: str
dpGetCarpet(op: str, result: int, data: str)
op: str
result: int
data: str
@dataclass
class dpSelfIdentifyingCarpet(roborock.data.containers.RoborockBase):
101@dataclass
102class dpSelfIdentifyingCarpet(RoborockBase):
103    op: str
104    result: int
105    data: str
dpSelfIdentifyingCarpet(op: str, result: int, data: str)
op: str
result: int
data: str
@dataclass
class dpNetInfo(roborock.data.containers.RoborockBase):
108@dataclass
109class dpNetInfo(RoborockBase):
110    wifi_name: str | None = None
111    # "ip_adress" intentionally mirrors the device's "ipAdress" key (sic).
112    ip_adress: str | None = None
113    mac: str | None = None
114    signal: int | None = None
115
116    @property
117    def ip_address(self) -> str | None:
118        """Correctly-spelled alias for :attr:`ip_adress`."""
119        return self.ip_adress
dpNetInfo( wifi_name: str | None = None, ip_adress: str | None = None, mac: str | None = None, signal: int | None = None)
wifi_name: str | None = None
ip_adress: str | None = None
mac: str | None = None
signal: int | None = None
ip_address: str | None
116    @property
117    def ip_address(self) -> str | None:
118        """Correctly-spelled alias for :attr:`ip_adress`."""
119        return self.ip_adress

Correctly-spelled alias for ip_adress.

@dataclass
class dpNotDisturbExpand(roborock.data.containers.RoborockBase):
122@dataclass
123class dpNotDisturbExpand(RoborockBase):
124    disturb_dust_enable: int | None = None
125    disturb_light: int | None = None
126    disturb_resume_clean: int | None = None
127    disturb_voice: int | None = None
dpNotDisturbExpand( disturb_dust_enable: int | None = None, disturb_light: int | None = None, disturb_resume_clean: int | None = None, disturb_voice: int | None = None)
disturb_dust_enable: int | None = None
disturb_light: int | None = None
disturb_resume_clean: int | None = None
disturb_voice: int | None = None
@dataclass
class dpCurrentCleanRoomIds(roborock.data.containers.RoborockBase):
130@dataclass
131class dpCurrentCleanRoomIds(RoborockBase):
132    room_id_list: list
dpCurrentCleanRoomIds(room_id_list: list)
room_id_list: list
@dataclass
class dpVoiceVersion(roborock.data.containers.RoborockBase):
135@dataclass
136class dpVoiceVersion(RoborockBase):
137    version: int
dpVoiceVersion(version: int)
version: int
@dataclass
class dpTimeZone(roborock.data.containers.RoborockBase):
140@dataclass
141class dpTimeZone(RoborockBase):
142    time_zone_city: str | None = None
143    time_zone_sec: int | None = None
dpTimeZone(time_zone_city: str | None = None, time_zone_sec: int | None = None)
time_zone_city: str | None = None
time_zone_sec: int | None = None
@dataclass
class Q10Status(roborock.data.containers.RoborockBase):
146@dataclass
147class Q10Status(RoborockBase):
148    """Core vacuum status for Q10 devices.
149
150    Fields are mapped to DPS values using metadata. Objects of this class can be
151    automatically updated using the `UpdatableTrait` helper. Settings that have
152    their own trait (volume, child lock, do-not-disturb, dust collection,
153    network info, consumables) live on those traits instead of here.
154    """
155
156    clean_time: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_TIME})
157    clean_area: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_AREA})
158    battery: int | None = field(default=None, metadata={"dps": B01_Q10_DP.BATTERY})
159    status: YXDeviceState | None = field(default=None, metadata={"dps": B01_Q10_DP.STATUS})
160    fan_level: YXFanLevel | None = field(default=None, metadata={"dps": B01_Q10_DP.FAN_LEVEL})
161    water_level: YXWaterLevel | None = field(default=None, metadata={"dps": B01_Q10_DP.WATER_LEVEL})
162    clean_count: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_COUNT})
163    total_clean_area: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_AREA})
164    total_clean_count: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_COUNT})
165    total_clean_time: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TOTAL_CLEAN_TIME})
166    clean_mode: YXCleanType | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_MODE})
167    clean_task_type: YXDeviceCleanTask | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_TASK_TYPE})
168    back_type: YXBackType | None = field(default=None, metadata={"dps": B01_Q10_DP.BACK_TYPE})
169    cleaning_progress: int | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_PROGRESS})
170    fault: YXFault | None = field(default=None, metadata={"dps": B01_Q10_DP.FAULT})
171
172    # Additional state reported in the device's full status dump.
173    clean_line: YXCleanLine | None = field(default=None, metadata={"dps": B01_Q10_DP.CLEAN_LINE})
174    carpet_clean_type: YXCarpetCleanType | None = field(default=None, metadata={"dps": B01_Q10_DP.CARPET_CLEAN_TYPE})
175    area_unit: YXAreaUnit | None = field(default=None, metadata={"dps": B01_Q10_DP.AREA_UNIT})
176    auto_boost: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.AUTO_BOOST})
177    multi_map_switch: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.MULTI_MAP_SWITCH})
178    map_save_switch: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.MAP_SAVE_SWITCH})
179    recent_clean_record: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.RECENT_CLEAN_RECORD})
180    valley_point_charging: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.VALLEY_POINT_CHARGING})
181    line_laser_obstacle_avoidance: bool | None = field(
182        default=None, metadata={"dps": B01_Q10_DP.LINE_LASER_OBSTACLE_AVOIDANCE}
183    )
184    # Whether a mop module is attached, and whether "clean along floor direction" is on.
185    mop_state: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.MOP_STATE})
186    ground_clean: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.GROUND_CLEAN})
187    # True while an "add area" / re-clean (the app's draw-a-rectangle "re cleaning")
188    # request is in progress; pulses back to False once the robot has the area.
189    add_clean_state: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.ADD_CLEAN_STATE})
190    robot_country_code: str | None = field(default=None, metadata={"dps": B01_Q10_DP.ROBOT_COUNTRY_CODE})
191    time_zone: dpTimeZone | None = field(default=None, metadata={"dps": B01_Q10_DP.TIME_ZONE})
192
193    # TODO(#846): value mappings for these ints are not yet decoded (no app
194    # control found / internal / constant); keep as int until reverse-engineered.
195    breakpoint_clean: int | None = field(default=None, metadata={"dps": B01_Q10_DP.BREAKPOINT_CLEAN})
196    timer_type: int | None = field(default=None, metadata={"dps": B01_Q10_DP.TIMER_TYPE})
197    user_plan: int | None = field(default=None, metadata={"dps": B01_Q10_DP.USER_PLAN})
198    robot_type: int | None = field(default=None, metadata={"dps": B01_Q10_DP.ROBOT_TYPE})
199
200    # DEPRECATED: consumable/accessory remaining-life now lives on the
201    # ``Q10Consumable`` trait. These aliases are kept here for backwards
202    # compatibility and will be removed in a follow-up release. See PR #846.
203    main_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.MAIN_BRUSH_LIFE})
204    side_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SIDE_BRUSH_LIFE})
205    filter_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.FILTER_LIFE})
206    sensor_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SENSOR_LIFE})
207
208    @property
209    def fault_name(self) -> str | None:
210        """Returns the name of the current fault."""
211        return self.fault.value if self.fault is not None else None

Core vacuum status for Q10 devices.

Fields are mapped to DPS values using metadata. Objects of this class can be automatically updated using the UpdatableTrait helper. Settings that have their own trait (volume, child lock, do-not-disturb, dust collection, network info, consumables) live on those traits instead of here.

Q10Status( clean_time: int | None = None, clean_area: int | None = None, battery: int | None = None, status: roborock.data.b01_q10.b01_q10_code_mappings.YXDeviceState | None = None, fan_level: roborock.data.b01_q10.b01_q10_code_mappings.YXFanLevel | None = None, water_level: roborock.data.b01_q10.b01_q10_code_mappings.YXWaterLevel | None = None, clean_count: int | None = None, total_clean_area: int | None = None, total_clean_count: int | None = None, total_clean_time: int | None = None, clean_mode: roborock.data.b01_q10.b01_q10_code_mappings.YXCleanType | None = None, clean_task_type: roborock.data.b01_q10.b01_q10_code_mappings.YXDeviceCleanTask | None = None, back_type: roborock.data.b01_q10.b01_q10_code_mappings.YXBackType | None = None, cleaning_progress: int | None = None, fault: roborock.data.b01_q10.b01_q10_code_mappings.YXFault | None = None, clean_line: roborock.data.b01_q10.b01_q10_code_mappings.YXCleanLine | None = None, carpet_clean_type: roborock.data.b01_q10.b01_q10_code_mappings.YXCarpetCleanType | None = None, area_unit: roborock.data.b01_q10.b01_q10_code_mappings.YXAreaUnit | None = None, auto_boost: bool | None = None, multi_map_switch: bool | None = None, map_save_switch: bool | None = None, recent_clean_record: bool | None = None, valley_point_charging: bool | None = None, line_laser_obstacle_avoidance: bool | None = None, mop_state: bool | None = None, ground_clean: bool | None = None, add_clean_state: bool | None = None, robot_country_code: str | None = None, time_zone: dpTimeZone | None = None, breakpoint_clean: int | None = None, timer_type: int | None = None, user_plan: int | None = None, robot_type: int | None = None, main_brush_life: int | None = None, side_brush_life: int | None = None, filter_life: int | None = None, sensor_life: int | None = None)
clean_time: int | None = None
clean_area: int | None = None
battery: int | None = None
clean_count: int | None = None
total_clean_area: int | None = None
total_clean_count: int | None = None
total_clean_time: int | None = None
cleaning_progress: int | None = None
auto_boost: bool | None = None
multi_map_switch: bool | None = None
map_save_switch: bool | None = None
recent_clean_record: bool | None = None
valley_point_charging: bool | None = None
line_laser_obstacle_avoidance: bool | None = None
mop_state: bool | None = None
ground_clean: bool | None = None
add_clean_state: bool | None = None
robot_country_code: str | None = None
time_zone: dpTimeZone | None = None
breakpoint_clean: int | None = None
timer_type: int | None = None
user_plan: int | None = None
robot_type: int | None = None
main_brush_life: int | None = None
side_brush_life: int | None = None
filter_life: int | None = None
sensor_life: int | None = None
fault_name: str | None
208    @property
209    def fault_name(self) -> str | None:
210        """Returns the name of the current fault."""
211        return self.fault.value if self.fault is not None else None

Returns the name of the current fault.

@dataclass
class SoundVolume(roborock.data.containers.RoborockBase):
214@dataclass
215class SoundVolume(RoborockBase):
216    """Speaker volume read-model (0-100)."""
217
218    volume: int | None = field(default=None, metadata={"dps": B01_Q10_DP.VOLUME})

Speaker volume read-model (0-100).

SoundVolume(volume: int | None = None)
volume: int | None = None
@dataclass
class ChildLock(roborock.data.containers.RoborockBase):
221@dataclass
222class ChildLock(RoborockBase):
223    """Child-lock read-model."""
224
225    child_lock: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.CHILD_LOCK})

Child-lock read-model.

ChildLock(child_lock: bool | None = None)
child_lock: bool | None = None
@dataclass
class DoNotDisturb(roborock.data.containers.RoborockBase):
228@dataclass
229class DoNotDisturb(RoborockBase):
230    """Do Not Disturb read-model."""
231
232    not_disturb: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.NOT_DISTURB})
233    not_disturb_expand: dpNotDisturbExpand | None = field(default=None, metadata={"dps": B01_Q10_DP.NOT_DISTURB_EXPAND})

Do Not Disturb read-model.

DoNotDisturb( not_disturb: bool | None = None, not_disturb_expand: dpNotDisturbExpand | None = None)
not_disturb: bool | None = None
not_disturb_expand: dpNotDisturbExpand | None = None
@dataclass
class DustCollection(roborock.data.containers.RoborockBase):
236@dataclass
237class DustCollection(RoborockBase):
238    """Dock auto-empty (dust collection) read-model."""
239
240    dust_switch: bool | None = field(default=None, metadata={"dps": B01_Q10_DP.DUST_SWITCH})
241    dust_setting: YXDeviceDustCollectionFrequency | None = field(
242        default=None, metadata={"dps": B01_Q10_DP.DUST_SETTING}
243    )

Dock auto-empty (dust collection) read-model.

DustCollection( dust_switch: bool | None = None, dust_setting: roborock.data.b01_q10.b01_q10_code_mappings.YXDeviceDustCollectionFrequency | None = None)
dust_switch: bool | None = None
@dataclass
class Q10Consumable(roborock.data.containers.RoborockBase):
246@dataclass
247class Q10Consumable(RoborockBase):
248    """Consumable / accessory remaining-life read-model.
249
250    Named with a ``Q10`` prefix to avoid shadowing the v1 ``Consumable`` when both
251    are star-imported into the ``roborock.data`` namespace.
252    """
253
254    main_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.MAIN_BRUSH_LIFE})
255    side_brush_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SIDE_BRUSH_LIFE})
256    filter_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.FILTER_LIFE})
257    sensor_life: int | None = field(default=None, metadata={"dps": B01_Q10_DP.SENSOR_LIFE})

Consumable / accessory remaining-life read-model.

Named with a Q10 prefix to avoid shadowing the v1 Consumable when both are star-imported into the roborock.data namespace.

Q10Consumable( main_brush_life: int | None = None, side_brush_life: int | None = None, filter_life: int | None = None, sensor_life: int | None = None)
main_brush_life: int | None = None
side_brush_life: int | None = None
filter_life: int | None = None
sensor_life: int | None = None
@dataclass
class Q10NetworkInfo(roborock.data.containers.RoborockBase):
260@dataclass
261class Q10NetworkInfo(RoborockBase):
262    """Network information read-model.
263
264    Named with a ``Q10`` prefix to avoid shadowing the v1 ``NetworkInfo`` when both
265    are star-imported into the ``roborock.data`` namespace.
266    """
267
268    net_info: dpNetInfo | None = field(default=None, metadata={"dps": B01_Q10_DP.NET_INFO})

Network information read-model.

Named with a Q10 prefix to avoid shadowing the v1 NetworkInfo when both are star-imported into the roborock.data namespace.

Q10NetworkInfo( net_info: dpNetInfo | None = None)
net_info: dpNetInfo | None = None