Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for Xiaomi Mi Air Quality Monitor (PM2.5) and Humidifier."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Iterable
6 from dataclasses import dataclass
7 import logging
8 
9 from miio import AirQualityMonitor, DeviceException
10 from miio.gateway.gateway import (
11  GATEWAY_MODEL_AC_V1,
12  GATEWAY_MODEL_AC_V2,
13  GATEWAY_MODEL_AC_V3,
14  GATEWAY_MODEL_AQARA,
15  GATEWAY_MODEL_EU,
16  GatewayException,
17 )
18 
20  SensorDeviceClass,
21  SensorEntity,
22  SensorEntityDescription,
23  SensorStateClass,
24 )
25 from homeassistant.config_entries import ConfigEntry
26 from homeassistant.const import (
27  ATTR_BATTERY_LEVEL,
28  ATTR_TEMPERATURE,
29  CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
30  CONCENTRATION_PARTS_PER_MILLION,
31  CONF_DEVICE,
32  CONF_HOST,
33  CONF_MODEL,
34  CONF_TOKEN,
35  LIGHT_LUX,
36  PERCENTAGE,
37  REVOLUTIONS_PER_MINUTE,
38  EntityCategory,
39  UnitOfArea,
40  UnitOfPower,
41  UnitOfPressure,
42  UnitOfTemperature,
43  UnitOfTime,
44  UnitOfVolume,
45 )
46 from homeassistant.core import HomeAssistant, callback
47 from homeassistant.helpers.device_registry import DeviceInfo
48 from homeassistant.helpers.entity_platform import AddEntitiesCallback
49 from homeassistant.util import dt as dt_util
50 
51 from . import VacuumCoordinatorDataAttributes
52 from .const import (
53  CONF_FLOW_TYPE,
54  CONF_GATEWAY,
55  DOMAIN,
56  KEY_COORDINATOR,
57  KEY_DEVICE,
58  MODEL_AIRFRESH_A1,
59  MODEL_AIRFRESH_T2017,
60  MODEL_AIRFRESH_VA2,
61  MODEL_AIRFRESH_VA4,
62  MODEL_AIRHUMIDIFIER_CA1,
63  MODEL_AIRHUMIDIFIER_CB1,
64  MODEL_AIRPURIFIER_3C,
65  MODEL_AIRPURIFIER_3C_REV_A,
66  MODEL_AIRPURIFIER_4,
67  MODEL_AIRPURIFIER_4_LITE_RMA1,
68  MODEL_AIRPURIFIER_4_LITE_RMB1,
69  MODEL_AIRPURIFIER_4_PRO,
70  MODEL_AIRPURIFIER_MA2,
71  MODEL_AIRPURIFIER_PRO,
72  MODEL_AIRPURIFIER_PRO_V7,
73  MODEL_AIRPURIFIER_V2,
74  MODEL_AIRPURIFIER_V3,
75  MODEL_AIRPURIFIER_ZA1,
76  MODEL_FAN_P5,
77  MODEL_FAN_V2,
78  MODEL_FAN_V3,
79  MODEL_FAN_ZA1,
80  MODEL_FAN_ZA3,
81  MODEL_FAN_ZA4,
82  MODEL_FAN_ZA5,
83  MODELS_AIR_QUALITY_MONITOR,
84  MODELS_HUMIDIFIER_MIIO,
85  MODELS_HUMIDIFIER_MIOT,
86  MODELS_HUMIDIFIER_MJJSQ,
87  MODELS_PURIFIER_MIIO,
88  MODELS_PURIFIER_MIOT,
89  MODELS_VACUUM,
90  ROBOROCK_GENERIC,
91  ROCKROBO_GENERIC,
92 )
93 from .entity import XiaomiCoordinatedMiioEntity, XiaomiGatewayDevice, XiaomiMiioEntity
94 
95 _LOGGER = logging.getLogger(__name__)
96 
97 DEFAULT_NAME = "Xiaomi Miio Sensor"
98 UNIT_LUMEN = "lm"
99 
100 ATTR_ACTUAL_SPEED = "actual_speed"
101 ATTR_AIR_QUALITY = "air_quality"
102 ATTR_TVOC = "tvoc"
103 ATTR_AQI = "aqi"
104 ATTR_BATTERY = "battery"
105 ATTR_CARBON_DIOXIDE = "co2"
106 ATTR_CHARGING = "charging"
107 ATTR_CONTROL_SPEED = "control_speed"
108 ATTR_DISPLAY_CLOCK = "display_clock"
109 ATTR_FAVORITE_SPEED = "favorite_speed"
110 ATTR_FILTER_LIFE_REMAINING = "filter_life_remaining"
111 ATTR_FILTER_HOURS_USED = "filter_hours_used"
112 ATTR_FILTER_LEFT_TIME = "filter_left_time"
113 ATTR_DUST_FILTER_LIFE_REMAINING = "dust_filter_life_remaining"
114 ATTR_DUST_FILTER_LIFE_REMAINING_DAYS = "dust_filter_life_remaining_days"
115 ATTR_UPPER_FILTER_LIFE_REMAINING = "upper_filter_life_remaining"
116 ATTR_UPPER_FILTER_LIFE_REMAINING_DAYS = "upper_filter_life_remaining_days"
117 ATTR_FILTER_USE = "filter_use"
118 ATTR_HUMIDITY = "humidity"
119 ATTR_ILLUMINANCE = "illuminance"
120 ATTR_ILLUMINANCE_LUX = "illuminance_lux"
121 ATTR_LOAD_POWER = "load_power"
122 ATTR_MOTOR2_SPEED = "motor2_speed"
123 ATTR_MOTOR_SPEED = "motor_speed"
124 ATTR_NIGHT_MODE = "night_mode"
125 ATTR_NIGHT_TIME_BEGIN = "night_time_begin"
126 ATTR_NIGHT_TIME_END = "night_time_end"
127 ATTR_PM10 = "pm10_density"
128 ATTR_PM25 = "pm25"
129 ATTR_PM25_2 = "pm25_2"
130 ATTR_POWER = "power"
131 ATTR_PRESSURE = "pressure"
132 ATTR_PURIFY_VOLUME = "purify_volume"
133 ATTR_SENSOR_STATE = "sensor_state"
134 ATTR_USE_TIME = "use_time"
135 ATTR_WATER_LEVEL = "water_level"
136 ATTR_DND_START = "start"
137 ATTR_DND_END = "end"
138 ATTR_LAST_CLEAN_TIME = "duration"
139 ATTR_LAST_CLEAN_AREA = "area"
140 ATTR_STATUS_CLEAN_TIME = "clean_time"
141 ATTR_STATUS_CLEAN_AREA = "clean_area"
142 ATTR_LAST_CLEAN_START = "start"
143 ATTR_LAST_CLEAN_END = "end"
144 ATTR_CLEAN_HISTORY_TOTAL_DURATION = "total_duration"
145 ATTR_CLEAN_HISTORY_TOTAL_AREA = "total_area"
146 ATTR_CLEAN_HISTORY_COUNT = "count"
147 ATTR_CLEAN_HISTORY_DUST_COLLECTION_COUNT = "dust_collection_count"
148 ATTR_CONSUMABLE_STATUS_MAIN_BRUSH_LEFT = "main_brush_left"
149 ATTR_CONSUMABLE_STATUS_SIDE_BRUSH_LEFT = "side_brush_left"
150 ATTR_CONSUMABLE_STATUS_FILTER_LEFT = "filter_left"
151 ATTR_CONSUMABLE_STATUS_SENSOR_DIRTY_LEFT = "sensor_dirty_left"
152 
153 
154 @dataclass(frozen=True)
156  """Class that holds device specific info for a xiaomi aqara or humidifier sensor."""
157 
158  attributes: tuple = ()
159  parent_key: str | None = None
160 
161 
162 SENSOR_TYPES = {
163  ATTR_TEMPERATURE: XiaomiMiioSensorDescription(
164  key=ATTR_TEMPERATURE,
165  native_unit_of_measurement=UnitOfTemperature.CELSIUS,
166  device_class=SensorDeviceClass.TEMPERATURE,
167  state_class=SensorStateClass.MEASUREMENT,
168  ),
169  ATTR_HUMIDITY: XiaomiMiioSensorDescription(
170  key=ATTR_HUMIDITY,
171  native_unit_of_measurement=PERCENTAGE,
172  device_class=SensorDeviceClass.HUMIDITY,
173  state_class=SensorStateClass.MEASUREMENT,
174  ),
175  ATTR_PRESSURE: XiaomiMiioSensorDescription(
176  key=ATTR_PRESSURE,
177  native_unit_of_measurement=UnitOfPressure.HPA,
178  device_class=SensorDeviceClass.ATMOSPHERIC_PRESSURE,
179  state_class=SensorStateClass.MEASUREMENT,
180  ),
181  ATTR_LOAD_POWER: XiaomiMiioSensorDescription(
182  key=ATTR_LOAD_POWER,
183  translation_key=ATTR_LOAD_POWER,
184  native_unit_of_measurement=UnitOfPower.WATT,
185  device_class=SensorDeviceClass.POWER,
186  ),
187  ATTR_WATER_LEVEL: XiaomiMiioSensorDescription(
188  key=ATTR_WATER_LEVEL,
189  translation_key=ATTR_WATER_LEVEL,
190  native_unit_of_measurement=PERCENTAGE,
191  icon="mdi:water-check",
192  state_class=SensorStateClass.MEASUREMENT,
193  entity_category=EntityCategory.DIAGNOSTIC,
194  ),
195  ATTR_ACTUAL_SPEED: XiaomiMiioSensorDescription(
196  key=ATTR_ACTUAL_SPEED,
197  translation_key=ATTR_ACTUAL_SPEED,
198  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
199  icon="mdi:fast-forward",
200  state_class=SensorStateClass.MEASUREMENT,
201  entity_category=EntityCategory.DIAGNOSTIC,
202  ),
203  ATTR_CONTROL_SPEED: XiaomiMiioSensorDescription(
204  key=ATTR_CONTROL_SPEED,
205  translation_key=ATTR_CONTROL_SPEED,
206  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
207  icon="mdi:fast-forward",
208  state_class=SensorStateClass.MEASUREMENT,
209  entity_category=EntityCategory.DIAGNOSTIC,
210  ),
211  ATTR_FAVORITE_SPEED: XiaomiMiioSensorDescription(
212  key=ATTR_FAVORITE_SPEED,
213  translation_key=ATTR_FAVORITE_SPEED,
214  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
215  icon="mdi:fast-forward",
216  state_class=SensorStateClass.MEASUREMENT,
217  entity_category=EntityCategory.DIAGNOSTIC,
218  ),
219  ATTR_MOTOR_SPEED: XiaomiMiioSensorDescription(
220  key=ATTR_MOTOR_SPEED,
221  translation_key=ATTR_MOTOR_SPEED,
222  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
223  icon="mdi:fast-forward",
224  state_class=SensorStateClass.MEASUREMENT,
225  entity_category=EntityCategory.DIAGNOSTIC,
226  ),
227  ATTR_MOTOR2_SPEED: XiaomiMiioSensorDescription(
228  key=ATTR_MOTOR2_SPEED,
229  translation_key=ATTR_MOTOR2_SPEED,
230  native_unit_of_measurement=REVOLUTIONS_PER_MINUTE,
231  icon="mdi:fast-forward",
232  state_class=SensorStateClass.MEASUREMENT,
233  entity_category=EntityCategory.DIAGNOSTIC,
234  ),
235  ATTR_USE_TIME: XiaomiMiioSensorDescription(
236  key=ATTR_USE_TIME,
237  translation_key=ATTR_USE_TIME,
238  native_unit_of_measurement=UnitOfTime.SECONDS,
239  icon="mdi:progress-clock",
240  device_class=SensorDeviceClass.DURATION,
241  state_class=SensorStateClass.TOTAL_INCREASING,
242  entity_registry_enabled_default=False,
243  entity_category=EntityCategory.DIAGNOSTIC,
244  ),
245  ATTR_ILLUMINANCE: XiaomiMiioSensorDescription(
246  key=ATTR_ILLUMINANCE,
247  translation_key=ATTR_ILLUMINANCE,
248  native_unit_of_measurement=UNIT_LUMEN,
249  state_class=SensorStateClass.MEASUREMENT,
250  ),
251  ATTR_ILLUMINANCE_LUX: XiaomiMiioSensorDescription(
252  key=ATTR_ILLUMINANCE,
253  native_unit_of_measurement=LIGHT_LUX,
254  device_class=SensorDeviceClass.ILLUMINANCE,
255  state_class=SensorStateClass.MEASUREMENT,
256  ),
257  ATTR_AIR_QUALITY: XiaomiMiioSensorDescription(
258  key=ATTR_AIR_QUALITY,
259  translation_key=ATTR_AIR_QUALITY,
260  native_unit_of_measurement="AQI",
261  icon="mdi:cloud",
262  state_class=SensorStateClass.MEASUREMENT,
263  ),
264  ATTR_TVOC: XiaomiMiioSensorDescription(
265  key=ATTR_TVOC,
266  translation_key=ATTR_TVOC,
267  state_class=SensorStateClass.MEASUREMENT,
268  native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
269  device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
270  ),
271  ATTR_PM10: XiaomiMiioSensorDescription(
272  key=ATTR_PM10,
273  native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
274  device_class=SensorDeviceClass.PM10,
275  state_class=SensorStateClass.MEASUREMENT,
276  ),
277  ATTR_PM25: XiaomiMiioSensorDescription(
278  key=ATTR_AQI,
279  translation_key=ATTR_AQI,
280  native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
281  device_class=SensorDeviceClass.PM25,
282  state_class=SensorStateClass.MEASUREMENT,
283  ),
284  ATTR_PM25_2: XiaomiMiioSensorDescription(
285  key=ATTR_PM25,
286  native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
287  device_class=SensorDeviceClass.PM25,
288  state_class=SensorStateClass.MEASUREMENT,
289  ),
290  ATTR_FILTER_LIFE_REMAINING: XiaomiMiioSensorDescription(
291  key=ATTR_FILTER_LIFE_REMAINING,
292  translation_key=ATTR_FILTER_LIFE_REMAINING,
293  native_unit_of_measurement=PERCENTAGE,
294  icon="mdi:air-filter",
295  state_class=SensorStateClass.MEASUREMENT,
296  attributes=("filter_type",),
297  entity_category=EntityCategory.DIAGNOSTIC,
298  ),
299  ATTR_FILTER_USE: XiaomiMiioSensorDescription(
300  key=ATTR_FILTER_HOURS_USED,
301  translation_key=ATTR_FILTER_HOURS_USED,
302  native_unit_of_measurement=UnitOfTime.HOURS,
303  icon="mdi:clock-outline",
304  device_class=SensorDeviceClass.DURATION,
305  state_class=SensorStateClass.MEASUREMENT,
306  entity_category=EntityCategory.DIAGNOSTIC,
307  ),
308  ATTR_FILTER_LEFT_TIME: XiaomiMiioSensorDescription(
309  key=ATTR_FILTER_LEFT_TIME,
310  translation_key=ATTR_FILTER_LEFT_TIME,
311  native_unit_of_measurement=UnitOfTime.DAYS,
312  icon="mdi:clock-outline",
313  device_class=SensorDeviceClass.DURATION,
314  state_class=SensorStateClass.MEASUREMENT,
315  entity_category=EntityCategory.DIAGNOSTIC,
316  ),
317  ATTR_DUST_FILTER_LIFE_REMAINING: XiaomiMiioSensorDescription(
318  key=ATTR_DUST_FILTER_LIFE_REMAINING,
319  translation_key=ATTR_DUST_FILTER_LIFE_REMAINING,
320  native_unit_of_measurement=PERCENTAGE,
321  icon="mdi:air-filter",
322  state_class=SensorStateClass.MEASUREMENT,
323  attributes=("filter_type",),
324  entity_category=EntityCategory.DIAGNOSTIC,
325  ),
326  ATTR_DUST_FILTER_LIFE_REMAINING_DAYS: XiaomiMiioSensorDescription(
327  key=ATTR_DUST_FILTER_LIFE_REMAINING_DAYS,
328  translation_key=ATTR_DUST_FILTER_LIFE_REMAINING_DAYS,
329  native_unit_of_measurement=UnitOfTime.DAYS,
330  icon="mdi:clock-outline",
331  device_class=SensorDeviceClass.DURATION,
332  state_class=SensorStateClass.MEASUREMENT,
333  entity_category=EntityCategory.DIAGNOSTIC,
334  ),
335  ATTR_UPPER_FILTER_LIFE_REMAINING: XiaomiMiioSensorDescription(
336  key=ATTR_UPPER_FILTER_LIFE_REMAINING,
337  translation_key=ATTR_UPPER_FILTER_LIFE_REMAINING,
338  native_unit_of_measurement=PERCENTAGE,
339  icon="mdi:air-filter",
340  state_class=SensorStateClass.MEASUREMENT,
341  attributes=("filter_type",),
342  entity_category=EntityCategory.DIAGNOSTIC,
343  ),
344  ATTR_UPPER_FILTER_LIFE_REMAINING_DAYS: XiaomiMiioSensorDescription(
345  key=ATTR_UPPER_FILTER_LIFE_REMAINING_DAYS,
346  translation_key=ATTR_UPPER_FILTER_LIFE_REMAINING_DAYS,
347  native_unit_of_measurement=UnitOfTime.DAYS,
348  icon="mdi:clock-outline",
349  device_class=SensorDeviceClass.DURATION,
350  state_class=SensorStateClass.MEASUREMENT,
351  entity_category=EntityCategory.DIAGNOSTIC,
352  ),
353  ATTR_CARBON_DIOXIDE: XiaomiMiioSensorDescription(
354  key=ATTR_CARBON_DIOXIDE,
355  native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
356  device_class=SensorDeviceClass.CO2,
357  state_class=SensorStateClass.MEASUREMENT,
358  ),
359  ATTR_PURIFY_VOLUME: XiaomiMiioSensorDescription(
360  key=ATTR_PURIFY_VOLUME,
361  translation_key=ATTR_PURIFY_VOLUME,
362  native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
363  device_class=SensorDeviceClass.VOLUME,
364  state_class=SensorStateClass.TOTAL_INCREASING,
365  entity_registry_enabled_default=False,
366  entity_category=EntityCategory.DIAGNOSTIC,
367  ),
368  ATTR_BATTERY: XiaomiMiioSensorDescription(
369  key=ATTR_BATTERY,
370  native_unit_of_measurement=PERCENTAGE,
371  device_class=SensorDeviceClass.BATTERY,
372  state_class=SensorStateClass.MEASUREMENT,
373  entity_category=EntityCategory.DIAGNOSTIC,
374  ),
375 }
376 
377 HUMIDIFIER_MIIO_SENSORS = (
378  ATTR_HUMIDITY,
379  ATTR_TEMPERATURE,
380  ATTR_USE_TIME,
381  ATTR_WATER_LEVEL,
382 )
383 HUMIDIFIER_CA1_CB1_SENSORS = (
384  ATTR_HUMIDITY,
385  ATTR_TEMPERATURE,
386  ATTR_MOTOR_SPEED,
387  ATTR_USE_TIME,
388  ATTR_WATER_LEVEL,
389 )
390 HUMIDIFIER_MIOT_SENSORS = (
391  ATTR_ACTUAL_SPEED,
392  ATTR_HUMIDITY,
393  ATTR_TEMPERATURE,
394  ATTR_USE_TIME,
395  ATTR_WATER_LEVEL,
396 )
397 HUMIDIFIER_MJJSQ_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE)
398 
399 PURIFIER_MIIO_SENSORS = (
400  ATTR_FILTER_LIFE_REMAINING,
401  ATTR_FILTER_USE,
402  ATTR_HUMIDITY,
403  ATTR_MOTOR_SPEED,
404  ATTR_PM25,
405  ATTR_TEMPERATURE,
406  ATTR_USE_TIME,
407 )
408 PURIFIER_MIOT_SENSORS = (
409  ATTR_FILTER_LIFE_REMAINING,
410  ATTR_FILTER_USE,
411  ATTR_HUMIDITY,
412  ATTR_MOTOR_SPEED,
413  ATTR_PM25,
414  ATTR_PURIFY_VOLUME,
415  ATTR_TEMPERATURE,
416  ATTR_USE_TIME,
417 )
418 PURIFIER_4_LITE_SENSORS = (
419  ATTR_FILTER_LIFE_REMAINING,
420  ATTR_FILTER_LEFT_TIME,
421  ATTR_FILTER_USE,
422  ATTR_HUMIDITY,
423  ATTR_MOTOR_SPEED,
424  ATTR_PM25,
425  ATTR_TEMPERATURE,
426  ATTR_USE_TIME,
427 )
428 PURIFIER_4_SENSORS = (
429  ATTR_FILTER_LIFE_REMAINING,
430  ATTR_FILTER_LEFT_TIME,
431  ATTR_FILTER_USE,
432  ATTR_HUMIDITY,
433  ATTR_MOTOR_SPEED,
434  ATTR_PM25,
435  ATTR_PURIFY_VOLUME,
436  ATTR_TEMPERATURE,
437  ATTR_USE_TIME,
438 )
439 PURIFIER_4_PRO_SENSORS = (
440  ATTR_FILTER_LIFE_REMAINING,
441  ATTR_FILTER_LEFT_TIME,
442  ATTR_FILTER_USE,
443  ATTR_HUMIDITY,
444  ATTR_MOTOR_SPEED,
445  ATTR_PM25,
446  ATTR_PM10,
447  ATTR_PURIFY_VOLUME,
448  ATTR_TEMPERATURE,
449  ATTR_USE_TIME,
450 )
451 PURIFIER_3C_SENSORS = (
452  ATTR_FILTER_LIFE_REMAINING,
453  ATTR_FILTER_USE,
454  ATTR_MOTOR_SPEED,
455  ATTR_PM25,
456 )
457 PURIFIER_ZA1_SENSORS = (
458  ATTR_FILTER_LIFE_REMAINING,
459  ATTR_FILTER_USE,
460  ATTR_MOTOR_SPEED,
461  ATTR_PM25,
462  ATTR_TVOC,
463  ATTR_HUMIDITY,
464  ATTR_TEMPERATURE,
465 )
466 PURIFIER_MA2_SENSORS = (
467  ATTR_FILTER_LIFE_REMAINING,
468  ATTR_FILTER_USE,
469  ATTR_HUMIDITY,
470  ATTR_MOTOR_SPEED,
471  ATTR_PM25,
472  ATTR_TEMPERATURE,
473  ATTR_USE_TIME,
474  ATTR_ILLUMINANCE,
475 )
476 PURIFIER_V2_SENSORS = (
477  ATTR_FILTER_LIFE_REMAINING,
478  ATTR_FILTER_USE,
479  ATTR_HUMIDITY,
480  ATTR_MOTOR_SPEED,
481  ATTR_PM25,
482  ATTR_PURIFY_VOLUME,
483  ATTR_TEMPERATURE,
484  ATTR_USE_TIME,
485 )
486 PURIFIER_V3_SENSORS = (
487  ATTR_FILTER_LIFE_REMAINING,
488  ATTR_FILTER_USE,
489  ATTR_ILLUMINANCE_LUX,
490  ATTR_MOTOR2_SPEED,
491  ATTR_MOTOR_SPEED,
492  ATTR_PM25,
493  ATTR_PURIFY_VOLUME,
494  ATTR_USE_TIME,
495 )
496 PURIFIER_PRO_SENSORS = (
497  ATTR_FILTER_LIFE_REMAINING,
498  ATTR_FILTER_USE,
499  ATTR_HUMIDITY,
500  ATTR_ILLUMINANCE_LUX,
501  ATTR_MOTOR2_SPEED,
502  ATTR_MOTOR_SPEED,
503  ATTR_PM25,
504  ATTR_PURIFY_VOLUME,
505  ATTR_TEMPERATURE,
506  ATTR_USE_TIME,
507 )
508 PURIFIER_PRO_V7_SENSORS = (
509  ATTR_FILTER_LIFE_REMAINING,
510  ATTR_FILTER_USE,
511  ATTR_HUMIDITY,
512  ATTR_ILLUMINANCE_LUX,
513  ATTR_MOTOR2_SPEED,
514  ATTR_MOTOR_SPEED,
515  ATTR_PM25,
516  ATTR_TEMPERATURE,
517  ATTR_USE_TIME,
518 )
519 AIRFRESH_SENSORS = (
520  ATTR_CARBON_DIOXIDE,
521  ATTR_FILTER_LIFE_REMAINING,
522  ATTR_FILTER_USE,
523  ATTR_HUMIDITY,
524  ATTR_PM25,
525  ATTR_TEMPERATURE,
526  ATTR_USE_TIME,
527 )
528 AIRFRESH_SENSORS_A1 = (
529  ATTR_CARBON_DIOXIDE,
530  ATTR_DUST_FILTER_LIFE_REMAINING,
531  ATTR_DUST_FILTER_LIFE_REMAINING_DAYS,
532  ATTR_PM25_2,
533  ATTR_TEMPERATURE,
534  ATTR_CONTROL_SPEED,
535  ATTR_FAVORITE_SPEED,
536 )
537 AIRFRESH_SENSORS_T2017 = (
538  ATTR_CARBON_DIOXIDE,
539  ATTR_DUST_FILTER_LIFE_REMAINING,
540  ATTR_DUST_FILTER_LIFE_REMAINING_DAYS,
541  ATTR_UPPER_FILTER_LIFE_REMAINING,
542  ATTR_UPPER_FILTER_LIFE_REMAINING_DAYS,
543  ATTR_PM25_2,
544  ATTR_TEMPERATURE,
545  ATTR_CONTROL_SPEED,
546  ATTR_FAVORITE_SPEED,
547 )
548 FAN_V2_V3_SENSORS = (
549  ATTR_BATTERY,
550  ATTR_HUMIDITY,
551  ATTR_TEMPERATURE,
552 )
553 
554 FAN_ZA5_SENSORS = (ATTR_HUMIDITY, ATTR_TEMPERATURE)
555 
556 MODEL_TO_SENSORS_MAP: dict[str, tuple[str, ...]] = {
557  MODEL_AIRFRESH_A1: AIRFRESH_SENSORS_A1,
558  MODEL_AIRFRESH_VA2: AIRFRESH_SENSORS,
559  MODEL_AIRFRESH_VA4: AIRFRESH_SENSORS,
560  MODEL_AIRFRESH_T2017: AIRFRESH_SENSORS_T2017,
561  MODEL_AIRHUMIDIFIER_CA1: HUMIDIFIER_CA1_CB1_SENSORS,
562  MODEL_AIRHUMIDIFIER_CB1: HUMIDIFIER_CA1_CB1_SENSORS,
563  MODEL_AIRPURIFIER_3C: PURIFIER_3C_SENSORS,
564  MODEL_AIRPURIFIER_3C_REV_A: PURIFIER_3C_SENSORS,
565  MODEL_AIRPURIFIER_4_LITE_RMA1: PURIFIER_4_LITE_SENSORS,
566  MODEL_AIRPURIFIER_4_LITE_RMB1: PURIFIER_4_LITE_SENSORS,
567  MODEL_AIRPURIFIER_4: PURIFIER_4_SENSORS,
568  MODEL_AIRPURIFIER_4_PRO: PURIFIER_4_PRO_SENSORS,
569  MODEL_AIRPURIFIER_PRO: PURIFIER_PRO_SENSORS,
570  MODEL_AIRPURIFIER_PRO_V7: PURIFIER_PRO_V7_SENSORS,
571  MODEL_AIRPURIFIER_V2: PURIFIER_V2_SENSORS,
572  MODEL_AIRPURIFIER_V3: PURIFIER_V3_SENSORS,
573  MODEL_AIRPURIFIER_ZA1: PURIFIER_ZA1_SENSORS,
574  MODEL_AIRPURIFIER_MA2: PURIFIER_MA2_SENSORS,
575  MODEL_FAN_V2: FAN_V2_V3_SENSORS,
576  MODEL_FAN_V3: FAN_V2_V3_SENSORS,
577  MODEL_FAN_ZA5: FAN_ZA5_SENSORS,
578 }
579 
580 VACUUM_SENSORS = {
581  f"dnd_{ATTR_DND_START}": XiaomiMiioSensorDescription(
582  key=ATTR_DND_START,
583  icon="mdi:minus-circle-off",
584  translation_key="dnd_start",
585  device_class=SensorDeviceClass.TIMESTAMP,
586  parent_key=VacuumCoordinatorDataAttributes.dnd_status,
587  entity_registry_enabled_default=False,
588  entity_category=EntityCategory.DIAGNOSTIC,
589  ),
590  f"dnd_{ATTR_DND_END}": XiaomiMiioSensorDescription(
591  key=ATTR_DND_END,
592  icon="mdi:minus-circle-off",
593  translation_key="dnd_end",
594  device_class=SensorDeviceClass.TIMESTAMP,
595  parent_key=VacuumCoordinatorDataAttributes.dnd_status,
596  entity_registry_enabled_default=False,
597  entity_category=EntityCategory.DIAGNOSTIC,
598  ),
599  f"last_clean_{ATTR_LAST_CLEAN_START}": XiaomiMiioSensorDescription(
600  key=ATTR_LAST_CLEAN_START,
601  icon="mdi:clock-time-twelve",
602  translation_key="last_clean_start",
603  device_class=SensorDeviceClass.TIMESTAMP,
604  parent_key=VacuumCoordinatorDataAttributes.last_clean_details,
605  entity_category=EntityCategory.DIAGNOSTIC,
606  ),
607  f"last_clean_{ATTR_LAST_CLEAN_END}": XiaomiMiioSensorDescription(
608  key=ATTR_LAST_CLEAN_END,
609  icon="mdi:clock-time-twelve",
610  device_class=SensorDeviceClass.TIMESTAMP,
611  parent_key=VacuumCoordinatorDataAttributes.last_clean_details,
612  translation_key="last_clean_end",
613  entity_category=EntityCategory.DIAGNOSTIC,
614  ),
615  f"last_clean_{ATTR_LAST_CLEAN_TIME}": XiaomiMiioSensorDescription(
616  native_unit_of_measurement=UnitOfTime.SECONDS,
617  icon="mdi:timer-sand",
618  device_class=SensorDeviceClass.DURATION,
619  key=ATTR_LAST_CLEAN_TIME,
620  parent_key=VacuumCoordinatorDataAttributes.last_clean_details,
621  translation_key=ATTR_LAST_CLEAN_TIME,
622  entity_category=EntityCategory.DIAGNOSTIC,
623  ),
624  f"last_clean_{ATTR_LAST_CLEAN_AREA}": XiaomiMiioSensorDescription(
625  native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
626  icon="mdi:texture-box",
627  key=ATTR_LAST_CLEAN_AREA,
628  parent_key=VacuumCoordinatorDataAttributes.last_clean_details,
629  translation_key=ATTR_LAST_CLEAN_AREA,
630  entity_category=EntityCategory.DIAGNOSTIC,
631  ),
632  f"current_{ATTR_STATUS_CLEAN_TIME}": XiaomiMiioSensorDescription(
633  native_unit_of_measurement=UnitOfTime.SECONDS,
634  icon="mdi:timer-sand",
635  device_class=SensorDeviceClass.DURATION,
636  key=ATTR_STATUS_CLEAN_TIME,
637  parent_key=VacuumCoordinatorDataAttributes.status,
638  translation_key=ATTR_STATUS_CLEAN_TIME,
639  entity_category=EntityCategory.DIAGNOSTIC,
640  ),
641  f"current_{ATTR_LAST_CLEAN_AREA}": XiaomiMiioSensorDescription(
642  native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
643  icon="mdi:texture-box",
644  key=ATTR_STATUS_CLEAN_AREA,
645  parent_key=VacuumCoordinatorDataAttributes.status,
646  entity_category=EntityCategory.DIAGNOSTIC,
647  translation_key=ATTR_STATUS_CLEAN_AREA,
648  ),
649  f"clean_history_{ATTR_CLEAN_HISTORY_TOTAL_DURATION}": XiaomiMiioSensorDescription(
650  native_unit_of_measurement=UnitOfTime.SECONDS,
651  device_class=SensorDeviceClass.DURATION,
652  icon="mdi:timer-sand",
653  key=ATTR_CLEAN_HISTORY_TOTAL_DURATION,
654  parent_key=VacuumCoordinatorDataAttributes.clean_history_status,
655  translation_key=ATTR_CLEAN_HISTORY_TOTAL_DURATION,
656  entity_registry_enabled_default=False,
657  entity_category=EntityCategory.DIAGNOSTIC,
658  ),
659  f"clean_history_{ATTR_CLEAN_HISTORY_TOTAL_AREA}": XiaomiMiioSensorDescription(
660  native_unit_of_measurement=UnitOfArea.SQUARE_METERS,
661  icon="mdi:texture-box",
662  key=ATTR_CLEAN_HISTORY_TOTAL_AREA,
663  parent_key=VacuumCoordinatorDataAttributes.clean_history_status,
664  translation_key=ATTR_CLEAN_HISTORY_TOTAL_AREA,
665  entity_registry_enabled_default=False,
666  entity_category=EntityCategory.DIAGNOSTIC,
667  ),
668  f"clean_history_{ATTR_CLEAN_HISTORY_COUNT}": XiaomiMiioSensorDescription(
669  native_unit_of_measurement="",
670  icon="mdi:counter",
671  state_class=SensorStateClass.TOTAL_INCREASING,
672  key=ATTR_CLEAN_HISTORY_COUNT,
673  parent_key=VacuumCoordinatorDataAttributes.clean_history_status,
674  translation_key=ATTR_CLEAN_HISTORY_COUNT,
675  entity_registry_enabled_default=False,
676  entity_category=EntityCategory.DIAGNOSTIC,
677  ),
678  f"clean_history_{ATTR_CLEAN_HISTORY_DUST_COLLECTION_COUNT}": XiaomiMiioSensorDescription(
679  native_unit_of_measurement="",
680  icon="mdi:counter",
681  state_class=SensorStateClass.TOTAL_INCREASING,
682  key=ATTR_CLEAN_HISTORY_DUST_COLLECTION_COUNT,
683  parent_key=VacuumCoordinatorDataAttributes.clean_history_status,
684  translation_key=ATTR_CLEAN_HISTORY_DUST_COLLECTION_COUNT,
685  entity_registry_enabled_default=False,
686  entity_category=EntityCategory.DIAGNOSTIC,
687  ),
688  f"consumable_{ATTR_CONSUMABLE_STATUS_MAIN_BRUSH_LEFT}": XiaomiMiioSensorDescription(
689  native_unit_of_measurement=UnitOfTime.SECONDS,
690  icon="mdi:brush",
691  device_class=SensorDeviceClass.DURATION,
692  key=ATTR_CONSUMABLE_STATUS_MAIN_BRUSH_LEFT,
693  parent_key=VacuumCoordinatorDataAttributes.consumable_status,
694  translation_key=ATTR_CONSUMABLE_STATUS_MAIN_BRUSH_LEFT,
695  entity_category=EntityCategory.DIAGNOSTIC,
696  ),
697  f"consumable_{ATTR_CONSUMABLE_STATUS_SIDE_BRUSH_LEFT}": XiaomiMiioSensorDescription(
698  native_unit_of_measurement=UnitOfTime.SECONDS,
699  icon="mdi:brush",
700  device_class=SensorDeviceClass.DURATION,
701  key=ATTR_CONSUMABLE_STATUS_SIDE_BRUSH_LEFT,
702  parent_key=VacuumCoordinatorDataAttributes.consumable_status,
703  translation_key=ATTR_CONSUMABLE_STATUS_SIDE_BRUSH_LEFT,
704  entity_category=EntityCategory.DIAGNOSTIC,
705  ),
706  f"consumable_{ATTR_CONSUMABLE_STATUS_FILTER_LEFT}": XiaomiMiioSensorDescription(
707  native_unit_of_measurement=UnitOfTime.SECONDS,
708  icon="mdi:air-filter",
709  device_class=SensorDeviceClass.DURATION,
710  key=ATTR_CONSUMABLE_STATUS_FILTER_LEFT,
711  parent_key=VacuumCoordinatorDataAttributes.consumable_status,
712  translation_key=ATTR_CONSUMABLE_STATUS_FILTER_LEFT,
713  entity_category=EntityCategory.DIAGNOSTIC,
714  ),
715  f"consumable_{ATTR_CONSUMABLE_STATUS_SENSOR_DIRTY_LEFT}": XiaomiMiioSensorDescription(
716  native_unit_of_measurement=UnitOfTime.SECONDS,
717  icon="mdi:eye-outline",
718  device_class=SensorDeviceClass.DURATION,
719  key=ATTR_CONSUMABLE_STATUS_SENSOR_DIRTY_LEFT,
720  parent_key=VacuumCoordinatorDataAttributes.consumable_status,
721  translation_key=ATTR_CONSUMABLE_STATUS_SENSOR_DIRTY_LEFT,
722  entity_category=EntityCategory.DIAGNOSTIC,
723  ),
724 }
725 
726 
727 def _setup_vacuum_sensors(hass, config_entry, async_add_entities):
728  """Set up the Xiaomi vacuum sensors."""
729  device = hass.data[DOMAIN][config_entry.entry_id].get(KEY_DEVICE)
730  coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR]
731  entities = []
732 
733  for sensor, description in VACUUM_SENSORS.items():
734  parent_key_data = getattr(coordinator.data, description.parent_key)
735  if getattr(parent_key_data, description.key, None) is None:
736  _LOGGER.debug(
737  "It seems the %s does not support the %s as the initial value is None",
738  config_entry.data[CONF_MODEL],
739  description.key,
740  )
741  continue
742  entities.append(
744  device,
745  config_entry,
746  f"{sensor}_{config_entry.unique_id}",
747  coordinator,
748  description,
749  )
750  )
751 
752  async_add_entities(entities)
753 
754 
756  hass: HomeAssistant,
757  config_entry: ConfigEntry,
758  async_add_entities: AddEntitiesCallback,
759 ) -> None:
760  """Set up the Xiaomi sensor from a config entry."""
761  entities: list[SensorEntity] = []
762 
763  if config_entry.data[CONF_FLOW_TYPE] == CONF_GATEWAY:
764  gateway = hass.data[DOMAIN][config_entry.entry_id][CONF_GATEWAY]
765  # Gateway illuminance sensor
766  if gateway.model not in [
767  GATEWAY_MODEL_AC_V1,
768  GATEWAY_MODEL_AC_V2,
769  GATEWAY_MODEL_AC_V3,
770  GATEWAY_MODEL_AQARA,
771  GATEWAY_MODEL_EU,
772  ]:
773  description = SENSOR_TYPES[ATTR_ILLUMINANCE]
774  entities.append(
776  gateway, config_entry.title, config_entry.unique_id, description
777  )
778  )
779  # Gateway sub devices
780  sub_devices = gateway.devices
781  for sub_device in sub_devices.values():
782  coordinator = hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR][
783  sub_device.sid
784  ]
785  for sensor, description in SENSOR_TYPES.items():
786  if sensor not in sub_device.status:
787  continue
788  entities.append(
790  coordinator, sub_device, config_entry, description
791  )
792  )
793  elif config_entry.data[CONF_FLOW_TYPE] == CONF_DEVICE:
794  host = config_entry.data[CONF_HOST]
795  token = config_entry.data[CONF_TOKEN]
796  model: str = config_entry.data[CONF_MODEL]
797 
798  if model in (MODEL_FAN_ZA1, MODEL_FAN_ZA3, MODEL_FAN_ZA4, MODEL_FAN_P5):
799  return
800 
801  if model in MODELS_AIR_QUALITY_MONITOR:
802  unique_id = config_entry.unique_id
803  name = config_entry.title
804  _LOGGER.debug("Initializing with host %s (token %s...)", host, token[:5])
805 
806  device = AirQualityMonitor(host, token)
807  description = SENSOR_TYPES[ATTR_AIR_QUALITY]
808  entities.append(
810  name, device, config_entry, unique_id, description
811  )
812  )
813  else:
814  device = hass.data[DOMAIN][config_entry.entry_id][KEY_DEVICE]
815  sensors: Iterable[str] = []
816  if model in MODEL_TO_SENSORS_MAP:
817  sensors = MODEL_TO_SENSORS_MAP[model]
818  elif model in MODELS_HUMIDIFIER_MIOT:
819  sensors = HUMIDIFIER_MIOT_SENSORS
820  elif model in MODELS_HUMIDIFIER_MJJSQ:
821  sensors = HUMIDIFIER_MJJSQ_SENSORS
822  elif model in MODELS_HUMIDIFIER_MIIO:
823  sensors = HUMIDIFIER_MIIO_SENSORS
824  elif model in MODELS_PURIFIER_MIIO:
825  sensors = PURIFIER_MIIO_SENSORS
826  elif model in MODELS_PURIFIER_MIOT:
827  sensors = PURIFIER_MIOT_SENSORS
828  elif model in MODELS_VACUUM or model.startswith(
829  (ROBOROCK_GENERIC, ROCKROBO_GENERIC)
830  ):
831  _setup_vacuum_sensors(hass, config_entry, async_add_entities)
832  return
833 
834  for sensor, description in SENSOR_TYPES.items():
835  if sensor not in sensors:
836  continue
837  entities.append(
839  device,
840  config_entry,
841  f"{sensor}_{config_entry.unique_id}",
842  hass.data[DOMAIN][config_entry.entry_id][KEY_COORDINATOR],
843  description,
844  )
845  )
846 
847  async_add_entities(entities)
848 
849 
851  """Representation of a Xiaomi generic sensor."""
852 
853  entity_description: XiaomiMiioSensorDescription
854 
855  def __init__(self, device, entry, unique_id, coordinator, description):
856  """Initialize the entity."""
857  super().__init__(device, entry, unique_id, coordinator)
858  self.entity_descriptionentity_description = description
859  self._attr_unique_id_attr_unique_id = unique_id
860  self._attr_native_value_attr_native_value = self._determine_native_value_determine_native_value()
861  self._attr_extra_state_attributes_attr_extra_state_attributes = self._extract_attributes_extract_attributes(coordinator.data)
862 
863  @callback
864  def _extract_attributes(self, data):
865  """Return state attributes with valid values."""
866  return {
867  attr: value
868  for attr in self.entity_descriptionentity_description.attributes
869  if hasattr(data, attr)
870  and (value := self._extract_value_from_attribute(data, attr)) is not None
871  }
872 
873  @callback
875  """Fetch state from the device."""
876  native_value = self._determine_native_value_determine_native_value()
877  # Sometimes (quite rarely) the device returns None as the sensor value so we
878  # check that the value is not None before updating the state.
879  if native_value is not None:
880  self._attr_native_value_attr_native_value = native_value
881  self._attr_extra_state_attributes_attr_extra_state_attributes = self._extract_attributes_extract_attributes(
882  self.coordinator.data
883  )
884  self.async_write_ha_stateasync_write_ha_state()
885 
887  """Determine native value."""
888  if self.entity_descriptionentity_description.parent_key is not None:
889  native_value = self._extract_value_from_attribute(
890  getattr(self.coordinator.data, self.entity_descriptionentity_description.parent_key),
891  self.entity_descriptionentity_description.key,
892  )
893  else:
894  native_value = self._extract_value_from_attribute(
895  self.coordinator.data, self.entity_descriptionentity_description.key
896  )
897 
898  if (
899  self.device_classdevice_classdevice_classdevice_class == SensorDeviceClass.TIMESTAMP
900  and native_value is not None
901  and (native_datetime := dt_util.parse_datetime(str(native_value)))
902  is not None
903  ):
904  return native_datetime.astimezone(dt_util.UTC)
905 
906  return native_value
907 
908 
910  """Representation of a Xiaomi Air Quality Monitor."""
911 
912  def __init__(self, name, device, entry, unique_id, description):
913  """Initialize the entity."""
914  super().__init__(name, device, entry, unique_id)
915 
916  self._available_available_available = None
917  self._state_state = None
918  self._state_attrs_state_attrs = {
919  ATTR_POWER: None,
920  ATTR_BATTERY_LEVEL: None,
921  ATTR_CHARGING: None,
922  ATTR_DISPLAY_CLOCK: None,
923  ATTR_NIGHT_MODE: None,
924  ATTR_NIGHT_TIME_BEGIN: None,
925  ATTR_NIGHT_TIME_END: None,
926  ATTR_SENSOR_STATE: None,
927  }
928  self.entity_descriptionentity_description = description
929 
930  @property
931  def available(self):
932  """Return true when state is known."""
933  return self._available_available_available
934 
935  @property
936  def native_value(self):
937  """Return the state of the device."""
938  return self._state_state
939 
940  @property
942  """Return the state attributes of the device."""
943  return self._state_attrs_state_attrs
944 
945  async def async_update(self) -> None:
946  """Fetch state from the miio device."""
947  try:
948  state = await self.hasshass.async_add_executor_job(self._device_device.status)
949  _LOGGER.debug("Got new state: %s", state)
950 
951  self._available_available_available = True
952  self._state_state = state.aqi
953  self._state_attrs_state_attrs.update(
954  {
955  ATTR_POWER: state.power,
956  ATTR_CHARGING: state.usb_power,
957  ATTR_BATTERY_LEVEL: state.battery,
958  ATTR_DISPLAY_CLOCK: state.display_clock,
959  ATTR_NIGHT_MODE: state.night_mode,
960  ATTR_NIGHT_TIME_BEGIN: state.night_time_begin,
961  ATTR_NIGHT_TIME_END: state.night_time_end,
962  ATTR_SENSOR_STATE: state.sensor_state,
963  }
964  )
965 
966  except DeviceException as ex:
967  if self._available_available_available:
968  self._available_available_available = False
969  _LOGGER.error("Got exception while fetching the state: %s", ex)
970 
971 
973  """Representation of a XiaomiGatewaySensor."""
974 
975  def __init__(self, coordinator, sub_device, entry, description):
976  """Initialize the XiaomiSensor."""
977  super().__init__(coordinator, sub_device, entry)
978  self._unique_id_unique_id_unique_id = f"{sub_device.sid}-{description.key}"
979  self._name_name_name = f"{description.key} ({sub_device.sid})".capitalize()
980  self.entity_descriptionentity_description = description
981 
982  @property
983  def native_value(self):
984  """Return the state of the sensor."""
985  return self._sub_device_sub_device.status[self.entity_descriptionentity_description.key]
986 
987 
989  """Representation of the gateway device's illuminance sensor."""
990 
991  def __init__(self, gateway_device, gateway_name, gateway_device_id, description):
992  """Initialize the entity."""
993  self._attr_name_attr_name = f"{gateway_name} {description.name}"
994  self._attr_unique_id_attr_unique_id = f"{gateway_device_id}-{description.key}"
995  self._attr_device_info_attr_device_info = DeviceInfo(
996  identifiers={(DOMAIN, gateway_device_id)},
997  )
998  self._gateway_gateway = gateway_device
999  self.entity_descriptionentity_description = description
1000  self._available_available = False
1001  self._state_state = None
1002 
1003  @property
1004  def available(self):
1005  """Return true when state is known."""
1006  return self._available_available
1007 
1008  @property
1009  def native_value(self):
1010  """Return the state of the device."""
1011  return self._state_state
1012 
1013  async def async_update(self) -> None:
1014  """Fetch state from the device."""
1015  try:
1016  self._state_state = await self.hasshass.async_add_executor_job(
1017  self._gateway_gateway.get_illumination
1018  )
1019  self._available_available = True
1020  except GatewayException as ex:
1021  if self._available_available:
1022  self._available_available = False
1023  _LOGGER.error(
1024  "Got exception while fetching the gateway illuminance state: %s", ex
1025  )
SensorDeviceClass|None device_class(self)
Definition: __init__.py:313
def __init__(self, name, device, entry, unique_id, description)
Definition: sensor.py:912
def __init__(self, gateway_device, gateway_name, gateway_device_id, description)
Definition: sensor.py:991
def __init__(self, coordinator, sub_device, entry, description)
Definition: sensor.py:975
def __init__(self, device, entry, unique_id, coordinator, description)
Definition: sensor.py:855
web.Response get(self, web.Request request, str config_key)
Definition: view.py:88
IssData update(pyiss.ISS iss)
Definition: __init__.py:33
def _setup_vacuum_sensors(hass, config_entry, async_add_entities)
Definition: sensor.py:727
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:759