diff --git a/homeassistant/components/aemet/const.py b/homeassistant/components/aemet/const.py index 0927f64dd2a..e84060b444d 100644 --- a/homeassistant/components/aemet/const.py +++ b/homeassistant/components/aemet/const.py @@ -1,5 +1,7 @@ """Constant values for the AEMET OpenData component.""" +from __future__ import annotations +from homeassistant.components.sensor import SensorEntityDescription from homeassistant.components.weather import ( ATTR_CONDITION_CLEAR_NIGHT, ATTR_CONDITION_CLOUDY, @@ -40,9 +42,6 @@ DEFAULT_NAME = "AEMET" DOMAIN = "aemet" ENTRY_NAME = "name" ENTRY_WEATHER_COORDINATOR = "weather_coordinator" -SENSOR_NAME = "sensor_name" -SENSOR_UNIT = "sensor_unit" -SENSOR_DEVICE_CLASS = "sensor_device_class" ATTR_API_CONDITION = "condition" ATTR_API_FORECAST_DAILY = "forecast-daily" @@ -200,118 +199,145 @@ FORECAST_MODE_ATTR_API = { FORECAST_MODE_HOURLY: ATTR_API_FORECAST_HOURLY, } -FORECAST_SENSOR_TYPES = { - ATTR_FORECAST_CONDITION: { - SENSOR_NAME: "Condition", - }, - ATTR_FORECAST_PRECIPITATION: { - SENSOR_NAME: "Precipitation", - SENSOR_UNIT: PRECIPITATION_MILLIMETERS_PER_HOUR, - }, - ATTR_FORECAST_PRECIPITATION_PROBABILITY: { - SENSOR_NAME: "Precipitation probability", - SENSOR_UNIT: PERCENTAGE, - }, - ATTR_FORECAST_TEMP: { - SENSOR_NAME: "Temperature", - SENSOR_UNIT: TEMP_CELSIUS, - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, - }, - ATTR_FORECAST_TEMP_LOW: { - SENSOR_NAME: "Temperature Low", - SENSOR_UNIT: TEMP_CELSIUS, - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, - }, - ATTR_FORECAST_TIME: { - SENSOR_NAME: "Time", - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TIMESTAMP, - }, - ATTR_FORECAST_WIND_BEARING: { - SENSOR_NAME: "Wind bearing", - SENSOR_UNIT: DEGREE, - }, - ATTR_FORECAST_WIND_SPEED: { - SENSOR_NAME: "Wind speed", - SENSOR_UNIT: SPEED_KILOMETERS_PER_HOUR, - }, -} -WEATHER_SENSOR_TYPES = { - ATTR_API_CONDITION: { - SENSOR_NAME: "Condition", - }, - ATTR_API_HUMIDITY: { - SENSOR_NAME: "Humidity", - SENSOR_UNIT: PERCENTAGE, - SENSOR_DEVICE_CLASS: DEVICE_CLASS_HUMIDITY, - }, - ATTR_API_PRESSURE: { - SENSOR_NAME: "Pressure", - SENSOR_UNIT: PRESSURE_HPA, - SENSOR_DEVICE_CLASS: DEVICE_CLASS_PRESSURE, - }, - ATTR_API_RAIN: { - SENSOR_NAME: "Rain", - SENSOR_UNIT: PRECIPITATION_MILLIMETERS_PER_HOUR, - }, - ATTR_API_RAIN_PROB: { - SENSOR_NAME: "Rain probability", - SENSOR_UNIT: PERCENTAGE, - }, - ATTR_API_SNOW: { - SENSOR_NAME: "Snow", - SENSOR_UNIT: PRECIPITATION_MILLIMETERS_PER_HOUR, - }, - ATTR_API_SNOW_PROB: { - SENSOR_NAME: "Snow probability", - SENSOR_UNIT: PERCENTAGE, - }, - ATTR_API_STATION_ID: { - SENSOR_NAME: "Station ID", - }, - ATTR_API_STATION_NAME: { - SENSOR_NAME: "Station name", - }, - ATTR_API_STATION_TIMESTAMP: { - SENSOR_NAME: "Station timestamp", - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TIMESTAMP, - }, - ATTR_API_STORM_PROB: { - SENSOR_NAME: "Storm probability", - SENSOR_UNIT: PERCENTAGE, - }, - ATTR_API_TEMPERATURE: { - SENSOR_NAME: "Temperature", - SENSOR_UNIT: TEMP_CELSIUS, - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, - }, - ATTR_API_TEMPERATURE_FEELING: { - SENSOR_NAME: "Temperature feeling", - SENSOR_UNIT: TEMP_CELSIUS, - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TEMPERATURE, - }, - ATTR_API_TOWN_ID: { - SENSOR_NAME: "Town ID", - }, - ATTR_API_TOWN_NAME: { - SENSOR_NAME: "Town name", - }, - ATTR_API_TOWN_TIMESTAMP: { - SENSOR_NAME: "Town timestamp", - SENSOR_DEVICE_CLASS: DEVICE_CLASS_TIMESTAMP, - }, - ATTR_API_WIND_BEARING: { - SENSOR_NAME: "Wind bearing", - SENSOR_UNIT: DEGREE, - }, - ATTR_API_WIND_MAX_SPEED: { - SENSOR_NAME: "Wind max speed", - SENSOR_UNIT: SPEED_KILOMETERS_PER_HOUR, - }, - ATTR_API_WIND_SPEED: { - SENSOR_NAME: "Wind speed", - SENSOR_UNIT: SPEED_KILOMETERS_PER_HOUR, - }, -} +FORECAST_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key=ATTR_FORECAST_CONDITION, + name="Condition", + ), + SensorEntityDescription( + key=ATTR_FORECAST_PRECIPITATION, + name="Precipitation", + native_unit_of_measurement=PRECIPITATION_MILLIMETERS_PER_HOUR, + ), + SensorEntityDescription( + key=ATTR_FORECAST_PRECIPITATION_PROBABILITY, + name="Precipitation probability", + native_unit_of_measurement=PERCENTAGE, + ), + SensorEntityDescription( + key=ATTR_FORECAST_TEMP, + name="Temperature", + native_unit_of_measurement=TEMP_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=ATTR_FORECAST_TEMP_LOW, + name="Temperature Low", + native_unit_of_measurement=TEMP_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=ATTR_FORECAST_TIME, + name="Time", + device_class=DEVICE_CLASS_TIMESTAMP, + ), + SensorEntityDescription( + key=ATTR_FORECAST_WIND_BEARING, + name="Wind bearing", + native_unit_of_measurement=DEGREE, + ), + SensorEntityDescription( + key=ATTR_FORECAST_WIND_SPEED, + name="Wind speed", + native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR, + ), +) +WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = ( + SensorEntityDescription( + key=ATTR_API_CONDITION, + name="Condition", + ), + SensorEntityDescription( + key=ATTR_API_HUMIDITY, + name="Humidity", + native_unit_of_measurement=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + SensorEntityDescription( + key=ATTR_API_PRESSURE, + name="Pressure", + native_unit_of_measurement=PRESSURE_HPA, + device_class=DEVICE_CLASS_PRESSURE, + ), + SensorEntityDescription( + key=ATTR_API_RAIN, + name="Rain", + native_unit_of_measurement=PRECIPITATION_MILLIMETERS_PER_HOUR, + ), + SensorEntityDescription( + key=ATTR_API_RAIN_PROB, + name="Rain probability", + native_unit_of_measurement=PERCENTAGE, + ), + SensorEntityDescription( + key=ATTR_API_SNOW, + name="Snow", + native_unit_of_measurement=PRECIPITATION_MILLIMETERS_PER_HOUR, + ), + SensorEntityDescription( + key=ATTR_API_SNOW_PROB, + name="Snow probability", + native_unit_of_measurement=PERCENTAGE, + ), + SensorEntityDescription( + key=ATTR_API_STATION_ID, + name="Station ID", + ), + SensorEntityDescription( + key=ATTR_API_STATION_NAME, + name="Station name", + ), + SensorEntityDescription( + key=ATTR_API_STATION_TIMESTAMP, + name="Station timestamp", + device_class=DEVICE_CLASS_TIMESTAMP, + ), + SensorEntityDescription( + key=ATTR_API_STORM_PROB, + name="Storm probability", + native_unit_of_measurement=PERCENTAGE, + ), + SensorEntityDescription( + key=ATTR_API_TEMPERATURE, + name="Temperature", + native_unit_of_measurement=TEMP_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=ATTR_API_TEMPERATURE_FEELING, + name="Temperature feeling", + native_unit_of_measurement=TEMP_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + SensorEntityDescription( + key=ATTR_API_TOWN_ID, + name="Town ID", + ), + SensorEntityDescription( + key=ATTR_API_TOWN_NAME, + name="Town name", + ), + SensorEntityDescription( + key=ATTR_API_TOWN_TIMESTAMP, + name="Town timestamp", + device_class=DEVICE_CLASS_TIMESTAMP, + ), + SensorEntityDescription( + key=ATTR_API_WIND_BEARING, + name="Wind bearing", + native_unit_of_measurement=DEGREE, + ), + SensorEntityDescription( + key=ATTR_API_WIND_MAX_SPEED, + name="Wind max speed", + native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR, + ), + SensorEntityDescription( + key=ATTR_API_WIND_SPEED, + name="Wind speed", + native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR, + ), +) WIND_BEARING_MAP = { "C": None, diff --git a/homeassistant/components/aemet/sensor.py b/homeassistant/components/aemet/sensor.py index 35336980e1a..685e9fb200b 100644 --- a/homeassistant/components/aemet/sensor.py +++ b/homeassistant/components/aemet/sensor.py @@ -1,5 +1,7 @@ """Support for the AEMET OpenData service.""" -from homeassistant.components.sensor import SensorEntity +from __future__ import annotations + +from homeassistant.components.sensor import SensorEntity, SensorEntityDescription from homeassistant.const import ATTR_ATTRIBUTION from homeassistant.helpers.update_coordinator import CoordinatorEntity @@ -14,9 +16,6 @@ from .const import ( FORECAST_MONITORED_CONDITIONS, FORECAST_SENSOR_TYPES, MONITORED_CONDITIONS, - SENSOR_DEVICE_CLASS, - SENSOR_NAME, - SENSOR_UNIT, WEATHER_SENSOR_TYPES, ) from .weather_update_coordinator import WeatherUpdateCoordinator @@ -28,37 +27,30 @@ async def async_setup_entry(hass, config_entry, async_add_entities): name = domain_data[ENTRY_NAME] weather_coordinator = domain_data[ENTRY_WEATHER_COORDINATOR] - weather_sensor_types = WEATHER_SENSOR_TYPES - forecast_sensor_types = FORECAST_SENSOR_TYPES - - entities = [] - for sensor_type in MONITORED_CONDITIONS: - unique_id = f"{config_entry.unique_id}-{sensor_type}" - entities.append( - AemetSensor( - name, - unique_id, - sensor_type, - weather_sensor_types[sensor_type], + unique_id = config_entry.unique_id + entities: list[AbstractAemetSensor] = [ + AemetSensor(name, unique_id, weather_coordinator, description) + for description in WEATHER_SENSOR_TYPES + if description.key in MONITORED_CONDITIONS + ] + entities.extend( + [ + AemetForecastSensor( + name_prefix, + unique_id_prefix, weather_coordinator, + mode, + description, ) - ) - - for mode in FORECAST_MODES: - name = f"{domain_data[ENTRY_NAME]} {mode}" - - for sensor_type in FORECAST_MONITORED_CONDITIONS: - unique_id = f"{config_entry.unique_id}-forecast-{mode}-{sensor_type}" - entities.append( - AemetForecastSensor( - f"{name} Forecast", - unique_id, - sensor_type, - forecast_sensor_types[sensor_type], - weather_coordinator, - mode, - ) + for mode in FORECAST_MODES + if ( + (name_prefix := f"{domain_data[ENTRY_NAME]} {mode} Forecast") + and (unique_id_prefix := f"{unique_id}-forecast-{mode}") ) + for description in FORECAST_SENSOR_TYPES + if description.key in FORECAST_MONITORED_CONDITIONS + ] + ) async_add_entities(entities) @@ -72,20 +64,14 @@ class AbstractAemetSensor(CoordinatorEntity, SensorEntity): self, name, unique_id, - sensor_type, - sensor_configuration, coordinator: WeatherUpdateCoordinator, + description: SensorEntityDescription, ): """Initialize the sensor.""" super().__init__(coordinator) - self._name = name - self._unique_id = unique_id - self._sensor_type = sensor_type - self._sensor_name = sensor_configuration[SENSOR_NAME] - self._attr_name = f"{self._name} {self._sensor_name}" - self._attr_unique_id = self._unique_id - self._attr_device_class = sensor_configuration.get(SENSOR_DEVICE_CLASS) - self._attr_native_unit_of_measurement = sensor_configuration.get(SENSOR_UNIT) + self.entity_description = description + self._attr_name = f"{name} {description.name}" + self._attr_unique_id = unique_id class AemetSensor(AbstractAemetSensor): @@ -95,20 +81,21 @@ class AemetSensor(AbstractAemetSensor): self, name, unique_id, - sensor_type, - sensor_configuration, weather_coordinator: WeatherUpdateCoordinator, + description: SensorEntityDescription, ): """Initialize the sensor.""" super().__init__( - name, unique_id, sensor_type, sensor_configuration, weather_coordinator + name=name, + unique_id=f"{unique_id}-{description.key}", + coordinator=weather_coordinator, + description=description, ) - self._weather_coordinator = weather_coordinator @property def native_value(self): """Return the state of the device.""" - return self._weather_coordinator.data.get(self._sensor_type) + return self.coordinator.data.get(self.entity_description.key) class AemetForecastSensor(AbstractAemetSensor): @@ -118,16 +105,17 @@ class AemetForecastSensor(AbstractAemetSensor): self, name, unique_id, - sensor_type, - sensor_configuration, weather_coordinator: WeatherUpdateCoordinator, forecast_mode, + description: SensorEntityDescription, ): """Initialize the sensor.""" super().__init__( - name, unique_id, sensor_type, sensor_configuration, weather_coordinator + name=name, + unique_id=f"{unique_id}-{description.key}", + coordinator=weather_coordinator, + description=description, ) - self._weather_coordinator = weather_coordinator self._forecast_mode = forecast_mode self._attr_entity_registry_enabled_default = ( self._forecast_mode == FORECAST_MODE_DAILY @@ -137,9 +125,9 @@ class AemetForecastSensor(AbstractAemetSensor): def native_value(self): """Return the state of the device.""" forecast = None - forecasts = self._weather_coordinator.data.get( + forecasts = self.coordinator.data.get( FORECAST_MODE_ATTR_API[self._forecast_mode] ) if forecasts: - forecast = forecasts[0].get(self._sensor_type) + forecast = forecasts[0].get(self.entity_description.key) return forecast