1 """Support for AirGradient sensors."""
3 from collections.abc
import Callable
4 from dataclasses
import dataclass
6 from airgradient
import Config
7 from airgradient.models
import (
17 SensorEntityDescription,
21 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
22 CONCENTRATION_PARTS_PER_MILLION,
24 SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
33 from .
import AirGradientConfigEntry
34 from .const
import PM_STANDARD, PM_STANDARD_REVERSE
35 from .coordinator
import AirGradientCoordinator
36 from .entity
import AirGradientEntity
39 @dataclass(frozen=True, kw_only=True)
41 """Describes AirGradient measurement sensor entity."""
43 value_fn: Callable[[Measures], StateType]
46 @dataclass(frozen=True, kw_only=True)
48 """Describes AirGradient config sensor entity."""
50 value_fn: Callable[[Config], StateType]
53 MEASUREMENT_SENSOR_TYPES: tuple[AirGradientMeasurementSensorEntityDescription, ...] = (
56 device_class=SensorDeviceClass.PM1,
57 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
58 state_class=SensorStateClass.MEASUREMENT,
59 value_fn=
lambda status: status.pm01,
63 device_class=SensorDeviceClass.PM25,
64 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
65 state_class=SensorStateClass.MEASUREMENT,
66 value_fn=
lambda status: status.pm02,
70 device_class=SensorDeviceClass.PM10,
71 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
72 state_class=SensorStateClass.MEASUREMENT,
73 value_fn=
lambda status: status.pm10,
77 device_class=SensorDeviceClass.TEMPERATURE,
78 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
79 state_class=SensorStateClass.MEASUREMENT,
80 value_fn=
lambda status: status.ambient_temperature,
84 device_class=SensorDeviceClass.HUMIDITY,
85 native_unit_of_measurement=PERCENTAGE,
86 state_class=SensorStateClass.MEASUREMENT,
87 value_fn=
lambda status: status.relative_humidity,
90 key=
"signal_strength",
91 device_class=SensorDeviceClass.SIGNAL_STRENGTH,
92 native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
93 entity_category=EntityCategory.DIAGNOSTIC,
94 state_class=SensorStateClass.MEASUREMENT,
95 entity_registry_enabled_default=
False,
96 value_fn=
lambda status: status.signal_strength,
100 translation_key=
"total_volatile_organic_component_index",
101 state_class=SensorStateClass.MEASUREMENT,
102 value_fn=
lambda status: status.total_volatile_organic_component_index,
105 key=
"nitrogen_index",
106 translation_key=
"nitrogen_index",
107 state_class=SensorStateClass.MEASUREMENT,
108 value_fn=
lambda status: status.nitrogen_index,
112 device_class=SensorDeviceClass.CO2,
113 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
114 state_class=SensorStateClass.MEASUREMENT,
115 value_fn=
lambda status: status.rco2,
119 translation_key=
"pm003_count",
120 native_unit_of_measurement=
"particles/dL",
121 state_class=SensorStateClass.MEASUREMENT,
122 value_fn=
lambda status: status.pm003_count,
126 translation_key=
"raw_nitrogen",
127 native_unit_of_measurement=
"ticks",
128 state_class=SensorStateClass.MEASUREMENT,
129 entity_registry_enabled_default=
False,
130 value_fn=
lambda status: status.raw_nitrogen,
134 translation_key=
"raw_total_volatile_organic_component",
135 native_unit_of_measurement=
"ticks",
136 state_class=SensorStateClass.MEASUREMENT,
137 entity_registry_enabled_default=
False,
138 value_fn=
lambda status: status.raw_total_volatile_organic_component,
142 CONFIG_SENSOR_TYPES: tuple[AirGradientConfigSensorEntityDescription, ...] = (
144 key=
"co2_automatic_baseline_calibration_days",
145 translation_key=
"co2_automatic_baseline_calibration_days",
146 device_class=SensorDeviceClass.DURATION,
147 native_unit_of_measurement=UnitOfTime.DAYS,
148 entity_category=EntityCategory.DIAGNOSTIC,
149 value_fn=
lambda config: config.co2_automatic_baseline_calibration_days,
152 key=
"nox_learning_offset",
153 translation_key=
"nox_learning_offset",
154 device_class=SensorDeviceClass.DURATION,
155 native_unit_of_measurement=UnitOfTime.DAYS,
156 entity_category=EntityCategory.DIAGNOSTIC,
157 value_fn=
lambda config: config.nox_learning_offset,
160 key=
"tvoc_learning_offset",
161 translation_key=
"tvoc_learning_offset",
162 device_class=SensorDeviceClass.DURATION,
163 native_unit_of_measurement=UnitOfTime.DAYS,
164 entity_category=EntityCategory.DIAGNOSTIC,
165 value_fn=
lambda config: config.tvoc_learning_offset,
169 CONFIG_LED_BAR_SENSOR_TYPES: tuple[AirGradientConfigSensorEntityDescription, ...] = (
172 translation_key=
"led_bar_mode",
173 device_class=SensorDeviceClass.ENUM,
174 options=[x.value
for x
in LedBarMode],
175 entity_category=EntityCategory.DIAGNOSTIC,
176 value_fn=
lambda config: config.led_bar_mode,
179 key=
"led_bar_brightness",
180 translation_key=
"led_bar_brightness",
181 native_unit_of_measurement=PERCENTAGE,
182 entity_category=EntityCategory.DIAGNOSTIC,
183 value_fn=
lambda config: config.led_bar_brightness,
187 CONFIG_DISPLAY_SENSOR_TYPES: tuple[AirGradientConfigSensorEntityDescription, ...] = (
189 key=
"display_temperature_unit",
190 translation_key=
"display_temperature_unit",
191 device_class=SensorDeviceClass.ENUM,
192 options=[x.value
for x
in TemperatureUnit],
193 entity_category=EntityCategory.DIAGNOSTIC,
194 value_fn=
lambda config: config.temperature_unit,
197 key=
"display_pm_standard",
198 translation_key=
"display_pm_standard",
199 device_class=SensorDeviceClass.ENUM,
200 options=
list(PM_STANDARD_REVERSE),
201 entity_category=EntityCategory.DIAGNOSTIC,
202 value_fn=
lambda config: PM_STANDARD.get(config.pm_standard),
205 key=
"display_brightness",
206 translation_key=
"display_brightness",
207 native_unit_of_measurement=PERCENTAGE,
208 entity_category=EntityCategory.DIAGNOSTIC,
209 value_fn=
lambda config: config.display_brightness,
216 entry: AirGradientConfigEntry,
217 async_add_entities: AddEntitiesCallback,
219 """Set up AirGradient sensor entities based on a config entry."""
221 coordinator = entry.runtime_data
222 listener: Callable[[],
None] |
None =
None
223 not_setup: set[AirGradientMeasurementSensorEntityDescription] = set(
224 MEASUREMENT_SENSOR_TYPES
229 """Add new entities based on the latest data."""
230 nonlocal not_setup, listener
231 sensor_descriptions = not_setup
234 for description
in sensor_descriptions:
235 if description.value_fn(coordinator.data.measures)
is None:
236 not_setup.add(description)
244 listener = coordinator.async_add_listener(add_entities)
252 for description
in CONFIG_SENSOR_TYPES
254 if "L" in coordinator.data.measures.model:
257 for description
in CONFIG_LED_BAR_SENSOR_TYPES
259 if "I" in coordinator.data.measures.model:
262 for description
in CONFIG_DISPLAY_SENSOR_TYPES
268 """Defines an AirGradient sensor."""
272 coordinator: AirGradientCoordinator,
273 description: SensorEntityDescription,
275 """Initialize airgradient sensor."""
278 self.
_attr_unique_id_attr_unique_id = f
"{coordinator.serial_number}-{description.key}"
282 """Defines an AirGradient sensor."""
284 entity_description: AirGradientMeasurementSensorEntityDescription
288 """Return the state of the sensor."""
293 """Defines an AirGradient sensor."""
295 entity_description: AirGradientConfigSensorEntityDescription
299 coordinator: AirGradientCoordinator,
300 description: AirGradientConfigSensorEntityDescription,
302 """Initialize airgradient sensor."""
303 super().
__init__(coordinator, description)
305 coordinator.data.config.configuration_control
306 is not ConfigurationControl.LOCAL
311 """Return the state of the sensor."""
_attr_entity_registry_enabled_default
StateType native_value(self)
None __init__(self, AirGradientCoordinator coordinator, AirGradientConfigSensorEntityDescription description)
StateType native_value(self)
None __init__(self, AirGradientCoordinator coordinator, SensorEntityDescription description)
None async_setup_entry(HomeAssistant hass, AirGradientConfigEntry entry, AddEntitiesCallback async_add_entities)
def add_entities(account, async_add_entities, tracked)