1 """Support for the AccuWeather service."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from typing
import Any, cast
12 SensorEntityDescription,
16 CONCENTRATION_PARTS_PER_CUBIC_METER,
42 from .coordinator
import (
43 AccuWeatherConfigEntry,
44 AccuWeatherDailyForecastDataUpdateCoordinator,
45 AccuWeatherObservationDataUpdateCoordinator,
51 @dataclass(frozen=True, kw_only=True)
53 """Class describing AccuWeather sensor entities."""
55 value_fn: Callable[[dict[str, Any]], str | int | float |
None]
56 attr_fn: Callable[[dict[str, Any]], dict[str, Any]] =
lambda _: {}
59 FORECAST_SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
62 value_fn=
lambda data: cast(str, data[ATTR_CATEGORY]),
63 device_class=SensorDeviceClass.ENUM,
64 options=[
"good",
"hazardous",
"high",
"low",
"moderate",
"unhealthy"],
65 translation_key=
"air_quality",
69 entity_registry_enabled_default=
False,
70 native_unit_of_measurement=PERCENTAGE,
71 value_fn=
lambda data: cast(int, data),
72 translation_key=
"cloud_cover_day",
75 key=
"CloudCoverNight",
76 entity_registry_enabled_default=
False,
77 native_unit_of_measurement=PERCENTAGE,
78 value_fn=
lambda data: cast(int, data),
79 translation_key=
"cloud_cover_night",
83 entity_registry_enabled_default=
False,
84 native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
85 value_fn=
lambda data: cast(int, data[ATTR_VALUE]),
86 attr_fn=
lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
87 translation_key=
"grass_pollen",
91 native_unit_of_measurement=UnitOfTime.HOURS,
92 value_fn=
lambda data: cast(float, data),
93 translation_key=
"hours_of_sun",
97 value_fn=
lambda data: cast(str, data),
98 translation_key=
"condition_day",
101 key=
"LongPhraseNight",
102 value_fn=
lambda data: cast(str, data),
103 translation_key=
"condition_night",
107 entity_registry_enabled_default=
False,
108 native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
109 value_fn=
lambda data: cast(int, data[ATTR_VALUE]),
110 attr_fn=
lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
111 translation_key=
"mold_pollen",
115 native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
116 entity_registry_enabled_default=
False,
117 value_fn=
lambda data: cast(int, data[ATTR_VALUE]),
118 attr_fn=
lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
119 translation_key=
"ragweed_pollen",
122 key=
"RealFeelTemperatureMax",
123 device_class=SensorDeviceClass.TEMPERATURE,
124 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
125 value_fn=
lambda data: cast(float, data[ATTR_VALUE]),
126 translation_key=
"realfeel_temperature_max",
129 key=
"RealFeelTemperatureMin",
130 device_class=SensorDeviceClass.TEMPERATURE,
131 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
132 value_fn=
lambda data: cast(float, data[ATTR_VALUE]),
133 translation_key=
"realfeel_temperature_min",
136 key=
"RealFeelTemperatureShadeMax",
137 device_class=SensorDeviceClass.TEMPERATURE,
138 entity_registry_enabled_default=
False,
139 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
140 value_fn=
lambda data: cast(float, data[ATTR_VALUE]),
141 translation_key=
"realfeel_temperature_shade_max",
144 key=
"RealFeelTemperatureShadeMin",
145 device_class=SensorDeviceClass.TEMPERATURE,
146 entity_registry_enabled_default=
False,
147 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
148 value_fn=
lambda data: cast(float, data[ATTR_VALUE]),
149 translation_key=
"realfeel_temperature_shade_min",
152 key=
"SolarIrradianceDay",
153 device_class=SensorDeviceClass.IRRADIANCE,
154 entity_registry_enabled_default=
False,
155 native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER,
156 value_fn=
lambda data: cast(float, data[ATTR_VALUE]),
157 translation_key=
"solar_irradiance_day",
160 key=
"SolarIrradianceNight",
161 device_class=SensorDeviceClass.IRRADIANCE,
162 entity_registry_enabled_default=
False,
163 native_unit_of_measurement=UnitOfIrradiance.WATTS_PER_SQUARE_METER,
164 value_fn=
lambda data: cast(float, data[ATTR_VALUE]),
165 translation_key=
"solar_irradiance_night",
168 key=
"ThunderstormProbabilityDay",
169 native_unit_of_measurement=PERCENTAGE,
170 value_fn=
lambda data: cast(int, data),
171 translation_key=
"thunderstorm_probability_day",
174 key=
"ThunderstormProbabilityNight",
175 native_unit_of_measurement=PERCENTAGE,
176 value_fn=
lambda data: cast(int, data),
177 translation_key=
"thunderstorm_probability_night",
181 native_unit_of_measurement=CONCENTRATION_PARTS_PER_CUBIC_METER,
182 entity_registry_enabled_default=
False,
183 value_fn=
lambda data: cast(int, data[ATTR_VALUE]),
184 attr_fn=
lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
185 translation_key=
"tree_pollen",
189 native_unit_of_measurement=UV_INDEX,
190 value_fn=
lambda data: cast(int, data[ATTR_VALUE]),
191 attr_fn=
lambda data: {ATTR_LEVEL: data[ATTR_CATEGORY]},
192 translation_key=
"uv_index_forecast",
196 device_class=SensorDeviceClass.WIND_SPEED,
197 entity_registry_enabled_default=
False,
198 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
199 value_fn=
lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
200 attr_fn=
lambda data: {
"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
201 translation_key=
"wind_gust_speed_day",
205 device_class=SensorDeviceClass.WIND_SPEED,
206 entity_registry_enabled_default=
False,
207 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
208 value_fn=
lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
209 attr_fn=
lambda data: {
"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
210 translation_key=
"wind_gust_speed_night",
214 device_class=SensorDeviceClass.WIND_SPEED,
215 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
216 value_fn=
lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
217 attr_fn=
lambda data: {
"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
218 translation_key=
"wind_speed_day",
222 device_class=SensorDeviceClass.WIND_SPEED,
223 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
224 value_fn=
lambda data: cast(float, data[ATTR_SPEED][ATTR_VALUE]),
225 attr_fn=
lambda data: {
"direction": data[ATTR_DIRECTION][ATTR_ENGLISH]},
226 translation_key=
"wind_speed_night",
230 SENSOR_TYPES: tuple[AccuWeatherSensorDescription, ...] = (
232 key=
"ApparentTemperature",
233 device_class=SensorDeviceClass.TEMPERATURE,
234 entity_registry_enabled_default=
False,
235 state_class=SensorStateClass.MEASUREMENT,
236 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
237 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
238 translation_key=
"apparent_temperature",
242 device_class=SensorDeviceClass.DISTANCE,
243 state_class=SensorStateClass.MEASUREMENT,
244 native_unit_of_measurement=UnitOfLength.METERS,
245 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
246 suggested_display_precision=0,
247 translation_key=
"cloud_ceiling",
251 entity_registry_enabled_default=
False,
252 state_class=SensorStateClass.MEASUREMENT,
253 native_unit_of_measurement=PERCENTAGE,
254 value_fn=
lambda data: cast(int, data),
255 translation_key=
"cloud_cover",
259 device_class=SensorDeviceClass.TEMPERATURE,
260 entity_registry_enabled_default=
False,
261 state_class=SensorStateClass.MEASUREMENT,
262 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
263 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
264 translation_key=
"dew_point",
267 key=
"RealFeelTemperature",
268 device_class=SensorDeviceClass.TEMPERATURE,
269 state_class=SensorStateClass.MEASUREMENT,
270 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
271 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
272 translation_key=
"realfeel_temperature",
275 key=
"RealFeelTemperatureShade",
276 device_class=SensorDeviceClass.TEMPERATURE,
277 entity_registry_enabled_default=
False,
278 state_class=SensorStateClass.MEASUREMENT,
279 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
280 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
281 translation_key=
"realfeel_temperature_shade",
284 key=
"RelativeHumidity",
285 device_class=SensorDeviceClass.HUMIDITY,
286 entity_registry_enabled_default=
False,
287 state_class=SensorStateClass.MEASUREMENT,
288 native_unit_of_measurement=PERCENTAGE,
289 value_fn=
lambda data: cast(int, data),
290 translation_key=
"humidity",
294 device_class=SensorDeviceClass.PRECIPITATION_INTENSITY,
295 state_class=SensorStateClass.MEASUREMENT,
296 native_unit_of_measurement=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
297 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
298 attr_fn=
lambda data: {
"type": data[
"PrecipitationType"]},
299 translation_key=
"precipitation",
303 device_class=SensorDeviceClass.PRESSURE,
304 entity_registry_enabled_default=
False,
305 state_class=SensorStateClass.MEASUREMENT,
306 suggested_display_precision=0,
307 native_unit_of_measurement=UnitOfPressure.HPA,
308 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
309 translation_key=
"pressure",
312 key=
"PressureTendency",
313 device_class=SensorDeviceClass.ENUM,
314 options=[
"falling",
"rising",
"steady"],
315 value_fn=
lambda data: cast(str, data[
"LocalizedText"]).lower(),
316 translation_key=
"pressure_tendency",
320 device_class=SensorDeviceClass.TEMPERATURE,
321 entity_registry_enabled_default=
False,
322 state_class=SensorStateClass.MEASUREMENT,
323 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
324 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
325 translation_key=
"temperature",
329 state_class=SensorStateClass.MEASUREMENT,
330 entity_registry_enabled_default=
False,
331 native_unit_of_measurement=UV_INDEX,
332 value_fn=
lambda data: cast(int, data),
333 attr_fn=
lambda data: {ATTR_LEVEL: data[
"UVIndexText"]},
334 translation_key=
"uv_index",
337 key=
"WetBulbTemperature",
338 device_class=SensorDeviceClass.TEMPERATURE,
339 entity_registry_enabled_default=
False,
340 state_class=SensorStateClass.MEASUREMENT,
341 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
342 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
343 translation_key=
"wet_bulb_temperature",
346 key=
"WindChillTemperature",
347 device_class=SensorDeviceClass.TEMPERATURE,
348 entity_registry_enabled_default=
False,
349 state_class=SensorStateClass.MEASUREMENT,
350 native_unit_of_measurement=UnitOfTemperature.CELSIUS,
351 value_fn=
lambda data: cast(float, data[API_METRIC][ATTR_VALUE]),
352 translation_key=
"wind_chill_temperature",
356 device_class=SensorDeviceClass.WIND_SPEED,
357 entity_registry_enabled_default=
False,
358 state_class=SensorStateClass.MEASUREMENT,
359 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
360 value_fn=
lambda data: cast(float, data[ATTR_SPEED][API_METRIC][ATTR_VALUE]),
361 translation_key=
"wind_speed",
365 device_class=SensorDeviceClass.WIND_SPEED,
366 entity_registry_enabled_default=
False,
367 state_class=SensorStateClass.MEASUREMENT,
368 native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
369 value_fn=
lambda data: cast(float, data[ATTR_SPEED][API_METRIC][ATTR_VALUE]),
370 translation_key=
"wind_gust_speed",
377 entry: AccuWeatherConfigEntry,
378 async_add_entities: AddEntitiesCallback,
380 """Add AccuWeather entities from a config_entry."""
381 observation_coordinator: AccuWeatherObservationDataUpdateCoordinator = (
382 entry.runtime_data.coordinator_observation
384 forecast_daily_coordinator: AccuWeatherDailyForecastDataUpdateCoordinator = (
385 entry.runtime_data.coordinator_daily_forecast
388 sensors: list[AccuWeatherSensor | AccuWeatherForecastSensor] = [
390 for description
in SENSOR_TYPES
396 for day
in range(MAX_FORECAST_DAYS + 1)
397 for description
in FORECAST_SENSOR_TYPES
398 if description.key
in forecast_daily_coordinator.data[day]
406 CoordinatorEntity[AccuWeatherObservationDataUpdateCoordinator], SensorEntity
408 """Define an AccuWeather entity."""
410 _attr_attribution = ATTRIBUTION
411 _attr_has_entity_name =
True
412 entity_description: AccuWeatherSensorDescription
416 coordinator: AccuWeatherObservationDataUpdateCoordinator,
417 description: AccuWeatherSensorDescription,
424 self.
_attr_unique_id_attr_unique_id = f
"{coordinator.location_key}-{description.key}".lower()
429 """Return the state."""
434 """Return the state attributes."""
439 """Handle data update."""
447 sensors: dict[str, Any],
450 """Get sensor data."""
451 if kind ==
"Precipitation":
452 return sensors[
"PrecipitationSummary"][
"PastHour"]
458 CoordinatorEntity[AccuWeatherDailyForecastDataUpdateCoordinator], SensorEntity
460 """Define an AccuWeather entity."""
462 _attr_attribution = ATTRIBUTION
463 _attr_has_entity_name =
True
464 entity_description: AccuWeatherSensorDescription
468 coordinator: AccuWeatherDailyForecastDataUpdateCoordinator,
469 description: AccuWeatherSensorDescription,
477 coordinator.data, description.key, forecast_day
480 f
"{coordinator.location_key}-{description.key}-{forecast_day}".lower()
488 """Return the state."""
493 """Return the state attributes."""
498 """Handle data update."""
506 sensors: list[dict[str, Any]],
510 """Get sensor data."""
511 return sensors[forecast_day][kind]
_attr_translation_placeholders
None _handle_coordinator_update(self)
None __init__(self, AccuWeatherDailyForecastDataUpdateCoordinator coordinator, AccuWeatherSensorDescription description, int forecast_day)
str|int|float|None native_value(self)
dict[str, Any] extra_state_attributes(self)
Any _get_sensor_data(list[dict[str, Any]] sensors, str kind, int forecast_day)
None _handle_coordinator_update(self)
None __init__(self, AccuWeatherObservationDataUpdateCoordinator coordinator, AccuWeatherSensorDescription description)
Any _get_sensor_data(dict[str, Any] sensors, str kind)
str|int|float|None native_value(self)
dict[str, Any] extra_state_attributes(self)
None async_write_ha_state(self)
None async_setup_entry(HomeAssistant hass, AccuWeatherConfigEntry entry, AddEntitiesCallback async_add_entities)