Use SensorEntityDescription in AccuWeather integration (#53604)

* Use SensorEntityDescription

* Add missing type for entity_description

* Use tuples instead of lists

* Suggested change
This commit is contained in:
Maciej Bieniek 2021-07-28 10:26:14 +02:00 committed by GitHub
parent d58151034c
commit 648e649718
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 328 additions and 341 deletions

View File

@ -3,7 +3,7 @@ from __future__ import annotations
from typing import Final from typing import Final
from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
from homeassistant.components.weather import ( from homeassistant.components.weather import (
ATTR_CONDITION_CLEAR_NIGHT, ATTR_CONDITION_CLEAR_NIGHT,
ATTR_CONDITION_CLOUDY, ATTR_CONDITION_CLOUDY,
@ -21,8 +21,6 @@ from homeassistant.components.weather import (
ATTR_CONDITION_WINDY, ATTR_CONDITION_WINDY,
) )
from homeassistant.const import ( from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_ICON,
CONCENTRATION_PARTS_PER_CUBIC_METER, CONCENTRATION_PARTS_PER_CUBIC_METER,
DEVICE_CLASS_TEMPERATURE, DEVICE_CLASS_TEMPERATURE,
LENGTH_FEET, LENGTH_FEET,
@ -38,16 +36,12 @@ from homeassistant.const import (
UV_INDEX, UV_INDEX,
) )
from .model import SensorDescription from .model import AccuWeatherSensorDescription
API_IMPERIAL: Final = "Imperial" API_IMPERIAL: Final = "Imperial"
API_METRIC: Final = "Metric" API_METRIC: Final = "Metric"
ATTRIBUTION: Final = "Data provided by AccuWeather" ATTRIBUTION: Final = "Data provided by AccuWeather"
ATTR_ENABLED: Final = "enabled"
ATTR_FORECAST: Final = "forecast" ATTR_FORECAST: Final = "forecast"
ATTR_LABEL: Final = "label"
ATTR_UNIT_IMPERIAL: Final = "unit_imperial"
ATTR_UNIT_METRIC: Final = "unit_metric"
CONF_FORECAST: Final = "forecast" CONF_FORECAST: Final = "forecast"
DOMAIN: Final = "accuweather" DOMAIN: Final = "accuweather"
MANUFACTURER: Final = "AccuWeather, Inc." MANUFACTURER: Final = "AccuWeather, Inc."
@ -71,276 +65,263 @@ CONDITION_CLASSES: Final[dict[str, list[int]]] = {
ATTR_CONDITION_WINDY: [32], ATTR_CONDITION_WINDY: [32],
} }
FORECAST_SENSOR_TYPES: Final[dict[str, SensorDescription]] = { FORECAST_SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
"CloudCoverDay": { AccuWeatherSensorDescription(
ATTR_DEVICE_CLASS: None, key="CloudCoverDay",
ATTR_ICON: "mdi:weather-cloudy", icon="mdi:weather-cloudy",
ATTR_LABEL: "Cloud Cover Day", name="Cloud Cover Day",
ATTR_UNIT_METRIC: PERCENTAGE, unit_metric=PERCENTAGE,
ATTR_UNIT_IMPERIAL: PERCENTAGE, unit_imperial=PERCENTAGE,
ATTR_ENABLED: False, entity_registry_enabled_default=False,
}, ),
"CloudCoverNight": { AccuWeatherSensorDescription(
ATTR_DEVICE_CLASS: None, key="CloudCoverNight",
ATTR_ICON: "mdi:weather-cloudy", icon="mdi:weather-cloudy",
ATTR_LABEL: "Cloud Cover Night", name="Cloud Cover Night",
ATTR_UNIT_METRIC: PERCENTAGE, unit_metric=PERCENTAGE,
ATTR_UNIT_IMPERIAL: PERCENTAGE, unit_imperial=PERCENTAGE,
ATTR_ENABLED: False, entity_registry_enabled_default=False,
}, ),
"Grass": { AccuWeatherSensorDescription(
ATTR_DEVICE_CLASS: None, key="Grass",
ATTR_ICON: "mdi:grass", icon="mdi:grass",
ATTR_LABEL: "Grass Pollen", name="Grass Pollen",
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER, unit_metric=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER, unit_imperial=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_ENABLED: False, entity_registry_enabled_default=False,
}, ),
"HoursOfSun": { AccuWeatherSensorDescription(
ATTR_DEVICE_CLASS: None, key="HoursOfSun",
ATTR_ICON: "mdi:weather-partly-cloudy", icon="mdi:weather-partly-cloudy",
ATTR_LABEL: "Hours Of Sun", name="Hours Of Sun",
ATTR_UNIT_METRIC: TIME_HOURS, unit_metric=TIME_HOURS,
ATTR_UNIT_IMPERIAL: TIME_HOURS, unit_imperial=TIME_HOURS,
ATTR_ENABLED: True, ),
}, AccuWeatherSensorDescription(
"Mold": { key="Mold",
ATTR_DEVICE_CLASS: None, icon="mdi:blur",
ATTR_ICON: "mdi:blur", name="Mold Pollen",
ATTR_LABEL: "Mold Pollen", unit_metric=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER, unit_imperial=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER, entity_registry_enabled_default=False,
ATTR_ENABLED: False, ),
}, AccuWeatherSensorDescription(
"Ozone": { key="Ozone",
ATTR_DEVICE_CLASS: None, icon="mdi:vector-triangle",
ATTR_ICON: "mdi:vector-triangle", name="Ozone",
ATTR_LABEL: "Ozone", unit_metric=None,
ATTR_UNIT_METRIC: None, unit_imperial=None,
ATTR_UNIT_IMPERIAL: None, entity_registry_enabled_default=False,
ATTR_ENABLED: False, ),
}, AccuWeatherSensorDescription(
"Ragweed": { key="Ragweed",
ATTR_DEVICE_CLASS: None, icon="mdi:sprout",
ATTR_ICON: "mdi:sprout", name="Ragweed Pollen",
ATTR_LABEL: "Ragweed Pollen", unit_metric=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER, unit_imperial=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER, entity_registry_enabled_default=False,
ATTR_ENABLED: False, ),
}, AccuWeatherSensorDescription(
"RealFeelTemperatureMax": { key="RealFeelTemperatureMax",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_ICON: None, name="RealFeel Temperature Max",
ATTR_LABEL: "RealFeel Temperature Max", unit_metric=TEMP_CELSIUS,
ATTR_UNIT_METRIC: TEMP_CELSIUS, unit_imperial=TEMP_FAHRENHEIT,
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, ),
ATTR_ENABLED: True, AccuWeatherSensorDescription(
}, key="RealFeelTemperatureMin",
"RealFeelTemperatureMin": { device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, name="RealFeel Temperature Min",
ATTR_ICON: None, unit_metric=TEMP_CELSIUS,
ATTR_LABEL: "RealFeel Temperature Min", unit_imperial=TEMP_FAHRENHEIT,
ATTR_UNIT_METRIC: TEMP_CELSIUS, ),
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, AccuWeatherSensorDescription(
ATTR_ENABLED: True, key="RealFeelTemperatureShadeMax",
}, device_class=DEVICE_CLASS_TEMPERATURE,
"RealFeelTemperatureShadeMax": { name="RealFeel Temperature Shade Max",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, unit_metric=TEMP_CELSIUS,
ATTR_ICON: None, unit_imperial=TEMP_FAHRENHEIT,
ATTR_LABEL: "RealFeel Temperature Shade Max", entity_registry_enabled_default=False,
ATTR_UNIT_METRIC: TEMP_CELSIUS, ),
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, AccuWeatherSensorDescription(
ATTR_ENABLED: False, key="RealFeelTemperatureShadeMin",
}, device_class=DEVICE_CLASS_TEMPERATURE,
"RealFeelTemperatureShadeMin": { name="RealFeel Temperature Shade Min",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, unit_metric=TEMP_CELSIUS,
ATTR_ICON: None, unit_imperial=TEMP_FAHRENHEIT,
ATTR_LABEL: "RealFeel Temperature Shade Min", entity_registry_enabled_default=False,
ATTR_UNIT_METRIC: TEMP_CELSIUS, ),
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, AccuWeatherSensorDescription(
ATTR_ENABLED: False, key="ThunderstormProbabilityDay",
}, icon="mdi:weather-lightning",
"ThunderstormProbabilityDay": { name="Thunderstorm Probability Day",
ATTR_DEVICE_CLASS: None, unit_metric=PERCENTAGE,
ATTR_ICON: "mdi:weather-lightning", unit_imperial=PERCENTAGE,
ATTR_LABEL: "Thunderstorm Probability Day", ),
ATTR_UNIT_METRIC: PERCENTAGE, AccuWeatherSensorDescription(
ATTR_UNIT_IMPERIAL: PERCENTAGE, key="ThunderstormProbabilityNight",
ATTR_ENABLED: True, icon="mdi:weather-lightning",
}, name="Thunderstorm Probability Night",
"ThunderstormProbabilityNight": { unit_metric=PERCENTAGE,
ATTR_DEVICE_CLASS: None, unit_imperial=PERCENTAGE,
ATTR_ICON: "mdi:weather-lightning", ),
ATTR_LABEL: "Thunderstorm Probability Night", AccuWeatherSensorDescription(
ATTR_UNIT_METRIC: PERCENTAGE, key="Tree",
ATTR_UNIT_IMPERIAL: PERCENTAGE, icon="mdi:tree-outline",
ATTR_ENABLED: True, name="Tree Pollen",
}, unit_metric=CONCENTRATION_PARTS_PER_CUBIC_METER,
"Tree": { unit_imperial=CONCENTRATION_PARTS_PER_CUBIC_METER,
ATTR_DEVICE_CLASS: None, entity_registry_enabled_default=False,
ATTR_ICON: "mdi:tree-outline", ),
ATTR_LABEL: "Tree Pollen", AccuWeatherSensorDescription(
ATTR_UNIT_METRIC: CONCENTRATION_PARTS_PER_CUBIC_METER, key="UVIndex",
ATTR_UNIT_IMPERIAL: CONCENTRATION_PARTS_PER_CUBIC_METER, icon="mdi:weather-sunny",
ATTR_ENABLED: False, name="UV Index",
}, unit_metric=UV_INDEX,
"UVIndex": { unit_imperial=UV_INDEX,
ATTR_DEVICE_CLASS: None, ),
ATTR_ICON: "mdi:weather-sunny", AccuWeatherSensorDescription(
ATTR_LABEL: "UV Index", key="WindGustDay",
ATTR_UNIT_METRIC: UV_INDEX, icon="mdi:weather-windy",
ATTR_UNIT_IMPERIAL: UV_INDEX, name="Wind Gust Day",
ATTR_ENABLED: True, unit_metric=SPEED_KILOMETERS_PER_HOUR,
}, unit_imperial=SPEED_MILES_PER_HOUR,
"WindGustDay": { entity_registry_enabled_default=False,
ATTR_DEVICE_CLASS: None, ),
ATTR_ICON: "mdi:weather-windy", AccuWeatherSensorDescription(
ATTR_LABEL: "Wind Gust Day", key="WindGustNight",
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR, icon="mdi:weather-windy",
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR, name="Wind Gust Night",
ATTR_ENABLED: False, unit_metric=SPEED_KILOMETERS_PER_HOUR,
}, unit_imperial=SPEED_MILES_PER_HOUR,
"WindGustNight": { entity_registry_enabled_default=False,
ATTR_DEVICE_CLASS: None, ),
ATTR_ICON: "mdi:weather-windy", AccuWeatherSensorDescription(
ATTR_LABEL: "Wind Gust Night", key="WindDay",
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR, icon="mdi:weather-windy",
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR, name="Wind Day",
ATTR_ENABLED: False, unit_metric=SPEED_KILOMETERS_PER_HOUR,
}, unit_imperial=SPEED_MILES_PER_HOUR,
"WindDay": { ),
ATTR_DEVICE_CLASS: None, AccuWeatherSensorDescription(
ATTR_ICON: "mdi:weather-windy", key="WindNight",
ATTR_LABEL: "Wind Day", icon="mdi:weather-windy",
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR, name="Wind Night",
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR, unit_metric=SPEED_KILOMETERS_PER_HOUR,
ATTR_ENABLED: True, unit_imperial=SPEED_MILES_PER_HOUR,
}, ),
"WindNight": { )
ATTR_DEVICE_CLASS: None,
ATTR_ICON: "mdi:weather-windy",
ATTR_LABEL: "Wind Night",
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR,
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR,
ATTR_ENABLED: True,
},
}
SENSOR_TYPES: Final[dict[str, SensorDescription]] = { SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
"ApparentTemperature": { AccuWeatherSensorDescription(
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, key="ApparentTemperature",
ATTR_ICON: None, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_LABEL: "Apparent Temperature", name="Apparent Temperature",
ATTR_UNIT_METRIC: TEMP_CELSIUS, unit_metric=TEMP_CELSIUS,
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, unit_imperial=TEMP_FAHRENHEIT,
ATTR_ENABLED: False, entity_registry_enabled_default=False,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, state_class=STATE_CLASS_MEASUREMENT,
}, ),
"Ceiling": { AccuWeatherSensorDescription(
ATTR_DEVICE_CLASS: None, key="Ceiling",
ATTR_ICON: "mdi:weather-fog", icon="mdi:weather-fog",
ATTR_LABEL: "Cloud Ceiling", name="Cloud Ceiling",
ATTR_UNIT_METRIC: LENGTH_METERS, unit_metric=LENGTH_METERS,
ATTR_UNIT_IMPERIAL: LENGTH_FEET, unit_imperial=LENGTH_FEET,
ATTR_ENABLED: True, state_class=STATE_CLASS_MEASUREMENT,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, ),
}, AccuWeatherSensorDescription(
"CloudCover": { key="CloudCover",
ATTR_DEVICE_CLASS: None, icon="mdi:weather-cloudy",
ATTR_ICON: "mdi:weather-cloudy", name="Cloud Cover",
ATTR_LABEL: "Cloud Cover", unit_metric=PERCENTAGE,
ATTR_UNIT_METRIC: PERCENTAGE, unit_imperial=PERCENTAGE,
ATTR_UNIT_IMPERIAL: PERCENTAGE, entity_registry_enabled_default=False,
ATTR_ENABLED: False, state_class=STATE_CLASS_MEASUREMENT,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, ),
}, AccuWeatherSensorDescription(
"DewPoint": { key="DewPoint",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_ICON: None, name="Dew Point",
ATTR_LABEL: "Dew Point", unit_metric=TEMP_CELSIUS,
ATTR_UNIT_METRIC: TEMP_CELSIUS, unit_imperial=TEMP_FAHRENHEIT,
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, entity_registry_enabled_default=False,
ATTR_ENABLED: False, state_class=STATE_CLASS_MEASUREMENT,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, ),
}, AccuWeatherSensorDescription(
"RealFeelTemperature": { key="RealFeelTemperature",
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_ICON: None, name="RealFeel Temperature",
ATTR_LABEL: "RealFeel Temperature", unit_metric=TEMP_CELSIUS,
ATTR_UNIT_METRIC: TEMP_CELSIUS, unit_imperial=TEMP_FAHRENHEIT,
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, state_class=STATE_CLASS_MEASUREMENT,
ATTR_ENABLED: True, ),
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, AccuWeatherSensorDescription(
}, key="RealFeelTemperatureShade",
"RealFeelTemperatureShade": { device_class=DEVICE_CLASS_TEMPERATURE,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, name="RealFeel Temperature Shade",
ATTR_ICON: None, unit_metric=TEMP_CELSIUS,
ATTR_LABEL: "RealFeel Temperature Shade", unit_imperial=TEMP_FAHRENHEIT,
ATTR_UNIT_METRIC: TEMP_CELSIUS, entity_registry_enabled_default=False,
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, state_class=STATE_CLASS_MEASUREMENT,
ATTR_ENABLED: False, ),
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, AccuWeatherSensorDescription(
}, key="Precipitation",
"Precipitation": { icon="mdi:weather-rainy",
ATTR_DEVICE_CLASS: None, name="Precipitation",
ATTR_ICON: "mdi:weather-rainy", unit_metric=LENGTH_MILLIMETERS,
ATTR_LABEL: "Precipitation", unit_imperial=LENGTH_INCHES,
ATTR_UNIT_METRIC: LENGTH_MILLIMETERS, state_class=STATE_CLASS_MEASUREMENT,
ATTR_UNIT_IMPERIAL: LENGTH_INCHES, ),
ATTR_ENABLED: True, AccuWeatherSensorDescription(
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, key="PressureTendency",
}, device_class="accuweather__pressure_tendency",
"PressureTendency": { icon="mdi:gauge",
ATTR_DEVICE_CLASS: "accuweather__pressure_tendency", name="Pressure Tendency",
ATTR_ICON: "mdi:gauge", unit_metric=None,
ATTR_LABEL: "Pressure Tendency", unit_imperial=None,
ATTR_UNIT_METRIC: None, ),
ATTR_UNIT_IMPERIAL: None, AccuWeatherSensorDescription(
ATTR_ENABLED: True, key="UVIndex",
}, icon="mdi:weather-sunny",
"UVIndex": { name="UV Index",
ATTR_DEVICE_CLASS: None, unit_metric=UV_INDEX,
ATTR_ICON: "mdi:weather-sunny", unit_imperial=UV_INDEX,
ATTR_LABEL: "UV Index", state_class=STATE_CLASS_MEASUREMENT,
ATTR_UNIT_METRIC: UV_INDEX, ),
ATTR_UNIT_IMPERIAL: UV_INDEX, AccuWeatherSensorDescription(
ATTR_ENABLED: True, key="WetBulbTemperature",
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, device_class=DEVICE_CLASS_TEMPERATURE,
}, name="Wet Bulb Temperature",
"WetBulbTemperature": { unit_metric=TEMP_CELSIUS,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, unit_imperial=TEMP_FAHRENHEIT,
ATTR_ICON: None, entity_registry_enabled_default=False,
ATTR_LABEL: "Wet Bulb Temperature", state_class=STATE_CLASS_MEASUREMENT,
ATTR_UNIT_METRIC: TEMP_CELSIUS, ),
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, AccuWeatherSensorDescription(
ATTR_ENABLED: False, key="WindChillTemperature",
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, device_class=DEVICE_CLASS_TEMPERATURE,
}, name="Wind Chill Temperature",
"WindChillTemperature": { unit_metric=TEMP_CELSIUS,
ATTR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, unit_imperial=TEMP_FAHRENHEIT,
ATTR_ICON: None, entity_registry_enabled_default=False,
ATTR_LABEL: "Wind Chill Temperature", state_class=STATE_CLASS_MEASUREMENT,
ATTR_UNIT_METRIC: TEMP_CELSIUS, ),
ATTR_UNIT_IMPERIAL: TEMP_FAHRENHEIT, AccuWeatherSensorDescription(
ATTR_ENABLED: False, key="Wind",
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, icon="mdi:weather-windy",
}, name="Wind",
"Wind": { unit_metric=SPEED_KILOMETERS_PER_HOUR,
ATTR_DEVICE_CLASS: None, unit_imperial=SPEED_MILES_PER_HOUR,
ATTR_ICON: "mdi:weather-windy", state_class=STATE_CLASS_MEASUREMENT,
ATTR_LABEL: "Wind", ),
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR, AccuWeatherSensorDescription(
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR, key="WindGust",
ATTR_ENABLED: True, icon="mdi:weather-windy",
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT, name="Wind Gust",
}, unit_metric=SPEED_KILOMETERS_PER_HOUR,
"WindGust": { unit_imperial=SPEED_MILES_PER_HOUR,
ATTR_DEVICE_CLASS: None, entity_registry_enabled_default=False,
ATTR_ICON: "mdi:weather-windy", state_class=STATE_CLASS_MEASUREMENT,
ATTR_LABEL: "Wind Gust", ),
ATTR_UNIT_METRIC: SPEED_KILOMETERS_PER_HOUR, )
ATTR_UNIT_IMPERIAL: SPEED_MILES_PER_HOUR,
ATTR_ENABLED: False,
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
},
}

View File

@ -1,16 +1,14 @@
"""Type definitions for AccuWeather integration.""" """Type definitions for AccuWeather integration."""
from __future__ import annotations from __future__ import annotations
from typing import TypedDict from dataclasses import dataclass
from homeassistant.components.sensor import SensorEntityDescription
class SensorDescription(TypedDict, total=False): @dataclass
"""Sensor description class.""" class AccuWeatherSensorDescription(SensorEntityDescription):
"""Class describing AccuWeather sensor entities."""
device_class: str | None unit_metric: str | None = None
icon: str | None unit_imperial: str | None = None
label: str
unit_metric: str | None
unit_imperial: str | None
enabled: bool
state_class: str | None

View File

@ -3,15 +3,9 @@ from __future__ import annotations
from typing import Any, cast from typing import Any, cast
from homeassistant.components.sensor import ATTR_STATE_CLASS, SensorEntity from homeassistant.components.sensor import SensorEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.const import ( from homeassistant.const import ATTR_ATTRIBUTION, CONF_NAME, DEVICE_CLASS_TEMPERATURE
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
ATTR_ICON,
CONF_NAME,
DEVICE_CLASS_TEMPERATURE,
)
from homeassistant.core import HomeAssistant, callback from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType from homeassistant.helpers.typing import StateType
@ -21,11 +15,7 @@ from . import AccuWeatherDataUpdateCoordinator
from .const import ( from .const import (
API_IMPERIAL, API_IMPERIAL,
API_METRIC, API_METRIC,
ATTR_ENABLED,
ATTR_FORECAST, ATTR_FORECAST,
ATTR_LABEL,
ATTR_UNIT_IMPERIAL,
ATTR_UNIT_METRIC,
ATTRIBUTION, ATTRIBUTION,
DOMAIN, DOMAIN,
FORECAST_SENSOR_TYPES, FORECAST_SENSOR_TYPES,
@ -34,6 +24,7 @@ from .const import (
NAME, NAME,
SENSOR_TYPES, SENSOR_TYPES,
) )
from .model import AccuWeatherSensorDescription
PARALLEL_UPDATES = 1 PARALLEL_UPDATES = 1
@ -47,17 +38,19 @@ async def async_setup_entry(
coordinator: AccuWeatherDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id] coordinator: AccuWeatherDataUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
sensors: list[AccuWeatherSensor] = [] sensors: list[AccuWeatherSensor] = []
for sensor in SENSOR_TYPES: for description in SENSOR_TYPES:
sensors.append(AccuWeatherSensor(name, sensor, coordinator)) sensors.append(AccuWeatherSensor(name, coordinator, description))
if coordinator.forecast: if coordinator.forecast:
for sensor in FORECAST_SENSOR_TYPES: for description in FORECAST_SENSOR_TYPES:
for day in range(MAX_FORECAST_DAYS + 1): for day in range(MAX_FORECAST_DAYS + 1):
# Some air quality/allergy sensors are only available for certain # Some air quality/allergy sensors are only available for certain
# locations. # locations.
if sensor in coordinator.data[ATTR_FORECAST][0]: if description.key in coordinator.data[ATTR_FORECAST][0]:
sensors.append( sensors.append(
AccuWeatherSensor(name, sensor, coordinator, forecast_day=day) AccuWeatherSensor(
name, coordinator, description, forecast_day=day
)
) )
async_add_entities(sensors) async_add_entities(sensors)
@ -67,69 +60,72 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
"""Define an AccuWeather entity.""" """Define an AccuWeather entity."""
coordinator: AccuWeatherDataUpdateCoordinator coordinator: AccuWeatherDataUpdateCoordinator
entity_description: AccuWeatherSensorDescription
def __init__( def __init__(
self, self,
name: str, name: str,
kind: str,
coordinator: AccuWeatherDataUpdateCoordinator, coordinator: AccuWeatherDataUpdateCoordinator,
description: AccuWeatherSensorDescription,
forecast_day: int | None = None, forecast_day: int | None = None,
) -> None: ) -> None:
"""Initialize.""" """Initialize."""
super().__init__(coordinator) super().__init__(coordinator)
self._sensor_data = _get_sensor_data(coordinator.data, forecast_day, kind) self.entity_description = description
if forecast_day is None: self._sensor_data = _get_sensor_data(
self._description = SENSOR_TYPES[kind] coordinator.data, forecast_day, description.key
else: )
self._description = FORECAST_SENSOR_TYPES[kind]
self._unit_system = API_METRIC if coordinator.is_metric else API_IMPERIAL
self.kind = kind
self._attrs = {ATTR_ATTRIBUTION: ATTRIBUTION} self._attrs = {ATTR_ATTRIBUTION: ATTRIBUTION}
self.forecast_day = forecast_day if forecast_day is not None:
self._attr_state_class = self._description.get(ATTR_STATE_CLASS) self._attr_name = f"{name} {description.name} {forecast_day}d"
self._attr_icon = self._description[ATTR_ICON]
self._attr_device_class = self._description[ATTR_DEVICE_CLASS]
self._attr_entity_registry_enabled_default = self._description[ATTR_ENABLED]
if self.forecast_day is not None:
self._attr_name = f"{name} {self._description[ATTR_LABEL]} {forecast_day}d"
self._attr_unique_id = ( self._attr_unique_id = (
f"{coordinator.location_key}-{kind}-{forecast_day}".lower() f"{coordinator.location_key}-{description.key}-{forecast_day}".lower()
) )
else: else:
self._attr_name = f"{name} {self._description[ATTR_LABEL]}" self._attr_name = f"{name} {description.name}"
self._attr_unique_id = f"{coordinator.location_key}-{kind}".lower() self._attr_unique_id = (
f"{coordinator.location_key}-{description.key}".lower()
)
if coordinator.is_metric: if coordinator.is_metric:
self._attr_unit_of_measurement = self._description[ATTR_UNIT_METRIC] self._unit_system = API_METRIC
self._attr_unit_of_measurement = description.unit_metric
else: else:
self._attr_unit_of_measurement = self._description[ATTR_UNIT_IMPERIAL] self._unit_system = API_IMPERIAL
self._attr_unit_of_measurement = description.unit_imperial
self._attr_device_info = { self._attr_device_info = {
"identifiers": {(DOMAIN, coordinator.location_key)}, "identifiers": {(DOMAIN, coordinator.location_key)},
"name": NAME, "name": NAME,
"manufacturer": MANUFACTURER, "manufacturer": MANUFACTURER,
"entry_type": "service", "entry_type": "service",
} }
self.forecast_day = forecast_day
@property @property
def state(self) -> StateType: def state(self) -> StateType:
"""Return the state.""" """Return the state."""
if self.forecast_day is not None: if self.forecast_day is not None:
if self._description["device_class"] == DEVICE_CLASS_TEMPERATURE: if self.entity_description.device_class == DEVICE_CLASS_TEMPERATURE:
return cast(float, self._sensor_data["Value"]) return cast(float, self._sensor_data["Value"])
if self.kind == "UVIndex": if self.entity_description.key == "UVIndex":
return cast(int, self._sensor_data["Value"]) return cast(int, self._sensor_data["Value"])
if self.kind in ["Grass", "Mold", "Ragweed", "Tree", "Ozone"]: if self.entity_description.key in ("Grass", "Mold", "Ragweed", "Tree", "Ozone"):
return cast(int, self._sensor_data["Value"]) return cast(int, self._sensor_data["Value"])
if self.kind == "Ceiling": if self.entity_description.key == "Ceiling":
return round(self._sensor_data[self._unit_system]["Value"]) return round(self._sensor_data[self._unit_system]["Value"])
if self.kind == "PressureTendency": if self.entity_description.key == "PressureTendency":
return cast(str, self._sensor_data["LocalizedText"].lower()) return cast(str, self._sensor_data["LocalizedText"].lower())
if self._description["device_class"] == DEVICE_CLASS_TEMPERATURE: if self.entity_description.device_class == DEVICE_CLASS_TEMPERATURE:
return cast(float, self._sensor_data[self._unit_system]["Value"]) return cast(float, self._sensor_data[self._unit_system]["Value"])
if self.kind == "Precipitation": if self.entity_description.key == "Precipitation":
return cast(float, self._sensor_data[self._unit_system]["Value"]) return cast(float, self._sensor_data[self._unit_system]["Value"])
if self.kind in ["Wind", "WindGust"]: if self.entity_description.key in ("Wind", "WindGust"):
return cast(float, self._sensor_data["Speed"][self._unit_system]["Value"]) return cast(float, self._sensor_data["Speed"][self._unit_system]["Value"])
if self.kind in ["WindDay", "WindNight", "WindGustDay", "WindGustNight"]: if self.entity_description.key in (
"WindDay",
"WindNight",
"WindGustDay",
"WindGustNight",
):
return cast(StateType, self._sensor_data["Speed"]["Value"]) return cast(StateType, self._sensor_data["Speed"]["Value"])
return cast(StateType, self._sensor_data) return cast(StateType, self._sensor_data)
@ -137,14 +133,26 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
def extra_state_attributes(self) -> dict[str, Any]: def extra_state_attributes(self) -> dict[str, Any]:
"""Return the state attributes.""" """Return the state attributes."""
if self.forecast_day is not None: if self.forecast_day is not None:
if self.kind in ["WindDay", "WindNight", "WindGustDay", "WindGustNight"]: if self.entity_description.key in (
"WindDay",
"WindNight",
"WindGustDay",
"WindGustNight",
):
self._attrs["direction"] = self._sensor_data["Direction"]["English"] self._attrs["direction"] = self._sensor_data["Direction"]["English"]
elif self.kind in ["Grass", "Mold", "Ragweed", "Tree", "UVIndex", "Ozone"]: elif self.entity_description.key in (
"Grass",
"Mold",
"Ozone",
"Ragweed",
"Tree",
"UVIndex",
):
self._attrs["level"] = self._sensor_data["Category"] self._attrs["level"] = self._sensor_data["Category"]
return self._attrs return self._attrs
if self.kind == "UVIndex": if self.entity_description.key == "UVIndex":
self._attrs["level"] = self.coordinator.data["UVIndexText"] self._attrs["level"] = self.coordinator.data["UVIndexText"]
elif self.kind == "Precipitation": elif self.entity_description.key == "Precipitation":
self._attrs["type"] = self.coordinator.data["PrecipitationType"] self._attrs["type"] = self.coordinator.data["PrecipitationType"]
return self._attrs return self._attrs
@ -152,7 +160,7 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
def _handle_coordinator_update(self) -> None: def _handle_coordinator_update(self) -> None:
"""Handle data update.""" """Handle data update."""
self._sensor_data = _get_sensor_data( self._sensor_data = _get_sensor_data(
self.coordinator.data, self.forecast_day, self.kind self.coordinator.data, self.forecast_day, self.entity_description.key
) )
self.async_write_ha_state() self.async_write_ha_state()