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:
parent
d58151034c
commit
648e649718
3 changed files with 328 additions and 341 deletions
|
@ -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,
|
||||
),
|
||||
)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue