1 """Support for the Airly sensor service."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
12 SensorEntityDescription,
16 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
27 from .
import AirlyConfigEntry, AirlyDataUpdateCoordinator
32 ATTR_API_CAQI_DESCRIPTION,
59 @dataclass(frozen=True)
61 """Class describing Airly sensor entities."""
63 attrs: Callable[[dict[str, Any]], dict[str, Any]] =
lambda data: {}
66 SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
69 translation_key=
"caqi",
70 native_unit_of_measurement=
"CAQI",
71 suggested_display_precision=0,
73 ATTR_LEVEL: data[ATTR_API_CAQI_LEVEL],
74 ATTR_ADVICE: data[ATTR_API_ADVICE],
75 ATTR_DESCRIPTION: data[ATTR_API_CAQI_DESCRIPTION],
80 device_class=SensorDeviceClass.PM1,
81 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
82 state_class=SensorStateClass.MEASUREMENT,
83 suggested_display_precision=0,
87 device_class=SensorDeviceClass.PM25,
88 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
89 state_class=SensorStateClass.MEASUREMENT,
90 suggested_display_precision=0,
92 ATTR_LIMIT: data[f
"{ATTR_API_PM25}_{SUFFIX_LIMIT}"],
93 ATTR_PERCENT: round(data[f
"{ATTR_API_PM25}_{SUFFIX_PERCENT}"]),
98 device_class=SensorDeviceClass.PM10,
99 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
100 state_class=SensorStateClass.MEASUREMENT,
101 suggested_display_precision=0,
103 ATTR_LIMIT: data[f
"{ATTR_API_PM10}_{SUFFIX_LIMIT}"],
104 ATTR_PERCENT: round(data[f
"{ATTR_API_PM10}_{SUFFIX_PERCENT}"]),
108 key=ATTR_API_HUMIDITY,
109 device_class=SensorDeviceClass.HUMIDITY,
110 native_unit_of_measurement=PERCENTAGE,
111 state_class=SensorStateClass.MEASUREMENT,
112 suggested_display_precision=1,
115 key=ATTR_API_PRESSURE,
116 device_class=SensorDeviceClass.PRESSURE,
117 native_unit_of_measurement=UnitOfPressure.HPA,
118 state_class=SensorStateClass.MEASUREMENT,
119 suggested_display_precision=0,
122 key=ATTR_API_TEMPERATURE,
123 device_class=SensorDeviceClass.TEMPERATURE,
124 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
125 state_class=SensorStateClass.MEASUREMENT,
126 suggested_display_precision=1,
130 translation_key=
"co",
131 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
132 state_class=SensorStateClass.MEASUREMENT,
133 suggested_display_precision=0,
135 ATTR_LIMIT: data[f
"{ATTR_API_CO}_{SUFFIX_LIMIT}"],
136 ATTR_PERCENT: round(data[f
"{ATTR_API_CO}_{SUFFIX_PERCENT}"]),
141 device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
142 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
143 state_class=SensorStateClass.MEASUREMENT,
144 suggested_display_precision=0,
146 ATTR_LIMIT: data[f
"{ATTR_API_NO2}_{SUFFIX_LIMIT}"],
147 ATTR_PERCENT: round(data[f
"{ATTR_API_NO2}_{SUFFIX_PERCENT}"]),
152 device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
153 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
154 state_class=SensorStateClass.MEASUREMENT,
155 suggested_display_precision=0,
157 ATTR_LIMIT: data[f
"{ATTR_API_SO2}_{SUFFIX_LIMIT}"],
158 ATTR_PERCENT: round(data[f
"{ATTR_API_SO2}_{SUFFIX_PERCENT}"]),
163 device_class=SensorDeviceClass.OZONE,
164 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
165 state_class=SensorStateClass.MEASUREMENT,
166 suggested_display_precision=0,
168 ATTR_LIMIT: data[f
"{ATTR_API_O3}_{SUFFIX_LIMIT}"],
169 ATTR_PERCENT: round(data[f
"{ATTR_API_O3}_{SUFFIX_PERCENT}"]),
177 entry: AirlyConfigEntry,
178 async_add_entities: AddEntitiesCallback,
180 """Set up Airly sensor entities based on a config entry."""
181 name = entry.data[CONF_NAME]
183 coordinator = entry.runtime_data
188 for description
in SENSOR_TYPES
190 if coordinator.data.get(description.key)
197 """Define an Airly sensor."""
199 _attr_attribution = ATTRIBUTION
200 _attr_has_entity_name =
True
201 entity_description: AirlySensorEntityDescription
205 coordinator: AirlyDataUpdateCoordinator,
207 description: AirlySensorEntityDescription,
212 entry_type=DeviceEntryType.SERVICE,
213 identifiers={(DOMAIN, f
"{coordinator.latitude}-{coordinator.longitude}")},
214 manufacturer=MANUFACTURER,
216 configuration_url=URL.format(
217 latitude=coordinator.latitude, longitude=coordinator.longitude
221 f
"{coordinator.latitude}-{coordinator.longitude}-{description.key}".lower()
229 """Handle updated data from the coordinator."""
232 self.coordinator.data
None __init__(self, AirlyDataUpdateCoordinator coordinator, str name, AirlySensorEntityDescription description)
_attr_extra_state_attributes
None _handle_coordinator_update(self)
None async_write_ha_state(self)
None async_setup_entry(HomeAssistant hass, AirlyConfigEntry entry, AddEntitiesCallback async_add_entities)