1 """Support for Roborock sensors."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
9 from roborock.code_mappings
import DyadError, RoborockDyadStateCode, ZeoError, ZeoState
10 from roborock.containers
import (
11 RoborockDockErrorCode,
16 from roborock.roborock_message
import (
18 RoborockDyadDataProtocol,
21 from roborock.roborock_typing
import DeviceProp
26 SensorEntityDescription,
33 from .
import RoborockConfigEntry
34 from .coordinator
import RoborockDataUpdateCoordinator, RoborockDataUpdateCoordinatorA01
35 from .entity
import RoborockCoordinatedEntityA01, RoborockCoordinatedEntityV1
38 @dataclass(frozen=True, kw_only=True)
40 """A class that describes Roborock sensors."""
42 value_fn: Callable[[DeviceProp], StateType | datetime.datetime]
44 protocol_listener: RoborockDataProtocol |
None =
None
47 @dataclass(frozen=True, kw_only=True)
49 """A class that describes Roborock sensors."""
51 data_protocol: RoborockDyadDataProtocol | RoborockZeoProtocol
56 status := properties.status.dock_error_status
57 )
is not None and properties.status.dock_type != RoborockDockTypeCode.no_dock:
63 SENSOR_DESCRIPTIONS = [
65 native_unit_of_measurement=UnitOfTime.SECONDS,
66 key=
"main_brush_time_left",
67 device_class=SensorDeviceClass.DURATION,
68 translation_key=
"main_brush_time_left",
69 value_fn=
lambda data: data.consumable.main_brush_time_left,
70 entity_category=EntityCategory.DIAGNOSTIC,
71 protocol_listener=RoborockDataProtocol.MAIN_BRUSH_WORK_TIME,
74 native_unit_of_measurement=UnitOfTime.SECONDS,
75 key=
"side_brush_time_left",
76 device_class=SensorDeviceClass.DURATION,
77 translation_key=
"side_brush_time_left",
78 value_fn=
lambda data: data.consumable.side_brush_time_left,
79 entity_category=EntityCategory.DIAGNOSTIC,
80 protocol_listener=RoborockDataProtocol.SIDE_BRUSH_WORK_TIME,
83 native_unit_of_measurement=UnitOfTime.SECONDS,
84 key=
"filter_time_left",
85 device_class=SensorDeviceClass.DURATION,
86 translation_key=
"filter_time_left",
87 value_fn=
lambda data: data.consumable.filter_time_left,
88 entity_category=EntityCategory.DIAGNOSTIC,
89 protocol_listener=RoborockDataProtocol.FILTER_WORK_TIME,
92 native_unit_of_measurement=UnitOfTime.SECONDS,
93 key=
"sensor_time_left",
94 device_class=SensorDeviceClass.DURATION,
95 translation_key=
"sensor_time_left",
96 value_fn=
lambda data: data.consumable.sensor_time_left,
97 entity_category=EntityCategory.DIAGNOSTIC,
100 native_unit_of_measurement=UnitOfTime.SECONDS,
102 translation_key=
"cleaning_time",
103 device_class=SensorDeviceClass.DURATION,
104 value_fn=
lambda data: data.status.clean_time,
105 entity_category=EntityCategory.DIAGNOSTIC,
108 native_unit_of_measurement=UnitOfTime.SECONDS,
109 key=
"total_cleaning_time",
110 translation_key=
"total_cleaning_time",
111 device_class=SensorDeviceClass.DURATION,
112 value_fn=
lambda data: data.clean_summary.clean_time,
113 entity_category=EntityCategory.DIAGNOSTIC,
117 device_class=SensorDeviceClass.ENUM,
118 translation_key=
"status",
119 value_fn=
lambda data: data.status.state_name,
120 entity_category=EntityCategory.DIAGNOSTIC,
121 options=RoborockStateCode.keys(),
122 protocol_listener=RoborockDataProtocol.STATE,
126 translation_key=
"cleaning_area",
127 value_fn=
lambda data: data.status.square_meter_clean_area,
128 entity_category=EntityCategory.DIAGNOSTIC,
129 native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
132 key=
"total_cleaning_area",
133 translation_key=
"total_cleaning_area",
134 value_fn=
lambda data: data.clean_summary.square_meter_clean_area,
135 entity_category=EntityCategory.DIAGNOSTIC,
136 native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
140 translation_key=
"vacuum_error",
141 device_class=SensorDeviceClass.ENUM,
142 value_fn=
lambda data: data.status.error_code_name,
143 entity_category=EntityCategory.DIAGNOSTIC,
144 options=RoborockErrorCode.keys(),
145 protocol_listener=RoborockDataProtocol.ERROR_CODE,
149 value_fn=
lambda data: data.status.battery,
150 entity_category=EntityCategory.DIAGNOSTIC,
151 native_unit_of_measurement=PERCENTAGE,
152 device_class=SensorDeviceClass.BATTERY,
153 protocol_listener=RoborockDataProtocol.BATTERY,
156 key=
"last_clean_start",
157 translation_key=
"last_clean_start",
158 value_fn=
lambda data: data.last_clean_record.begin_datetime
159 if data.last_clean_record
is not None
161 entity_category=EntityCategory.DIAGNOSTIC,
162 device_class=SensorDeviceClass.TIMESTAMP,
165 key=
"last_clean_end",
166 translation_key=
"last_clean_end",
167 value_fn=
lambda data: data.last_clean_record.end_datetime
168 if data.last_clean_record
is not None
170 entity_category=EntityCategory.DIAGNOSTIC,
171 device_class=SensorDeviceClass.TIMESTAMP,
176 translation_key=
"clean_percent",
177 value_fn=
lambda data: data.status.clean_percent,
178 entity_category=EntityCategory.DIAGNOSTIC,
179 native_unit_of_measurement=PERCENTAGE,
184 translation_key=
"dock_error",
185 value_fn=_dock_error_value_fn,
186 entity_category=EntityCategory.DIAGNOSTIC,
187 device_class=SensorDeviceClass.ENUM,
188 options=RoborockDockErrorCode.keys(),
191 key=
"mop_clean_remaining",
192 native_unit_of_measurement=UnitOfTime.SECONDS,
193 device_class=SensorDeviceClass.DURATION,
194 value_fn=
lambda data: data.status.rdt,
195 translation_key=
"mop_drying_remaining_time",
196 entity_category=EntityCategory.DIAGNOSTIC,
201 A01_SENSOR_DESCRIPTIONS: list[RoborockSensorDescriptionA01] = [
204 data_protocol=RoborockDyadDataProtocol.STATUS,
205 translation_key=
"a01_status",
206 entity_category=EntityCategory.DIAGNOSTIC,
207 device_class=SensorDeviceClass.ENUM,
208 options=RoborockDyadStateCode.keys(),
212 data_protocol=RoborockDyadDataProtocol.POWER,
213 entity_category=EntityCategory.DIAGNOSTIC,
214 native_unit_of_measurement=PERCENTAGE,
215 device_class=SensorDeviceClass.BATTERY,
218 key=
"filter_time_left",
219 data_protocol=RoborockDyadDataProtocol.MESH_LEFT,
220 native_unit_of_measurement=UnitOfTime.SECONDS,
221 device_class=SensorDeviceClass.DURATION,
222 translation_key=
"filter_time_left",
223 entity_category=EntityCategory.DIAGNOSTIC,
226 key=
"brush_remaining",
227 data_protocol=RoborockDyadDataProtocol.BRUSH_LEFT,
228 native_unit_of_measurement=UnitOfTime.SECONDS,
229 device_class=SensorDeviceClass.DURATION,
230 translation_key=
"brush_remaining",
231 entity_category=EntityCategory.DIAGNOSTIC,
235 data_protocol=RoborockDyadDataProtocol.ERROR,
236 device_class=SensorDeviceClass.ENUM,
237 translation_key=
"a01_error",
238 entity_category=EntityCategory.DIAGNOSTIC,
239 options=DyadError.keys(),
242 key=
"total_cleaning_time",
243 native_unit_of_measurement=UnitOfTime.MINUTES,
244 data_protocol=RoborockDyadDataProtocol.TOTAL_RUN_TIME,
245 device_class=SensorDeviceClass.DURATION,
246 translation_key=
"total_cleaning_time",
247 entity_category=EntityCategory.DIAGNOSTIC,
251 data_protocol=RoborockZeoProtocol.STATE,
252 translation_key=
"zeo_state",
253 entity_category=EntityCategory.DIAGNOSTIC,
254 device_class=SensorDeviceClass.ENUM,
255 options=ZeoState.keys(),
259 native_unit_of_measurement=UnitOfTime.MINUTES,
260 data_protocol=RoborockZeoProtocol.COUNTDOWN,
261 device_class=SensorDeviceClass.DURATION,
262 translation_key=
"countdown",
263 entity_category=EntityCategory.DIAGNOSTIC,
267 native_unit_of_measurement=UnitOfTime.MINUTES,
268 data_protocol=RoborockZeoProtocol.WASHING_LEFT,
269 device_class=SensorDeviceClass.DURATION,
270 translation_key=
"washing_left",
271 entity_category=EntityCategory.DIAGNOSTIC,
275 data_protocol=RoborockZeoProtocol.ERROR,
276 device_class=SensorDeviceClass.ENUM,
277 translation_key=
"zeo_error",
278 entity_category=EntityCategory.DIAGNOSTIC,
279 options=ZeoError.keys(),
286 config_entry: RoborockConfigEntry,
287 async_add_entities: AddEntitiesCallback,
289 """Set up the Roborock vacuum sensors."""
290 coordinators = config_entry.runtime_data
296 for coordinator
in coordinators.v1
297 for description
in SENSOR_DESCRIPTIONS
298 if description.value_fn(coordinator.roborock_device_info.props)
is not None
305 for coordinator
in coordinators.a01
306 for description
in A01_SENSOR_DESCRIPTIONS
307 if description.data_protocol
in coordinator.data
312 """Representation of a Roborock sensor."""
314 entity_description: RoborockSensorDescription
318 coordinator: RoborockDataUpdateCoordinator,
319 description: RoborockSensorDescription,
321 """Initialize the entity."""
324 f
"{description.key}_{coordinator.duid_slug}",
326 description.protocol_listener,
331 """Return the value reported by the sensor."""
333 self.coordinator.roborock_device_info.props
338 """Representation of a A01 Roborock sensor."""
340 entity_description: RoborockSensorDescriptionA01
344 coordinator: RoborockDataUpdateCoordinatorA01,
345 description: RoborockSensorDescriptionA01,
347 """Initialize the entity."""
349 super().
__init__(f
"{description.key}_{coordinator.duid_slug}", coordinator)
353 """Return the value reported by the sensor."""
StateType native_value(self)
None __init__(self, RoborockDataUpdateCoordinatorA01 coordinator, RoborockSensorDescriptionA01 description)
StateType|datetime.datetime native_value(self)
None __init__(self, RoborockDataUpdateCoordinator coordinator, RoborockSensorDescription description)
None async_setup_entry(HomeAssistant hass, RoborockConfigEntry config_entry, AddEntitiesCallback async_add_entities)
str|None _dock_error_value_fn(DeviceProp properties)