From 2cf930f3bd1505ac48030854f2d82dafe7729d49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Hjelseth=20H=C3=B8yer?= Date: Wed, 21 Jul 2021 08:46:01 +0200 Subject: [PATCH] Netatmo, use nameclass (#53247) --- homeassistant/components/netatmo/sensor.py | 344 ++++++++++++--------- 1 file changed, 206 insertions(+), 138 deletions(-) diff --git a/homeassistant/components/netatmo/sensor.py b/homeassistant/components/netatmo/sensor.py index 917d04d1b4d..46bb06149cd 100644 --- a/homeassistant/components/netatmo/sensor.py +++ b/homeassistant/components/netatmo/sensor.py @@ -1,5 +1,8 @@ """Support for the Netatmo Weather Service.""" +from __future__ import annotations + import logging +from typing import NamedTuple from homeassistant.components.sensor import SensorEntity from homeassistant.const import ( @@ -51,136 +54,172 @@ SUPPORTED_PUBLIC_SENSOR_TYPES = [ "sum_rain_24", ] -# sensor type: [name, netatmo name, unit of measurement, icon, device class, enable default] -SENSOR_TYPES = { - "temperature": [ + +class SensorMetadata(NamedTuple): + """Metadata for an individual sensor.""" + + name: str + netatmo_name: str + enable_default: bool + unit: str | None = None + icon: str | None = None + device_class: str | None = None + + +SENSOR_TYPES: dict[str, SensorMetadata] = { + "temperature": SensorMetadata( "Temperature", - "Temperature", - TEMP_CELSIUS, - None, - DEVICE_CLASS_TEMPERATURE, - True, - ], - "temp_trend": [ + netatmo_name="Temperature", + enable_default=True, + unit=TEMP_CELSIUS, + device_class=DEVICE_CLASS_TEMPERATURE, + ), + "temp_trend": SensorMetadata( "Temperature trend", - "temp_trend", - None, - "mdi:trending-up", - None, - False, - ], - "co2": [ + netatmo_name="temp_trend", + enable_default=False, + icon="mdi:trending-up", + ), + "co2": SensorMetadata( "CO2", - "CO2", - CONCENTRATION_PARTS_PER_MILLION, - None, - DEVICE_CLASS_CO2, - True, - ], - "pressure": [ + netatmo_name="CO2", + unit=CONCENTRATION_PARTS_PER_MILLION, + enable_default=True, + device_class=DEVICE_CLASS_CO2, + ), + "pressure": SensorMetadata( "Pressure", - "Pressure", - PRESSURE_MBAR, - None, - DEVICE_CLASS_PRESSURE, - True, - ], - "pressure_trend": [ + netatmo_name="Pressure", + enable_default=True, + unit=PRESSURE_MBAR, + device_class=DEVICE_CLASS_PRESSURE, + ), + "pressure_trend": SensorMetadata( "Pressure trend", - "pressure_trend", - None, - "mdi:trending-up", - None, - False, - ], - "noise": ["Noise", "Noise", SOUND_PRESSURE_DB, "mdi:volume-high", None, True], - "humidity": ["Humidity", "Humidity", PERCENTAGE, None, DEVICE_CLASS_HUMIDITY, True], - "rain": ["Rain", "Rain", LENGTH_MILLIMETERS, "mdi:weather-rainy", None, True], - "sum_rain_1": [ + netatmo_name="pressure_trend", + enable_default=False, + icon="mdi:trending-up", + ), + "noise": SensorMetadata( + "Noise", + netatmo_name="Noise", + enable_default=True, + unit=SOUND_PRESSURE_DB, + icon="mdi:volume-high", + ), + "humidity": SensorMetadata( + "Humidity", + netatmo_name="Humidity", + enable_default=True, + unit=PERCENTAGE, + device_class=DEVICE_CLASS_HUMIDITY, + ), + "rain": SensorMetadata( + "Rain", + netatmo_name="Rain", + enable_default=True, + unit=LENGTH_MILLIMETERS, + icon="mdi:weather-rainy", + ), + "sum_rain_1": SensorMetadata( "Rain last hour", - "sum_rain_1", - LENGTH_MILLIMETERS, - "mdi:weather-rainy", - None, - False, - ], - "sum_rain_24": [ + enable_default=False, + netatmo_name="sum_rain_1", + unit=LENGTH_MILLIMETERS, + icon="mdi:weather-rainy", + ), + "sum_rain_24": SensorMetadata( "Rain today", - "sum_rain_24", - LENGTH_MILLIMETERS, - "mdi:weather-rainy", - None, - True, - ], - "battery_percent": [ + enable_default=True, + netatmo_name="sum_rain_24", + unit=LENGTH_MILLIMETERS, + icon="mdi:weather-rainy", + ), + "battery_percent": SensorMetadata( "Battery Percent", - "battery_percent", - PERCENTAGE, - None, - DEVICE_CLASS_BATTERY, - True, - ], - "windangle": ["Direction", "WindAngle", None, "mdi:compass-outline", None, True], - "windangle_value": [ + netatmo_name="battery_percent", + enable_default=True, + unit=PERCENTAGE, + device_class=DEVICE_CLASS_BATTERY, + ), + "windangle": SensorMetadata( + "Direction", + netatmo_name="WindAngle", + enable_default=True, + icon="mdi:compass-outline", + ), + "windangle_value": SensorMetadata( "Angle", - "WindAngle", - DEGREE, - "mdi:compass-outline", - None, - False, - ], - "windstrength": [ + netatmo_name="WindAngle", + enable_default=False, + unit=DEGREE, + icon="mdi:compass-outline", + ), + "windstrength": SensorMetadata( "Wind Strength", - "WindStrength", - SPEED_KILOMETERS_PER_HOUR, - "mdi:weather-windy", - None, - True, - ], - "gustangle": [ + netatmo_name="WindStrength", + enable_default=True, + unit=SPEED_KILOMETERS_PER_HOUR, + icon="mdi:weather-windy", + ), + "gustangle": SensorMetadata( "Gust Direction", - "GustAngle", - None, - "mdi:compass-outline", - None, - False, - ], - "gustangle_value": [ + netatmo_name="GustAngle", + enable_default=False, + icon="mdi:compass-outline", + ), + "gustangle_value": SensorMetadata( "Gust Angle", - "GustAngle", - DEGREE, - "mdi:compass-outline", - None, - False, - ], - "guststrength": [ + netatmo_name="GustAngle", + enable_default=False, + unit=DEGREE, + icon="mdi:compass-outline", + ), + "guststrength": SensorMetadata( "Gust Strength", - "GustStrength", - SPEED_KILOMETERS_PER_HOUR, - "mdi:weather-windy", - None, - False, - ], - "reachable": ["Reachability", "reachable", None, "mdi:signal", None, False], - "rf_status": ["Radio", "rf_status", None, "mdi:signal", None, False], - "rf_status_lvl": [ + netatmo_name="GustStrength", + enable_default=False, + unit=SPEED_KILOMETERS_PER_HOUR, + icon="mdi:weather-windy", + ), + "reachable": SensorMetadata( + "Reachability", + netatmo_name="reachable", + enable_default=False, + icon="mdi:signal", + ), + "rf_status": SensorMetadata( + "Radio", + netatmo_name="rf_status", + enable_default=False, + icon="mdi:signal", + ), + "rf_status_lvl": SensorMetadata( "Radio Level", - "rf_status", - SIGNAL_STRENGTH_DECIBELS_MILLIWATT, - None, - DEVICE_CLASS_SIGNAL_STRENGTH, - False, - ], - "wifi_status": ["Wifi", "wifi_status", None, "mdi:wifi", None, False], - "wifi_status_lvl": [ + netatmo_name="rf_status", + enable_default=False, + unit=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + ), + "wifi_status": SensorMetadata( + "Wifi", + netatmo_name="wifi_status", + enable_default=False, + icon="mdi:wifi", + ), + "wifi_status_lvl": SensorMetadata( "Wifi Level", - "wifi_status", - SIGNAL_STRENGTH_DECIBELS_MILLIWATT, - None, - DEVICE_CLASS_SIGNAL_STRENGTH, - False, - ], - "health_idx": ["Health", "health_idx", None, "mdi:cloud", None, True], + netatmo_name="wifi_status", + enable_default=False, + unit=SIGNAL_STRENGTH_DECIBELS_MILLIWATT, + device_class=DEVICE_CLASS_SIGNAL_STRENGTH, + ), + "health_idx": SensorMetadata( + "Health", + enable_default=True, + netatmo_name="health_idx", + icon="mdi:cloud", + ), } MODULE_TYPE_OUTDOOR = "NAModule1" @@ -188,11 +227,41 @@ MODULE_TYPE_WIND = "NAModule2" MODULE_TYPE_RAIN = "NAModule3" MODULE_TYPE_INDOOR = "NAModule4" + +class BatteryData(NamedTuple): + """Metadata for a batter.""" + + full: int + high: int + medium: int + low: int + + BATTERY_VALUES = { - MODULE_TYPE_WIND: {"Full": 5590, "High": 5180, "Medium": 4770, "Low": 4360}, - MODULE_TYPE_RAIN: {"Full": 5500, "High": 5000, "Medium": 4500, "Low": 4000}, - MODULE_TYPE_INDOOR: {"Full": 5500, "High": 5280, "Medium": 4920, "Low": 4560}, - MODULE_TYPE_OUTDOOR: {"Full": 5500, "High": 5000, "Medium": 4500, "Low": 4000}, + MODULE_TYPE_WIND: BatteryData( + full=5590, + high=5180, + medium=4770, + low=4360, + ), + MODULE_TYPE_RAIN: BatteryData( + full=5500, + high=5000, + medium=4500, + low=4000, + ), + MODULE_TYPE_INDOOR: BatteryData( + full=5500, + high=5280, + medium=4920, + low=4560, + ), + MODULE_TYPE_OUTDOOR: BatteryData( + full=5500, + high=5000, + medium=4500, + low=4000, + ), } PUBLIC = "public" @@ -331,6 +400,8 @@ class NetatmoSensor(NetatmoBase, SensorEntity): """Initialize the sensor.""" super().__init__(data_handler) + metadata: SensorMetadata = SENSOR_TYPES[sensor_type] + self._data_classes.append( {"name": data_class_name, SIGNAL_NAME: data_class_name} ) @@ -353,16 +424,14 @@ class NetatmoSensor(NetatmoBase, SensorEntity): f"{module_info.get('module_name', device['type'])}" ) - self._attr_name = ( - f"{MANUFACTURER} {self._device_name} {SENSOR_TYPES[sensor_type][0]}" - ) + self._attr_name = f"{MANUFACTURER} {self._device_name} {metadata.name}" self.type = sensor_type - self._attr_device_class = SENSOR_TYPES[self.type][4] - self._attr_icon = SENSOR_TYPES[self.type][3] - self._attr_unit_of_measurement = SENSOR_TYPES[self.type][2] + self._attr_device_class = metadata.device_class + self._attr_icon = metadata.icon + self._attr_unit_of_measurement = metadata.unit self._model = device["type"] self._attr_unique_id = f"{self._id}-{self.type}" - self._attr_entity_registry_enabled_default = SENSOR_TYPES[self.type][5] + self._attr_entity_registry_enabled_default = metadata.enable_default @property def available(self): @@ -395,7 +464,7 @@ class NetatmoSensor(NetatmoBase, SensorEntity): return try: - state = data[SENSOR_TYPES[self.type][1]] + state = data[SENSOR_TYPES[self.type].netatmo_name] if self.type in {"temperature", "pressure", "sum_rain_1"}: self._attr_state = round(state, 1) elif self.type in {"windangle_value", "gustangle_value"}: @@ -449,15 +518,15 @@ def process_angle(angle: int) -> str: def process_battery(data: int, model: str) -> str: """Process battery data and return string for display.""" - values = BATTERY_VALUES[model] + battery_data = BATTERY_VALUES[model] - if data >= values["Full"]: + if data >= battery_data.full: return "Full" - if data >= values["High"]: + if data >= battery_data.high: return "High" - if data >= values["Medium"]: + if data >= battery_data.medium: return "Medium" - if data >= values["Low"]: + if data >= battery_data.low: return "Low" return "Very Low" @@ -518,6 +587,7 @@ class NetatmoPublicSensor(NetatmoBase, SensorEntity): SIGNAL_NAME: self._signal_name, } ) + metadata: SensorMetadata = SENSOR_TYPES[sensor_type] self.type = sensor_type self.area = area @@ -525,12 +595,10 @@ class NetatmoPublicSensor(NetatmoBase, SensorEntity): self._area_name = area.area_name self._id = self._area_name self._device_name = f"{self._area_name}" - self._attr_name = ( - f"{MANUFACTURER} {self._device_name} {SENSOR_TYPES[self.type][0]}" - ) - self._attr_device_class = SENSOR_TYPES[self.type][4] - self._attr_icon = SENSOR_TYPES[self.type][3] - self._attr_unit_of_measurement = SENSOR_TYPES[self.type][2] + self._attr_name = f"{MANUFACTURER} {self._device_name} {metadata.name}" + self._attr_device_class = metadata.device_class + self._attr_icon = metadata.icon + self._attr_unit_of_measurement = metadata.unit self._show_on_map = area.show_on_map self._attr_unique_id = f"{self._device_name.replace(' ', '-')}-{self.type}" self._model = PUBLIC