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

View file

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

View file

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