1 """Support for the AirNow sensor service."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
9 from dateutil
import parser
14 SensorEntityDescription,
19 CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
20 CONCENTRATION_PARTS_PER_MILLION,
28 from .
import AirNowConfigEntry, AirNowDataUpdateCoordinator
31 ATTR_API_AQI_DESCRIPTION,
40 ATTR_API_STATION_LATITUDE,
41 ATTR_API_STATION_LONGITUDE,
47 ATTRIBUTION =
"Data provided by AirNow"
51 ATTR_DESCR =
"description"
53 ATTR_STATION =
"reporting_station"
56 @dataclass(frozen=True, kw_only=True)
58 """Describes Airnow sensor entity."""
60 value_fn: Callable[[Any], StateType]
61 extra_state_attributes_fn: Callable[[Any], dict[str, str]] |
None
65 """Process extra attributes for station location (if available)."""
66 if ATTR_API_STATION
in data:
68 "lat": data.get(ATTR_API_STATION_LATITUDE),
69 "long": data.get(ATTR_API_STATION_LONGITUDE),
75 """Process extra attributes for main AQI sensor."""
77 ATTR_DESCR: data[ATTR_API_AQI_DESCRIPTION],
78 ATTR_LEVEL: data[ATTR_API_AQI_LEVEL],
79 ATTR_TIME: parser.parse(
80 f
"{data[ATTR_API_REPORT_DATE]} {data[ATTR_API_REPORT_HOUR]}:00 {data[ATTR_API_REPORT_TZ]}",
81 tzinfos=US_TZ_OFFSETS,
86 SENSOR_TYPES: tuple[AirNowEntityDescription, ...] = (
89 translation_key=
"aqi",
90 state_class=SensorStateClass.MEASUREMENT,
91 device_class=SensorDeviceClass.AQI,
92 value_fn=
lambda data: data.get(ATTR_API_AQI),
93 extra_state_attributes_fn=aqi_extra_attrs,
97 translation_key=
"pm10",
98 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
99 state_class=SensorStateClass.MEASUREMENT,
100 device_class=SensorDeviceClass.PM10,
101 value_fn=
lambda data: data.get(ATTR_API_PM10),
102 extra_state_attributes_fn=
None,
106 translation_key=
"pm25",
107 native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
108 state_class=SensorStateClass.MEASUREMENT,
109 device_class=SensorDeviceClass.PM25,
110 value_fn=
lambda data: data.get(ATTR_API_PM25),
111 extra_state_attributes_fn=
None,
115 translation_key=
"o3",
116 native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
117 state_class=SensorStateClass.MEASUREMENT,
118 value_fn=
lambda data: data.get(ATTR_API_O3),
119 extra_state_attributes_fn=
None,
122 key=ATTR_API_STATION,
123 translation_key=
"station",
124 value_fn=
lambda data: data.get(ATTR_API_STATION),
125 extra_state_attributes_fn=station_extra_attrs,
132 config_entry: AirNowConfigEntry,
133 async_add_entities: AddEntitiesCallback,
135 """Set up AirNow sensor entities based on a config entry."""
136 coordinator = config_entry.runtime_data
138 entities = [
AirNowSensor(coordinator, description)
for description
in SENSOR_TYPES]
144 """Define an AirNow sensor."""
146 _attr_attribution = ATTRIBUTION
147 _attr_has_entity_name =
True
149 entity_description: AirNowEntityDescription
153 coordinator: AirNowDataUpdateCoordinator,
154 description: AirNowEntityDescription,
159 _device_id = f
"{coordinator.latitude}-{coordinator.longitude}"
164 entry_type=DeviceEntryType.SERVICE,
165 identifiers={(DOMAIN, _device_id)},
166 manufacturer=DEFAULT_NAME,
172 """Return the state."""
177 """Return the state attributes."""
180 self.coordinator.data
None __init__(self, AirNowDataUpdateCoordinator coordinator, AirNowEntityDescription description)
dict[str, str]|None extra_state_attributes(self)
StateType native_value(self)
dict[str, Any] station_extra_attrs(dict[str, Any] data)
None async_setup_entry(HomeAssistant hass, AirNowConfigEntry config_entry, AddEntitiesCallback async_add_entities)
dict[str, Any] aqi_extra_attrs(dict[str, Any] data)