From f5480481cd29e7dd1db71a6be596abaa70288409 Mon Sep 17 00:00:00 2001 From: Marc Mueller <30130371+cdce8p@users.noreply.github.com> Date: Thu, 22 Jul 2021 07:25:38 +0200 Subject: [PATCH] Use NamedTuple - metoffice (#53294) --- homeassistant/components/metoffice/sensor.py | 195 ++++++++++++------- 1 file changed, 122 insertions(+), 73 deletions(-) diff --git a/homeassistant/components/metoffice/sensor.py b/homeassistant/components/metoffice/sensor.py index 6b45dac22e7..1307c3aae45 100644 --- a/homeassistant/components/metoffice/sensor.py +++ b/homeassistant/components/metoffice/sensor.py @@ -1,4 +1,8 @@ """Support for UK Met Office weather service.""" +from __future__ import annotations + +from typing import NamedTuple + from homeassistant.components.sensor import SensorEntity from homeassistant.const import ( ATTR_ATTRIBUTION, @@ -34,51 +38,102 @@ ATTR_SENSOR_ID = "sensor_id" ATTR_SITE_ID = "site_id" ATTR_SITE_NAME = "site_name" -# Sensor types are defined as: -# variable -> [0]title, [1]device_class, [2]units, [3]icon, [4]enabled_by_default + +class MetOfficeSensorMetadata(NamedTuple): + """Sensor metadata for an individual NWS sensor.""" + + title: str + device_class: str | None + unit_of_measurement: str | None + icon: str | None + enabled_by_default: bool + + SENSOR_TYPES = { - "name": ["Station Name", None, None, "mdi:label-outline", False], - "weather": [ + "name": MetOfficeSensorMetadata( + "Station Name", + device_class=None, + unit_of_measurement=None, + icon="mdi:label-outline", + enabled_by_default=False, + ), + "weather": MetOfficeSensorMetadata( "Weather", - None, - None, - "mdi:weather-sunny", # but will adapt to current conditions - True, - ], - "temperature": ["Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS, None, True], - "feels_like_temperature": [ + device_class=None, + unit_of_measurement=None, + icon="mdi:weather-sunny", # but will adapt to current conditions + enabled_by_default=True, + ), + "temperature": MetOfficeSensorMetadata( + "Temperature", + device_class=DEVICE_CLASS_TEMPERATURE, + unit_of_measurement=TEMP_CELSIUS, + icon=None, + enabled_by_default=True, + ), + "feels_like_temperature": MetOfficeSensorMetadata( "Feels Like Temperature", - DEVICE_CLASS_TEMPERATURE, - TEMP_CELSIUS, - None, - False, - ], - "wind_speed": [ + device_class=DEVICE_CLASS_TEMPERATURE, + unit_of_measurement=TEMP_CELSIUS, + icon=None, + enabled_by_default=False, + ), + "wind_speed": MetOfficeSensorMetadata( "Wind Speed", - None, - SPEED_MILES_PER_HOUR, - "mdi:weather-windy", - True, - ], - "wind_direction": ["Wind Direction", None, None, "mdi:compass-outline", False], - "wind_gust": ["Wind Gust", None, SPEED_MILES_PER_HOUR, "mdi:weather-windy", False], - "visibility": ["Visibility", None, None, "mdi:eye", False], - "visibility_distance": [ + device_class=None, + unit_of_measurement=SPEED_MILES_PER_HOUR, + icon="mdi:weather-windy", + enabled_by_default=True, + ), + "wind_direction": MetOfficeSensorMetadata( + "Wind Direction", + device_class=None, + unit_of_measurement=None, + icon="mdi:compass-outline", + enabled_by_default=False, + ), + "wind_gust": MetOfficeSensorMetadata( + "Wind Gust", + device_class=None, + unit_of_measurement=SPEED_MILES_PER_HOUR, + icon="mdi:weather-windy", + enabled_by_default=False, + ), + "visibility": MetOfficeSensorMetadata( + "Visibility", + device_class=None, + unit_of_measurement=None, + icon="mdi:eye", + enabled_by_default=False, + ), + "visibility_distance": MetOfficeSensorMetadata( "Visibility Distance", - None, - LENGTH_KILOMETERS, - "mdi:eye", - False, - ], - "uv": ["UV Index", None, UV_INDEX, "mdi:weather-sunny-alert", True], - "precipitation": [ + device_class=None, + unit_of_measurement=LENGTH_KILOMETERS, + icon="mdi:eye", + enabled_by_default=False, + ), + "uv": MetOfficeSensorMetadata( + "UV Index", + device_class=None, + unit_of_measurement=UV_INDEX, + icon="mdi:weather-sunny-alert", + enabled_by_default=True, + ), + "precipitation": MetOfficeSensorMetadata( "Probability of Precipitation", - None, - PERCENTAGE, - "mdi:weather-rainy", - True, - ], - "humidity": ["Humidity", DEVICE_CLASS_HUMIDITY, PERCENTAGE, None, False], + device_class=None, + unit_of_measurement=PERCENTAGE, + icon="mdi:weather-rainy", + enabled_by_default=True, + ), + "humidity": MetOfficeSensorMetadata( + "Humidity", + device_class=DEVICE_CLASS_HUMIDITY, + unit_of_measurement=PERCENTAGE, + icon=None, + enabled_by_default=False, + ), } @@ -91,15 +146,23 @@ async def async_setup_entry( async_add_entities( [ MetOfficeCurrentSensor( - hass_data[METOFFICE_HOURLY_COORDINATOR], hass_data, True, sensor_type + hass_data[METOFFICE_HOURLY_COORDINATOR], + hass_data, + True, + sensor_type, + metadata, ) - for sensor_type in SENSOR_TYPES + for sensor_type, metadata in SENSOR_TYPES.items() ] + [ MetOfficeCurrentSensor( - hass_data[METOFFICE_DAILY_COORDINATOR], hass_data, False, sensor_type + hass_data[METOFFICE_DAILY_COORDINATOR], + hass_data, + False, + sensor_type, + metadata, ) - for sensor_type in SENSOR_TYPES + for sensor_type, metadata in SENSOR_TYPES.items() ], False, ) @@ -108,33 +171,29 @@ async def async_setup_entry( class MetOfficeCurrentSensor(CoordinatorEntity, SensorEntity): """Implementation of a Met Office current weather condition sensor.""" - def __init__(self, coordinator, hass_data, use_3hourly, sensor_type): + def __init__( + self, + coordinator, + hass_data, + use_3hourly, + sensor_type, + metadata: MetOfficeSensorMetadata, + ): """Initialize the sensor.""" super().__init__(coordinator) self._type = sensor_type + self._metadata = metadata mode_label = MODE_3HOURLY_LABEL if use_3hourly else MODE_DAILY_LABEL - self._name = ( - f"{hass_data[METOFFICE_NAME]} {SENSOR_TYPES[self._type][0]} {mode_label}" - ) - self._unique_id = ( - f"{SENSOR_TYPES[self._type][0]}_{hass_data[METOFFICE_COORDINATES]}" - ) + self._attr_name = f"{hass_data[METOFFICE_NAME]} {metadata.title} {mode_label}" + self._attr_unique_id = f"{metadata.title}_{hass_data[METOFFICE_COORDINATES]}" if not use_3hourly: - self._unique_id = f"{self._unique_id}_{MODE_DAILY}" + self._attr_unique_id = f"{self._attr_unique_id}_{MODE_DAILY}" + self._attr_device_class = metadata.device_class + self._attr_unit_of_measurement = metadata.unit_of_measurement self.use_3hourly = use_3hourly - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def unique_id(self): - """Return the unique of the sensor.""" - return self._unique_id - @property def state(self): """Return the state of the sensor.""" @@ -167,15 +226,10 @@ class MetOfficeCurrentSensor(CoordinatorEntity, SensorEntity): return value - @property - def unit_of_measurement(self): - """Return the unit of measurement.""" - return SENSOR_TYPES[self._type][2] - @property def icon(self): """Return the icon for the entity card.""" - value = SENSOR_TYPES[self._type][3] + value = self._metadata.icon if self._type == "weather": value = self.state if value is None: @@ -186,11 +240,6 @@ class MetOfficeCurrentSensor(CoordinatorEntity, SensorEntity): return value - @property - def device_class(self): - """Return the device class of the sensor.""" - return SENSOR_TYPES[self._type][1] - @property def extra_state_attributes(self): """Return the state attributes of the device.""" @@ -205,4 +254,4 @@ class MetOfficeCurrentSensor(CoordinatorEntity, SensorEntity): @property def entity_registry_enabled_default(self) -> bool: """Return if the entity should be enabled when first added to the entity registry.""" - return SENSOR_TYPES[self._type][4] and self.use_3hourly + return self._metadata.enabled_by_default and self.use_3hourly