1 """Definition of air-Q sensor platform."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
8 from typing
import Literal
13 SensorEntityDescription,
17 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
18 CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
19 CONCENTRATION_PARTS_PER_BILLION,
20 CONCENTRATION_PARTS_PER_MILLION,
30 from .
import AirQConfigEntry, AirQCoordinator
32 ACTIVITY_BECQUEREL_PER_CUBIC_METER,
33 CONCENTRATION_GRAMS_PER_CUBIC_METER,
36 _LOGGER = logging.getLogger(__name__)
39 @dataclass(frozen=True, kw_only=True)
41 """Describes AirQ sensor entity."""
43 value: Callable[[dict], float | int |
None]
47 SENSOR_TYPES: list[AirQEntityDescription] = [
50 translation_key=
"acetaldehyde",
51 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
52 state_class=SensorStateClass.MEASUREMENT,
53 value=
lambda data: data.get(
"c2h4o"),
57 translation_key=
"ammonia",
58 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
59 state_class=SensorStateClass.MEASUREMENT,
60 value=
lambda data: data.get(
"nh3_MR100"),
64 translation_key=
"arsine",
65 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
66 state_class=SensorStateClass.MEASUREMENT,
67 value=
lambda data: data.get(
"ash3"),
71 translation_key=
"bromine",
72 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
73 state_class=SensorStateClass.MEASUREMENT,
74 value=
lambda data: data.get(
"br2"),
78 translation_key=
"methanethiol",
79 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
80 state_class=SensorStateClass.MEASUREMENT,
81 value=
lambda data: data.get(
"ch4s"),
85 translation_key=
"chlorine",
86 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
87 state_class=SensorStateClass.MEASUREMENT,
88 value=
lambda data: data.get(
"cl2_M20"),
92 translation_key=
"chlorine_dioxide",
93 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
94 state_class=SensorStateClass.MEASUREMENT,
95 value=
lambda data: data.get(
"clo2"),
99 translation_key=
"carbon_monoxide",
100 native_unit_of_measurement=CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
101 state_class=SensorStateClass.MEASUREMENT,
102 value=
lambda data: data.get(
"co"),
106 device_class=SensorDeviceClass.CO2,
107 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
108 state_class=SensorStateClass.MEASUREMENT,
109 value=
lambda data: data.get(
"co2"),
113 translation_key=
"carbon_disulfide",
114 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
115 state_class=SensorStateClass.MEASUREMENT,
116 value=
lambda data: data.get(
"cs2"),
120 translation_key=
"dew_point",
121 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
122 state_class=SensorStateClass.MEASUREMENT,
123 value=
lambda data: data.get(
"dewpt"),
124 device_class=SensorDeviceClass.TEMPERATURE,
128 translation_key=
"ethanol",
129 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
130 state_class=SensorStateClass.MEASUREMENT,
131 value=
lambda data: data.get(
"ethanol"),
135 translation_key=
"ethylene",
136 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
137 state_class=SensorStateClass.MEASUREMENT,
138 value=
lambda data: data.get(
"c2h4"),
142 translation_key=
"formaldehyde",
143 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
144 state_class=SensorStateClass.MEASUREMENT,
145 value=
lambda data: data.get(
"ch2o_M10"),
149 translation_key=
"fluorine",
150 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
151 state_class=SensorStateClass.MEASUREMENT,
152 value=
lambda data: data.get(
"f2"),
156 translation_key=
"hydrogen_sulfide",
157 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
158 state_class=SensorStateClass.MEASUREMENT,
159 value=
lambda data: data.get(
"h2s"),
163 translation_key=
"hydrochloric_acid",
164 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
165 state_class=SensorStateClass.MEASUREMENT,
166 value=
lambda data: data.get(
"hcl"),
170 translation_key=
"hydrogen_cyanide",
171 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
172 state_class=SensorStateClass.MEASUREMENT,
173 value=
lambda data: data.get(
"hcn"),
177 translation_key=
"hydrogen_fluoride",
178 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
179 state_class=SensorStateClass.MEASUREMENT,
180 value=
lambda data: data.get(
"hf"),
184 translation_key=
"health_index",
185 native_unit_of_measurement=PERCENTAGE,
186 state_class=SensorStateClass.MEASUREMENT,
187 value=
lambda data: data.get(
"health", 0.0) / 10.0,
191 device_class=SensorDeviceClass.HUMIDITY,
192 native_unit_of_measurement=PERCENTAGE,
193 state_class=SensorStateClass.MEASUREMENT,
194 value=
lambda data: data.get(
"humidity"),
198 translation_key=
"absolute_humidity",
199 native_unit_of_measurement=CONCENTRATION_GRAMS_PER_CUBIC_METER,
200 state_class=SensorStateClass.MEASUREMENT,
201 value=
lambda data: data.get(
"humidity_abs"),
205 translation_key=
"hydrogen",
206 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
207 state_class=SensorStateClass.MEASUREMENT,
208 value=
lambda data: data.get(
"h2_M1000"),
212 translation_key=
"hydrogen_peroxide",
213 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
214 state_class=SensorStateClass.MEASUREMENT,
215 value=
lambda data: data.get(
"h2o2"),
219 translation_key=
"methane",
220 native_unit_of_measurement=PERCENTAGE,
221 state_class=SensorStateClass.MEASUREMENT,
222 value=
lambda data: data.get(
"ch4_MIPEX"),
226 device_class=SensorDeviceClass.NITROUS_OXIDE,
227 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
228 state_class=SensorStateClass.MEASUREMENT,
229 value=
lambda data: data.get(
"n2o"),
233 device_class=SensorDeviceClass.NITROGEN_MONOXIDE,
234 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
235 state_class=SensorStateClass.MEASUREMENT,
236 value=
lambda data: data.get(
"no_M250"),
240 device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
241 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
242 state_class=SensorStateClass.MEASUREMENT,
243 value=
lambda data: data.get(
"no2"),
247 translation_key=
"organic_acid",
248 native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
249 state_class=SensorStateClass.MEASUREMENT,
250 value=
lambda data: data.get(
"acid_M100"),
254 translation_key=
"oxygen",
255 native_unit_of_measurement=PERCENTAGE,
256 state_class=SensorStateClass.MEASUREMENT,
257 value=
lambda data: data.get(
"oxygen"),
261 device_class=SensorDeviceClass.OZONE,
262 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
263 state_class=SensorStateClass.MEASUREMENT,
264 value=
lambda data: data.get(
"o3"),
268 translation_key=
"performance_index",
269 native_unit_of_measurement=PERCENTAGE,
270 state_class=SensorStateClass.MEASUREMENT,
271 value=
lambda data: data.get(
"performance", 0.0) / 10.0,
275 translation_key=
"hydrogen_phosphide",
276 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
277 state_class=SensorStateClass.MEASUREMENT,
278 value=
lambda data: data.get(
"ph3"),
282 device_class=SensorDeviceClass.PM1,
283 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
284 state_class=SensorStateClass.MEASUREMENT,
285 value=
lambda data: data.get(
"pm1"),
289 device_class=SensorDeviceClass.PM25,
290 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
291 state_class=SensorStateClass.MEASUREMENT,
292 value=
lambda data: data.get(
"pm2_5"),
296 device_class=SensorDeviceClass.PM10,
297 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
298 state_class=SensorStateClass.MEASUREMENT,
299 value=
lambda data: data.get(
"pm10"),
303 device_class=SensorDeviceClass.PRESSURE,
304 native_unit_of_measurement=UnitOfPressure.HPA,
305 state_class=SensorStateClass.MEASUREMENT,
306 value=
lambda data: data.get(
"pressure"),
310 translation_key=
"relative_pressure",
311 native_unit_of_measurement=UnitOfPressure.HPA,
312 state_class=SensorStateClass.MEASUREMENT,
313 value=
lambda data: data.get(
"pressure_rel"),
314 device_class=SensorDeviceClass.PRESSURE,
318 translation_key=
"propane",
319 native_unit_of_measurement=PERCENTAGE,
320 state_class=SensorStateClass.MEASUREMENT,
321 value=
lambda data: data.get(
"c3h8_MIPEX"),
325 translation_key=
"refigerant",
326 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
327 state_class=SensorStateClass.MEASUREMENT,
328 value=
lambda data: data.get(
"refigerant"),
332 translation_key=
"silicon_hydride",
333 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
334 state_class=SensorStateClass.MEASUREMENT,
335 value=
lambda data: data.get(
"sih4"),
339 device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
340 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
341 state_class=SensorStateClass.MEASUREMENT,
342 value=
lambda data: data.get(
"so2"),
346 translation_key=
"noise",
347 native_unit_of_measurement=UnitOfSoundPressure.WEIGHTED_DECIBEL_A,
348 state_class=SensorStateClass.MEASUREMENT,
349 value=
lambda data: data.get(
"sound"),
350 device_class=SensorDeviceClass.SOUND_PRESSURE,
354 translation_key=
"maximum_noise",
355 native_unit_of_measurement=UnitOfSoundPressure.WEIGHTED_DECIBEL_A,
356 state_class=SensorStateClass.MEASUREMENT,
357 value=
lambda data: data.get(
"sound_max"),
358 device_class=SensorDeviceClass.SOUND_PRESSURE,
362 translation_key=
"radon",
363 native_unit_of_measurement=ACTIVITY_BECQUEREL_PER_CUBIC_METER,
364 state_class=SensorStateClass.MEASUREMENT,
365 value=
lambda data: data.get(
"radon"),
369 device_class=SensorDeviceClass.TEMPERATURE,
370 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
371 state_class=SensorStateClass.MEASUREMENT,
372 value=
lambda data: data.get(
"temperature"),
376 device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
377 native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
378 state_class=SensorStateClass.MEASUREMENT,
379 value=
lambda data: data.get(
"tvoc"),
383 translation_key=
"industrial_volatile_organic_compounds",
384 device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
385 native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
386 state_class=SensorStateClass.MEASUREMENT,
387 value=
lambda data: data.get(
"tvoc_ionsc"),
391 translation_key=
"virus_index",
392 native_unit_of_measurement=PERCENTAGE,
393 state_class=SensorStateClass.MEASUREMENT,
394 value=
lambda data: data.get(
"virus", 0.0),
401 entry: AirQConfigEntry,
402 async_add_entities: AddEntitiesCallback,
404 """Set up sensor entities based on a config entry."""
406 coordinator = entry.runtime_data
408 entities: list[AirQSensor] = []
410 device_status: dict[str, str] | Literal[
"OK"] = coordinator.data[
"Status"]
412 for description
in SENSOR_TYPES:
413 if description.key
not in coordinator.data:
416 )
and "sensor still in warm up phase" in device_status.get(
417 description.key,
"OK"
421 _LOGGER.debug(
"Following sensor is warming up: %s", description.key)
424 entities.append(
AirQSensor(coordinator, description))
430 """Representation of a Sensor."""
432 _attr_has_entity_name =
True
436 coordinator: AirQCoordinator,
437 description: AirQEntityDescription,
439 """Initialize a single sensor."""
441 self.entity_description: AirQEntityDescription = description
449 """Handle updated data from the coordinator."""
450 self.
_attr_native_value_attr_native_value = self.entity_description.value(self.coordinator.data)
None _handle_coordinator_update(self)
None __init__(self, AirQCoordinator coordinator, AirQEntityDescription description)
None async_write_ha_state(self)
None async_setup_entry(HomeAssistant hass, AirQConfigEntry entry, AddEntitiesCallback async_add_entities)