From 05de7a78d1c87b7bcdce9dbba7d89aa4ec7db3d3 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Sat, 21 Aug 2021 20:32:40 +0200 Subject: [PATCH] Use EntityDescription - trafikverket_weatherstation (#54430) --- .../trafikverket_weatherstation/sensor.py | 235 +++++++++--------- 1 file changed, 119 insertions(+), 116 deletions(-) diff --git a/homeassistant/components/trafikverket_weatherstation/sensor.py b/homeassistant/components/trafikverket_weatherstation/sensor.py index 1435da6a988..5fe3c462a56 100644 --- a/homeassistant/components/trafikverket_weatherstation/sensor.py +++ b/homeassistant/components/trafikverket_weatherstation/sensor.py @@ -1,6 +1,8 @@ """Weather information for air and road temperature (by Trafikverket).""" +from __future__ import annotations import asyncio +from dataclasses import dataclass from datetime import timedelta import logging @@ -8,7 +10,11 @@ import aiohttp from pytrafikverket.trafikverket_weather import TrafikverketWeather import voluptuous as vol -from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity +from homeassistant.components.sensor import ( + PLATFORM_SCHEMA, + SensorEntity, + SensorEntityDescription, +) from homeassistant.const import ( ATTR_ATTRIBUTION, CONF_API_KEY, @@ -38,85 +44,102 @@ MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=10) SCAN_INTERVAL = timedelta(seconds=300) -SENSOR_TYPES = { - "air_temp": [ - "Air temperature", - TEMP_CELSIUS, - "air_temp", - "mdi:thermometer", - DEVICE_CLASS_TEMPERATURE, - ], - "road_temp": [ - "Road temperature", - TEMP_CELSIUS, - "road_temp", - "mdi:thermometer", - DEVICE_CLASS_TEMPERATURE, - ], - "precipitation": [ - "Precipitation type", - None, - "precipitationtype", - "mdi:weather-snowy-rainy", - None, - ], - "wind_direction": [ - "Wind direction", - DEGREE, - "winddirection", - "mdi:flag-triangle", - None, - ], - "wind_direction_text": [ - "Wind direction text", - None, - "winddirectiontext", - "mdi:flag-triangle", - None, - ], - "wind_speed": [ - "Wind speed", - SPEED_METERS_PER_SECOND, - "windforce", - "mdi:weather-windy", - None, - ], - "wind_speed_max": [ - "Wind speed max", - SPEED_METERS_PER_SECOND, - "windforcemax", - "mdi:weather-windy-variant", - None, - ], - "humidity": [ - "Humidity", - PERCENTAGE, - "humidity", - "mdi:water-percent", - DEVICE_CLASS_HUMIDITY, - ], - "precipitation_amount": [ - "Precipitation amount", - LENGTH_MILLIMETERS, - "precipitation_amount", - "mdi:cup-water", - None, - ], - "precipitation_amountname": [ - "Precipitation name", - None, - "precipitation_amountname", - "mdi:weather-pouring", - None, - ], -} + +@dataclass +class TrafikverketRequiredKeysMixin: + """Mixin for required keys.""" + + api_key: str + + +@dataclass +class TrafikverketSensorEntityDescription( + SensorEntityDescription, TrafikverketRequiredKeysMixin +): + """Describes Trafikverket sensor entity.""" + + +SENSOR_TYPES: tuple[TrafikverketSensorEntityDescription, ...] = ( + TrafikverketSensorEntityDescription( + key="air_temp", + api_key="air_temp", + name="Air temperature", + native_unit_of_measurement=TEMP_CELSIUS, + icon="mdi:thermometer", + device_class=DEVICE_CLASS_TEMPERATURE, + ), + TrafikverketSensorEntityDescription( + key="road_temp", + api_key="road_temp", + name="Road temperature", + native_unit_of_measurement=TEMP_CELSIUS, + icon="mdi:thermometer", + device_class=DEVICE_CLASS_TEMPERATURE, + ), + TrafikverketSensorEntityDescription( + key="precipitation", + api_key="precipitationtype", + name="Precipitation type", + icon="mdi:weather-snowy-rainy", + ), + TrafikverketSensorEntityDescription( + key="wind_direction", + api_key="winddirection", + name="Wind direction", + native_unit_of_measurement=DEGREE, + icon="mdi:flag-triangle", + ), + TrafikverketSensorEntityDescription( + key="wind_direction_text", + api_key="winddirectiontext", + name="Wind direction text", + icon="mdi:flag-triangle", + ), + TrafikverketSensorEntityDescription( + key="wind_speed", + api_key="windforce", + name="Wind speed", + native_unit_of_measurement=SPEED_METERS_PER_SECOND, + icon="mdi:weather-windy", + ), + TrafikverketSensorEntityDescription( + key="wind_speed_max", + api_key="windforcemax", + name="Wind speed max", + native_unit_of_measurement=SPEED_METERS_PER_SECOND, + icon="mdi:weather-windy-variant", + ), + TrafikverketSensorEntityDescription( + key="humidity", + api_key="humidity", + name="Humidity", + native_unit_of_measurement=PERCENTAGE, + icon="mdi:water-percent", + device_class=DEVICE_CLASS_HUMIDITY, + ), + TrafikverketSensorEntityDescription( + key="precipitation_amount", + api_key="precipitation_amount", + name="Precipitation amount", + native_unit_of_measurement=LENGTH_MILLIMETERS, + icon="mdi:cup-water", + ), + TrafikverketSensorEntityDescription( + key="precipitation_amountname", + api_key="precipitation_amountname", + name="Precipitation name", + icon="mdi:weather-pouring", + ), +) + +SENSOR_KEYS = [desc.key for desc in SENSOR_TYPES] PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( { vol.Required(CONF_NAME): cv.string, vol.Required(CONF_API_KEY): cv.string, vol.Required(CONF_STATION): cv.string, - vol.Required(CONF_MONITORED_CONDITIONS, default=[]): [vol.In(SENSOR_TYPES)], + vol.Required(CONF_MONITORED_CONDITIONS, default=[]): [vol.In(SENSOR_KEYS)], } ) @@ -132,44 +155,37 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info= weather_api = TrafikverketWeather(web_session, sensor_api) - dev = [] - for condition in config[CONF_MONITORED_CONDITIONS]: - dev.append( - TrafikverketWeatherStation( - weather_api, sensor_name, condition, sensor_station - ) + monitored_conditions = config[CONF_MONITORED_CONDITIONS] + entities = [ + TrafikverketWeatherStation( + weather_api, sensor_name, sensor_station, description ) + for description in SENSOR_TYPES + if description.key in monitored_conditions + ] - if dev: - async_add_entities(dev, True) + async_add_entities(entities, True) class TrafikverketWeatherStation(SensorEntity): """Representation of a Trafikverket sensor.""" - def __init__(self, weather_api, name, sensor_type, sensor_station): + entity_description: TrafikverketSensorEntityDescription + + def __init__( + self, + weather_api, + name, + sensor_station, + description: TrafikverketSensorEntityDescription, + ): """Initialize the sensor.""" - self._client = name - self._name = SENSOR_TYPES[sensor_type][0] - self._type = sensor_type - self._state = None - self._unit = SENSOR_TYPES[sensor_type][1] + self.entity_description = description + self._attr_name = f"{name} {description.name}" self._station = sensor_station self._weather_api = weather_api - self._icon = SENSOR_TYPES[sensor_type][3] - self._device_class = SENSOR_TYPES[sensor_type][4] self._weather = None - @property - def name(self): - """Return the name of the sensor.""" - return f"{self._client} {self._name}" - - @property - def icon(self): - """Icon to use in the frontend.""" - return self._icon - @property def extra_state_attributes(self): """Return the state attributes of Trafikverket Weatherstation.""" @@ -179,26 +195,13 @@ class TrafikverketWeatherStation(SensorEntity): ATTR_MEASURE_TIME: self._weather.measure_time, } - @property - def device_class(self): - """Return the device class of the sensor.""" - return self._device_class - - @property - def native_value(self): - """Return the state of the device.""" - return self._state - - @property - def native_unit_of_measurement(self): - """Return the unit of measurement of this entity, if any.""" - return self._unit - @Throttle(MIN_TIME_BETWEEN_UPDATES) async def async_update(self): """Get the latest data from Trafikverket and updates the states.""" try: self._weather = await self._weather_api.async_get_weather(self._station) - self._state = getattr(self._weather, SENSOR_TYPES[self._type][2]) + self._attr_native_value = getattr( + self._weather, self.entity_description.api_key + ) except (asyncio.TimeoutError, aiohttp.ClientError, ValueError) as error: _LOGGER.error("Could not fetch weather data: %s", error)