From d1f3c200795838a12581831f4f38f90b6444fd4a Mon Sep 17 00:00:00 2001
From: Erik Montnemery <erik@montnemery.com>
Date: Mon, 12 Jul 2021 20:41:45 +0200
Subject: [PATCH] Set device_class on temperature sensors L-Q (#52919)

---
 homeassistant/components/lacrosse/sensor.py   |  2 +
 .../components/luftdaten/__init__.py          | 33 ++++++++-
 homeassistant/components/luftdaten/sensor.py  | 13 +++-
 homeassistant/components/mfi/sensor.py        | 16 +++-
 homeassistant/components/mysensors/sensor.py  | 74 +++++++++++--------
 homeassistant/components/notion/sensor.py     |  6 +-
 homeassistant/components/openevse/sensor.py   | 16 ++--
 homeassistant/components/qnap/sensor.py       | 47 ++++++++----
 8 files changed, 143 insertions(+), 64 deletions(-)

diff --git a/homeassistant/components/lacrosse/sensor.py b/homeassistant/components/lacrosse/sensor.py
index 7c5557757ef..2f93196a4bb 100644
--- a/homeassistant/components/lacrosse/sensor.py
+++ b/homeassistant/components/lacrosse/sensor.py
@@ -17,6 +17,7 @@ from homeassistant.const import (
     CONF_NAME,
     CONF_SENSORS,
     CONF_TYPE,
+    DEVICE_CLASS_TEMPERATURE,
     EVENT_HOMEASSISTANT_STOP,
     PERCENTAGE,
     TEMP_CELSIUS,
@@ -174,6 +175,7 @@ class LaCrosseSensor(SensorEntity):
 class LaCrosseTemperature(LaCrosseSensor):
     """Implementation of a Lacrosse temperature sensor."""
 
+    _attr_device_class = DEVICE_CLASS_TEMPERATURE
     _attr_unit_of_measurement = TEMP_CELSIUS
 
     @property
diff --git a/homeassistant/components/luftdaten/__init__.py b/homeassistant/components/luftdaten/__init__.py
index f03448fa3a9..5dffab65d75 100644
--- a/homeassistant/components/luftdaten/__init__.py
+++ b/homeassistant/components/luftdaten/__init__.py
@@ -12,6 +12,9 @@ from homeassistant.const import (
     CONF_SCAN_INTERVAL,
     CONF_SENSORS,
     CONF_SHOW_ON_MAP,
+    DEVICE_CLASS_HUMIDITY,
+    DEVICE_CLASS_PRESSURE,
+    DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     PRESSURE_HPA,
     TEMP_CELSIUS,
@@ -45,19 +48,41 @@ SENSOR_TEMPERATURE = "temperature"
 TOPIC_UPDATE = f"{DOMAIN}_data_update"
 
 SENSORS = {
-    SENSOR_TEMPERATURE: ["Temperature", "mdi:thermometer", TEMP_CELSIUS],
-    SENSOR_HUMIDITY: ["Humidity", "mdi:water-percent", PERCENTAGE],
-    SENSOR_PRESSURE: ["Pressure", "mdi:arrow-down-bold", PRESSURE_HPA],
-    SENSOR_PRESSURE_AT_SEALEVEL: ["Pressure at sealevel", "mdi:download", PRESSURE_HPA],
+    SENSOR_TEMPERATURE: [
+        "Temperature",
+        "mdi:thermometer",
+        TEMP_CELSIUS,
+        DEVICE_CLASS_TEMPERATURE,
+    ],
+    SENSOR_HUMIDITY: [
+        "Humidity",
+        "mdi:water-percent",
+        PERCENTAGE,
+        DEVICE_CLASS_HUMIDITY,
+    ],
+    SENSOR_PRESSURE: [
+        "Pressure",
+        "mdi:arrow-down-bold",
+        PRESSURE_HPA,
+        DEVICE_CLASS_PRESSURE,
+    ],
+    SENSOR_PRESSURE_AT_SEALEVEL: [
+        "Pressure at sealevel",
+        "mdi:download",
+        PRESSURE_HPA,
+        DEVICE_CLASS_PRESSURE,
+    ],
     SENSOR_PM10: [
         "PM10",
         "mdi:thought-bubble",
         CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
+        None,
     ],
     SENSOR_PM2_5: [
         "PM2.5",
         "mdi:thought-bubble-outline",
         CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
+        None,
     ],
 }
 
diff --git a/homeassistant/components/luftdaten/sensor.py b/homeassistant/components/luftdaten/sensor.py
index aec77961b94..b27cc35ab26 100644
--- a/homeassistant/components/luftdaten/sensor.py
+++ b/homeassistant/components/luftdaten/sensor.py
@@ -31,14 +31,20 @@ async def async_setup_entry(hass, entry, async_add_entities):
     sensors = []
     for sensor_type in luftdaten.sensor_conditions:
         try:
-            name, icon, unit = SENSORS[sensor_type]
+            name, icon, unit, device_class = SENSORS[sensor_type]
         except KeyError:
             _LOGGER.debug("Unknown sensor value type: %s", sensor_type)
             continue
 
         sensors.append(
             LuftdatenSensor(
-                luftdaten, sensor_type, name, icon, unit, entry.data[CONF_SHOW_ON_MAP]
+                luftdaten,
+                sensor_type,
+                name,
+                icon,
+                unit,
+                device_class,
+                entry.data[CONF_SHOW_ON_MAP],
             )
         )
 
@@ -48,7 +54,7 @@ async def async_setup_entry(hass, entry, async_add_entities):
 class LuftdatenSensor(SensorEntity):
     """Implementation of a Luftdaten sensor."""
 
-    def __init__(self, luftdaten, sensor_type, name, icon, unit, show):
+    def __init__(self, luftdaten, sensor_type, name, icon, unit, device_class, show):
         """Initialize the Luftdaten sensor."""
         self._async_unsub_dispatcher_connect = None
         self.luftdaten = luftdaten
@@ -59,6 +65,7 @@ class LuftdatenSensor(SensorEntity):
         self._unit_of_measurement = unit
         self._show_on_map = show
         self._attrs = {}
+        self._attr_device_class = device_class
 
     @property
     def icon(self):
diff --git a/homeassistant/components/mfi/sensor.py b/homeassistant/components/mfi/sensor.py
index c7a64f17bd6..fafaf53ff99 100644
--- a/homeassistant/components/mfi/sensor.py
+++ b/homeassistant/components/mfi/sensor.py
@@ -13,6 +13,7 @@ from homeassistant.const import (
     CONF_SSL,
     CONF_USERNAME,
     CONF_VERIFY_SSL,
+    DEVICE_CLASS_TEMPERATURE,
     STATE_OFF,
     STATE_ON,
     TEMP_CELSIUS,
@@ -83,7 +84,7 @@ class MfiSensor(SensorEntity):
 
     @property
     def name(self):
-        """Return the name of th sensor."""
+        """Return the name of the sensor."""
         return self._port.label
 
     @property
@@ -100,6 +101,19 @@ class MfiSensor(SensorEntity):
         digits = DIGITS.get(self._port.tag, 0)
         return round(self._port.value, digits)
 
+    @property
+    def device_class(self):
+        """Return the device class of the sensor."""
+        try:
+            tag = self._port.tag
+        except ValueError:
+            return None
+
+        if tag == "temperature":
+            return DEVICE_CLASS_TEMPERATURE
+
+        return None
+
     @property
     def unit_of_measurement(self):
         """Return the unit of measurement of this entity, if any."""
diff --git a/homeassistant/components/mysensors/sensor.py b/homeassistant/components/mysensors/sensor.py
index 2ede5e38c6a..6a5c80e1e8a 100644
--- a/homeassistant/components/mysensors/sensor.py
+++ b/homeassistant/components/mysensors/sensor.py
@@ -9,6 +9,8 @@ from homeassistant.config_entries import ConfigEntry
 from homeassistant.const import (
     CONDUCTIVITY,
     DEGREE,
+    DEVICE_CLASS_HUMIDITY,
+    DEVICE_CLASS_TEMPERATURE,
     ELECTRICAL_CURRENT_AMPERE,
     ELECTRICAL_VOLT_AMPERE,
     ENERGY_KILO_WATT_HOUR,
@@ -31,37 +33,37 @@ from .const import MYSENSORS_DISCOVERY, DiscoveryInfo
 from .helpers import on_unload
 
 SENSORS: dict[str, list[str | None] | dict[str, list[str | None]]] = {
-    "V_TEMP": [None, "mdi:thermometer"],
-    "V_HUM": [PERCENTAGE, "mdi:water-percent"],
-    "V_DIMMER": [PERCENTAGE, "mdi:percent"],
-    "V_PERCENTAGE": [PERCENTAGE, "mdi:percent"],
-    "V_PRESSURE": [None, "mdi:gauge"],
-    "V_FORECAST": [None, "mdi:weather-partly-cloudy"],
-    "V_RAIN": [None, "mdi:weather-rainy"],
-    "V_RAINRATE": [None, "mdi:weather-rainy"],
-    "V_WIND": [None, "mdi:weather-windy"],
-    "V_GUST": [None, "mdi:weather-windy"],
-    "V_DIRECTION": [DEGREE, "mdi:compass"],
-    "V_WEIGHT": [MASS_KILOGRAMS, "mdi:weight-kilogram"],
-    "V_DISTANCE": [LENGTH_METERS, "mdi:ruler"],
-    "V_IMPEDANCE": ["ohm", None],
-    "V_WATT": [POWER_WATT, None],
-    "V_KWH": [ENERGY_KILO_WATT_HOUR, None],
-    "V_LIGHT_LEVEL": [PERCENTAGE, "mdi:white-balance-sunny"],
-    "V_FLOW": [LENGTH_METERS, "mdi:gauge"],
-    "V_VOLUME": [f"{VOLUME_CUBIC_METERS}", None],
+    "V_TEMP": [None, None, DEVICE_CLASS_TEMPERATURE],
+    "V_HUM": [PERCENTAGE, "mdi:water-percent", DEVICE_CLASS_HUMIDITY],
+    "V_DIMMER": [PERCENTAGE, "mdi:percent", None],
+    "V_PERCENTAGE": [PERCENTAGE, "mdi:percent", None],
+    "V_PRESSURE": [None, "mdi:gauge", None],
+    "V_FORECAST": [None, "mdi:weather-partly-cloudy", None],
+    "V_RAIN": [None, "mdi:weather-rainy", None],
+    "V_RAINRATE": [None, "mdi:weather-rainy", None],
+    "V_WIND": [None, "mdi:weather-windy", None],
+    "V_GUST": [None, "mdi:weather-windy", None],
+    "V_DIRECTION": [DEGREE, "mdi:compass", None],
+    "V_WEIGHT": [MASS_KILOGRAMS, "mdi:weight-kilogram", None],
+    "V_DISTANCE": [LENGTH_METERS, "mdi:ruler", None],
+    "V_IMPEDANCE": ["ohm", None, None],
+    "V_WATT": [POWER_WATT, None, None],
+    "V_KWH": [ENERGY_KILO_WATT_HOUR, None, None],
+    "V_LIGHT_LEVEL": [PERCENTAGE, "mdi:white-balance-sunny", None],
+    "V_FLOW": [LENGTH_METERS, "mdi:gauge", None],
+    "V_VOLUME": [f"{VOLUME_CUBIC_METERS}", None, None],
     "V_LEVEL": {
-        "S_SOUND": ["dB", "mdi:volume-high"],
-        "S_VIBRATION": [FREQUENCY_HERTZ, None],
-        "S_LIGHT_LEVEL": [LIGHT_LUX, "mdi:white-balance-sunny"],
+        "S_SOUND": ["dB", "mdi:volume-high", None],
+        "S_VIBRATION": [FREQUENCY_HERTZ, None, None],
+        "S_LIGHT_LEVEL": [LIGHT_LUX, "mdi:white-balance-sunny", None],
     },
-    "V_VOLTAGE": [VOLT, "mdi:flash"],
-    "V_CURRENT": [ELECTRICAL_CURRENT_AMPERE, "mdi:flash-auto"],
-    "V_PH": ["pH", None],
-    "V_ORP": ["mV", None],
-    "V_EC": [CONDUCTIVITY, None],
-    "V_VAR": ["var", None],
-    "V_VA": [ELECTRICAL_VOLT_AMPERE, None],
+    "V_VOLTAGE": [VOLT, "mdi:flash", None],
+    "V_CURRENT": [ELECTRICAL_CURRENT_AMPERE, "mdi:flash-auto", None],
+    "V_PH": ["pH", None, None],
+    "V_ORP": ["mV", None, None],
+    "V_EC": [CONDUCTIVITY, None, None],
+    "V_VAR": ["var", None, None],
+    "V_VA": [ELECTRICAL_VOLT_AMPERE, None, None],
 }
 
 
@@ -107,9 +109,15 @@ class MySensorsSensor(mysensors.device.MySensorsEntity, SensorEntity):
 
     @property
     def state(self) -> str | None:
-        """Return the state of the device."""
+        """Return the state of this entity."""
         return self._values.get(self.value_type)
 
+    @property
+    def device_class(self) -> str | None:
+        """Return the device class of this entity."""
+        icon = self._get_sensor_type()[2]
+        return icon
+
     @property
     def icon(self) -> str | None:
         """Return the icon to use in the frontend, if any."""
@@ -140,9 +148,11 @@ class MySensorsSensor(mysensors.device.MySensorsEntity, SensorEntity):
         pres = self.gateway.const.Presentation
         set_req = self.gateway.const.SetReq
 
-        _sensor_type = SENSORS.get(set_req(self.value_type).name, [None, None])
+        _sensor_type = SENSORS.get(set_req(self.value_type).name, [None, None, None])
         if isinstance(_sensor_type, dict):
-            sensor_type = _sensor_type.get(pres(self.child_type).name, [None, None])
+            sensor_type = _sensor_type.get(
+                pres(self.child_type).name, [None, None, None]
+            )
         else:
             sensor_type = _sensor_type
         return sensor_type
diff --git a/homeassistant/components/notion/sensor.py b/homeassistant/components/notion/sensor.py
index 659b58e9815..48b9a25f783 100644
--- a/homeassistant/components/notion/sensor.py
+++ b/homeassistant/components/notion/sensor.py
@@ -1,7 +1,7 @@
 """Support for Notion sensors."""
 from homeassistant.components.sensor import SensorEntity
 from homeassistant.config_entries import ConfigEntry
-from homeassistant.const import TEMP_CELSIUS
+from homeassistant.const import DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS
 from homeassistant.core import HomeAssistant, callback
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
@@ -9,7 +9,9 @@ from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
 from . import NotionEntity
 from .const import DATA_COORDINATOR, DOMAIN, LOGGER, SENSOR_TEMPERATURE
 
-SENSOR_TYPES = {SENSOR_TEMPERATURE: ("Temperature", "temperature", TEMP_CELSIUS)}
+SENSOR_TYPES = {
+    SENSOR_TEMPERATURE: ("Temperature", DEVICE_CLASS_TEMPERATURE, TEMP_CELSIUS)
+}
 
 
 async def async_setup_entry(
diff --git a/homeassistant/components/openevse/sensor.py b/homeassistant/components/openevse/sensor.py
index d7d4149e26d..29eeceb232c 100644
--- a/homeassistant/components/openevse/sensor.py
+++ b/homeassistant/components/openevse/sensor.py
@@ -9,6 +9,7 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
 from homeassistant.const import (
     CONF_HOST,
     CONF_MONITORED_VARIABLES,
+    DEVICE_CLASS_TEMPERATURE,
     ENERGY_KILO_WATT_HOUR,
     TEMP_CELSIUS,
     TIME_MINUTES,
@@ -18,13 +19,13 @@ import homeassistant.helpers.config_validation as cv
 _LOGGER = logging.getLogger(__name__)
 
 SENSOR_TYPES = {
-    "status": ["Charging Status", None],
-    "charge_time": ["Charge Time Elapsed", TIME_MINUTES],
-    "ambient_temp": ["Ambient Temperature", TEMP_CELSIUS],
-    "ir_temp": ["IR Temperature", TEMP_CELSIUS],
-    "rtc_temp": ["RTC Temperature", TEMP_CELSIUS],
-    "usage_session": ["Usage this Session", ENERGY_KILO_WATT_HOUR],
-    "usage_total": ["Total Usage", ENERGY_KILO_WATT_HOUR],
+    "status": ["Charging Status", None, None],
+    "charge_time": ["Charge Time Elapsed", TIME_MINUTES, None],
+    "ambient_temp": ["Ambient Temperature", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE],
+    "ir_temp": ["IR Temperature", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE],
+    "rtc_temp": ["RTC Temperature", TEMP_CELSIUS, DEVICE_CLASS_TEMPERATURE],
+    "usage_session": ["Usage this Session", ENERGY_KILO_WATT_HOUR, None],
+    "usage_total": ["Total Usage", ENERGY_KILO_WATT_HOUR, None],
 }
 
 PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
@@ -61,6 +62,7 @@ class OpenEVSESensor(SensorEntity):
         self._state = None
         self.charger = charger
         self._unit_of_measurement = SENSOR_TYPES[sensor_type][1]
+        self._attr_device_class = SENSOR_TYPES[sensor_type][2]
 
     @property
     def name(self):
diff --git a/homeassistant/components/qnap/sensor.py b/homeassistant/components/qnap/sensor.py
index 5759713e80c..c175d89f60e 100644
--- a/homeassistant/components/qnap/sensor.py
+++ b/homeassistant/components/qnap/sensor.py
@@ -18,6 +18,7 @@ from homeassistant.const import (
     CONF_VERIFY_SSL,
     DATA_GIBIBYTES,
     DATA_RATE_MEBIBYTES_PER_SECOND,
+    DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     TEMP_CELSIUS,
 )
@@ -56,31 +57,46 @@ NOTIFICATION_ID = "qnap_notification"
 NOTIFICATION_TITLE = "QNAP Sensor Setup"
 
 _SYSTEM_MON_COND = {
-    "status": ["Status", None, "mdi:checkbox-marked-circle-outline"],
-    "system_temp": ["System Temperature", TEMP_CELSIUS, "mdi:thermometer"],
+    "status": ["Status", None, "mdi:checkbox-marked-circle-outline", None],
+    "system_temp": ["System Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
 }
 _CPU_MON_COND = {
-    "cpu_temp": ["CPU Temperature", TEMP_CELSIUS, "mdi:thermometer"],
-    "cpu_usage": ["CPU Usage", PERCENTAGE, "mdi:chip"],
+    "cpu_temp": ["CPU Temperature", TEMP_CELSIUS, None, DEVICE_CLASS_TEMPERATURE],
+    "cpu_usage": ["CPU Usage", PERCENTAGE, "mdi:chip", None],
 }
 _MEMORY_MON_COND = {
-    "memory_free": ["Memory Available", DATA_GIBIBYTES, "mdi:memory"],
-    "memory_used": ["Memory Used", DATA_GIBIBYTES, "mdi:memory"],
-    "memory_percent_used": ["Memory Usage", PERCENTAGE, "mdi:memory"],
+    "memory_free": ["Memory Available", DATA_GIBIBYTES, "mdi:memory", None],
+    "memory_used": ["Memory Used", DATA_GIBIBYTES, "mdi:memory", None],
+    "memory_percent_used": ["Memory Usage", PERCENTAGE, "mdi:memory", None],
 }
 _NETWORK_MON_COND = {
-    "network_link_status": ["Network Link", None, "mdi:checkbox-marked-circle-outline"],
-    "network_tx": ["Network Up", DATA_RATE_MEBIBYTES_PER_SECOND, "mdi:upload"],
-    "network_rx": ["Network Down", DATA_RATE_MEBIBYTES_PER_SECOND, "mdi:download"],
+    "network_link_status": [
+        "Network Link",
+        None,
+        "mdi:checkbox-marked-circle-outline",
+        None,
+    ],
+    "network_tx": ["Network Up", DATA_RATE_MEBIBYTES_PER_SECOND, "mdi:upload", None],
+    "network_rx": [
+        "Network Down",
+        DATA_RATE_MEBIBYTES_PER_SECOND,
+        "mdi:download",
+        None,
+    ],
 }
 _DRIVE_MON_COND = {
-    "drive_smart_status": ["SMART Status", None, "mdi:checkbox-marked-circle-outline"],
-    "drive_temp": ["Temperature", TEMP_CELSIUS, "mdi:thermometer"],
+    "drive_smart_status": [
+        "SMART Status",
+        None,
+        "mdi:checkbox-marked-circle-outline",
+        None,
+    ],
+    "drive_temp": ["Temperature", TEMP_CELSIUS, None, None, DEVICE_CLASS_TEMPERATURE],
 }
 _VOLUME_MON_COND = {
-    "volume_size_used": ["Used Space", DATA_GIBIBYTES, "mdi:chart-pie"],
-    "volume_size_free": ["Free Space", DATA_GIBIBYTES, "mdi:chart-pie"],
-    "volume_percentage_used": ["Volume Used", PERCENTAGE, "mdi:chart-pie"],
+    "volume_size_used": ["Used Space", DATA_GIBIBYTES, "mdi:chart-pie", None],
+    "volume_size_free": ["Free Space", DATA_GIBIBYTES, "mdi:chart-pie", None],
+    "volume_percentage_used": ["Volume Used", PERCENTAGE, "mdi:chart-pie", None],
 }
 
 _MONITORED_CONDITIONS = (
@@ -210,6 +226,7 @@ class QNAPSensor(SensorEntity):
         self.var_icon = variable_info[2]
         self.monitor_device = monitor_device
         self._api = api
+        self._attr_device_class = variable_info[3]
 
     @property
     def name(self):