Browse Source

Add support for device class to number platform.

This was silently added to HA in 2023.2.0.  Unfortunately it is
missing duration, which is the most common use for numbers, and both
sensor and number are missing a class for relative temperatures, which
is the second (using temperature would cause incorrect conversions
due to the misalignment of 0 points between Celsius and Fahrenheit).

So only a few instances of temperature limits, and some power,
current, voltage and illumanance configs can be given device classes.

Issue #513
Jason Rumney 2 years ago
parent
commit
b06f0fcd47
40 changed files with 130 additions and 15 deletions
  1. 20 0
      custom_components/tuya_local/devices/arlec_thermostat_smartplug.yaml
  2. 2 0
      custom_components/tuya_local/devices/avatto_wt100_thermostat.yaml
  3. 1 8
      custom_components/tuya_local/devices/bcom_intercom_camera.yaml
  4. 2 0
      custom_components/tuya_local/devices/beok_tgr81_thermostat_c.yaml
  5. 2 0
      custom_components/tuya_local/devices/beok_tol47_thermostat.yaml
  6. 2 0
      custom_components/tuya_local/devices/beok_tr9b_thermostat.yaml
  7. 1 0
      custom_components/tuya_local/devices/bvf_cp1_heater.yaml
  8. 0 1
      custom_components/tuya_local/devices/ecostrad_iqceramic_radiator.yaml
  9. 2 0
      custom_components/tuya_local/devices/etop_ht_thermostat.yaml
  10. 5 0
      custom_components/tuya_local/devices/hysen_hy08acf_thermostat.yaml
  11. 5 0
      custom_components/tuya_local/devices/hysen_hy08we2_thermostat.yaml
  12. 2 0
      custom_components/tuya_local/devices/inkbird_itc306a_thermostat.yaml
  13. 2 0
      custom_components/tuya_local/devices/inkbird_itc308_thermostat.yaml
  14. 1 0
      custom_components/tuya_local/devices/jiahong_et72w_thermostat.yaml
  15. 3 0
      custom_components/tuya_local/devices/ledkia_fan_light.yaml
  16. 2 0
      custom_components/tuya_local/devices/me80_thermostat.yaml
  17. 1 0
      custom_components/tuya_local/devices/minco_mh1823d_thermostat.yaml
  18. 1 1
      custom_components/tuya_local/devices/moes_dimmer.yaml
  19. 1 0
      custom_components/tuya_local/devices/motion_sensor_light.yaml
  20. 1 0
      custom_components/tuya_local/devices/nedis_pet_feeder.yaml
  21. 2 0
      custom_components/tuya_local/devices/parkside_plgs2012a1_smart_charger.yaml
  22. 4 2
      custom_components/tuya_local/devices/pgst_climate_sensor.yaml
  23. 1 0
      custom_components/tuya_local/devices/pj1103_clamp_meter.yaml
  24. 2 0
      custom_components/tuya_local/devices/salcar_t9w_thermostat.yaml
  25. 2 0
      custom_components/tuya_local/devices/saswell_c16_thermostat.yaml
  26. 1 0
      custom_components/tuya_local/devices/setti_czajnik_kettle.yaml
  27. 2 0
      custom_components/tuya_local/devices/t5e_wf_thermostat.yaml
  28. 13 0
      custom_components/tuya_local/number.py
  29. 1 1
      hacs.json
  30. 1 1
      requirements-dev.txt
  31. 3 0
      tests/devices/test_beok_tr9b_thermostat.py
  32. 6 0
      tests/devices/test_hysen_hy08we2_thermostat.py
  33. 3 0
      tests/devices/test_inkbird_itc306a_thermostat.py
  34. 3 0
      tests/devices/test_inkbird_itc308_thermostat.py
  35. 2 1
      tests/devices/test_jiahong_et72w_thermostat.py
  36. 2 0
      tests/devices/test_minco_mh1823d_thermostat.py
  37. 2 0
      tests/devices/test_motion_sensor_light.py
  38. 3 0
      tests/devices/test_parkside_plgs2012a1_smart_charger.py
  39. 3 0
      tests/devices/test_saswell_c16_thermostat.py
  40. 18 0
      tests/mixins/number.py

+ 20 - 0
custom_components/tuya_local/devices/arlec_thermostat_smartplug.yaml

@@ -205,6 +205,14 @@ secondary_entities:
         mapping:
           - scale: 10
             step: 5
+      - id: 20
+        type: string
+        name: unit
+        mapping:
+          - dps_val: c
+            value: C
+          - dps_val: f
+            value: F
   - entity: number
     name: Temperature correction
     category: config
@@ -216,14 +224,24 @@ secondary_entities:
         range:
           min: -9
           max: 9
+      - id: 20
+        type: string
+        name: unit
+        mapping:
+          - dps_val: c
+            value: C
+          - dps_val: f
+            value: F
   - entity: number
     name: Humidity hysteresis
     category: config
+    class: humidity
     icon: "mdi:arrow-collapse-vertical"
     dps:
       - id: 42
         type: integer
         name: value
+        unit: "%"
         range:
           min: 2
           max: 20
@@ -232,11 +250,13 @@ secondary_entities:
   - entity: number
     name: Humidity correction
     category: config
+    class: humidity
     icon: "mdi:pan-vertical"
     dps:
       - id: 47
         type: integer
         name: value
+        unit: "%"
         range:
           min: -9
           max: 9

+ 2 - 0
custom_components/tuya_local/devices/avatto_wt100_thermostat.yaml

@@ -116,6 +116,7 @@ secondary_entities:
   - entity: number
     name: Maximum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 21
@@ -208,6 +209,7 @@ secondary_entities:
   - entity: number
     name: External temperature limit
     category: config
+    class: temperature
     icon: "mdi:arrow-collapse-up"
     dps:
       - id: 107

+ 1 - 8
custom_components/tuya_local/devices/bcom_intercom_camera.yaml

@@ -139,13 +139,6 @@ secondary_entities:
     dps:
       - id: 231
         type: string
-        name: sensor
-
-  
-            
-
-            
-
-            
+        name: sensor          
 
 

+ 2 - 0
custom_components/tuya_local/devices/beok_tgr81_thermostat_c.yaml

@@ -129,6 +129,7 @@ secondary_entities:
   - entity: number
     name: High temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 19
@@ -141,6 +142,7 @@ secondary_entities:
   - entity: number
     name: Low temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-down"
     dps:
       - id: 26

+ 2 - 0
custom_components/tuya_local/devices/beok_tol47_thermostat.yaml

@@ -110,6 +110,7 @@ secondary_entities:
   - entity: number
     name: High temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 21
@@ -202,6 +203,7 @@ secondary_entities:
   - entity: number
     name: External sensor temperature limit
     category: config
+    class: temperature
     icon: "mdi:arrow-collapse-up"
     dps:
       - id: 107

+ 2 - 0
custom_components/tuya_local/devices/beok_tr9b_thermostat.yaml

@@ -141,6 +141,7 @@ secondary_entities:
   - entity: number
     name: High temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer"
     dps:
       - id: 19
@@ -156,6 +157,7 @@ secondary_entities:
   - entity: number
     name: Low temperature limit
     category: config
+    class: temperature
     dps:
       - id: 26
         name: value

+ 1 - 0
custom_components/tuya_local/devices/bvf_cp1_heater.yaml

@@ -66,6 +66,7 @@ secondary_entities:
       - id: 27
         type: integer
         name: value
+        unit: C
         range:
           min: -9
           max: 9

+ 0 - 1
custom_components/tuya_local/devices/ecostrad_iqceramic_radiator.yaml

@@ -110,7 +110,6 @@ secondary_entities:
   - entity: number
     name: Calibration offset
     category: config
-    icon: "mdi:thermometer"
     dps:
       - id: 27
         type: integer

+ 2 - 0
custom_components/tuya_local/devices/etop_ht_thermostat.yaml

@@ -98,6 +98,7 @@ secondary_entities:
   - entity: number
     name: "Setpoint min."
     category: config
+    class: temperature
     mode: slider
     dps:
       - id: 26
@@ -114,6 +115,7 @@ secondary_entities:
   - entity: number
     name: "Setpoint max."
     category: config
+    class: temperature
     mode: slider
     dps:
       - id: 19

+ 5 - 0
custom_components/tuya_local/devices/hysen_hy08acf_thermostat.yaml

@@ -154,6 +154,7 @@ secondary_entities:
       - id: 102
         type: integer
         name: value
+        unit: C
         range:
           min: -90
           max: 90
@@ -162,22 +163,26 @@ secondary_entities:
   - entity: number
     name: Maximum temperature
     category: config
+    class: temperature
     icon: "mdi:temperature-chevron-up"
     dps:
       - id: 103
         type: integer
         name: value
+        unit: C
         range:
           min: 16
           max: 50
   - entity: number
     name: Minimum temperature
     category: config
+    class: temperature
     icon: "mdi:temperature-chevron-down"
     dps:
       - id: 104
         type: integer
         name: value
+        unit: C
         range:
           min: 5
           max: 15

+ 5 - 0
custom_components/tuya_local/devices/hysen_hy08we2_thermostat.yaml

@@ -138,6 +138,7 @@ secondary_entities:
   - entity: number
     name: Holiday temperature
     category: config
+    class: temperature
     dps:
       - id: 105
         type: integer
@@ -216,6 +217,7 @@ secondary_entities:
             value: F
   - entity: number
     name: High temperature protection
+    class: temperature
     category: config
     dps:
       - id: 112
@@ -241,6 +243,7 @@ secondary_entities:
   - entity: number
     name: Low temperature protection
     category: config
+    class: temperature
     dps:
       - id: 113
         type: integer
@@ -265,6 +268,7 @@ secondary_entities:
   - entity: number
     name: High temperature limit
     category: config
+    class: temperature
     dps:
       - id: 114
         type: integer
@@ -289,6 +293,7 @@ secondary_entities:
   - entity: number
     name: Low temperature limit
     category: config
+    class: temperature
     dps:
       - id: 115
         type: integer

+ 2 - 0
custom_components/tuya_local/devices/inkbird_itc306a_thermostat.yaml

@@ -153,6 +153,7 @@ secondary_entities:
   - entity: number
     name: High temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer-alert"
     dps:
       - id: 109
@@ -177,6 +178,7 @@ secondary_entities:
     name: Low temperature limit
     icon: "mdi:snowflake-alert"
     category: config
+    class: temperature
     dps:
       - id: 110
         name: value

+ 2 - 0
custom_components/tuya_local/devices/inkbird_itc308_thermostat.yaml

@@ -119,6 +119,7 @@ secondary_entities:
   - entity: number
     name: High temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer-alert"
     dps:
       - id: 109
@@ -143,6 +144,7 @@ secondary_entities:
     name: Low temperature limit
     icon: "mdi:snowflake-alert"
     category: config
+    class: temperature
     dps:
       - id: 110
         name: value

+ 1 - 0
custom_components/tuya_local/devices/jiahong_et72w_thermostat.yaml

@@ -188,6 +188,7 @@ secondary_entities:
             icon: "mdi:temperature-fahrenheit"
   - entity: number
     category: config
+    class: temperature
     name: Room temperature limit
     icon: "mdi:thermometer-chevron-down"
     dps:

+ 3 - 0
custom_components/tuya_local/devices/ledkia_fan_light.yaml

@@ -59,10 +59,13 @@ secondary_entities:
       - id: 58
         type: integer
         name: value
+        unit: "%"
         optional: true
         range:
           min: 10
           max: 1000
+        mapping:
+          - scale: 10
   - entity: number
     name: Fan timer
     icon: "mdi:timer"

+ 2 - 0
custom_components/tuya_local/devices/me80_thermostat.yaml

@@ -121,6 +121,7 @@ secondary_entities:
   - entity: number
     name: Maximum Temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 18
@@ -156,6 +157,7 @@ secondary_entities:
   - entity: number
     name: Minimum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-down"
     dps:
       - id: 20

+ 1 - 0
custom_components/tuya_local/devices/minco_mh1823d_thermostat.yaml

@@ -220,6 +220,7 @@ secondary_entities:
             value: F
   - entity: number
     category: config
+    class: temperature
     name: High temperature limit
     icon: "mdi:thermometer-alert"
     dps:

+ 1 - 1
custom_components/tuya_local/devices/moes_dimmer.yaml

@@ -24,7 +24,7 @@ secondary_entities:
       - id: 3
         type: integer
         name: value
-        unit: percent
+        unit: "%"
         range:
           min: 10
           max: 1000

+ 1 - 0
custom_components/tuya_local/devices/motion_sensor_light.yaml

@@ -80,6 +80,7 @@ secondary_entities:
     name: Light level
     icon: "mdi:theme-light-dark"
     category: config
+    class: illuminance
     dps:
       - id: 105
         type: integer

+ 1 - 0
custom_components/tuya_local/devices/nedis_pet_feeder.yaml

@@ -52,6 +52,7 @@ secondary_entities:
   - entity: number
     name: Weight
     category: config
+    class: weight
     icon: "mdi:scale"
     dps:
       - id: 110

+ 2 - 0
custom_components/tuya_local/devices/parkside_plgs2012a1_smart_charger.yaml

@@ -16,6 +16,7 @@ secondary_entities:
     name: Charge current
     icon: "mdi:current-dc"
     category: config
+    class: current
     dps:
       - id: 3
         type: integer
@@ -30,6 +31,7 @@ secondary_entities:
     name: Charge voltage
     icon: "mdi:battery-charging"
     category: config
+    class: voltage
     dps:
       - id: 4
         type: integer

+ 4 - 2
custom_components/tuya_local/devices/pgst_climate_sensor.yaml

@@ -57,6 +57,7 @@ secondary_entities:
   - entity: number
     name: Maximum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 10
@@ -69,6 +70,7 @@ secondary_entities:
   - entity: number
     name: Minimum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-down"
     dps:
       - id: 11
@@ -81,7 +83,7 @@ secondary_entities:
   - entity: number
     name: Maximum humidity
     category: config
-    icon: "mdi:water-percent"
+    class: humidity
     dps:
       - id: 12
         type: integer
@@ -93,7 +95,7 @@ secondary_entities:
   - entity: number
     name: Minimum humidity
     category: config
-    icon: "mdi:water-percent"
+    class: humidity
     dps:
       - id: 13
         type: integer

+ 1 - 0
custom_components/tuya_local/devices/pj1103_clamp_meter.yaml

@@ -66,6 +66,7 @@ secondary_entities:
   - entity: number
     name: Maximum Standby Power
     category: config
+    class: power
     dps:
       - id: 51
         type: integer

+ 2 - 0
custom_components/tuya_local/devices/salcar_t9w_thermostat.yaml

@@ -92,6 +92,7 @@ secondary_entities:
   - entity: number
     name: Maximum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 19
@@ -127,6 +128,7 @@ secondary_entities:
   - entity: number
     name: Minimum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-down"
     dps:
       - id: 26

+ 2 - 0
custom_components/tuya_local/devices/saswell_c16_thermostat.yaml

@@ -106,6 +106,7 @@ secondary_entities:
   - entity: number
     name: Floor temperature limit
     category: config
+    class: temperature
     icon: "mdi:thermometer-alert"
     dps:
       - id: 6
@@ -217,6 +218,7 @@ secondary_entities:
   - entity: number
     name: Power rating
     category: config
+    class: power
     icon: "mdi:signal"
     dps:
       - id: 22

+ 1 - 0
custom_components/tuya_local/devices/setti_czajnik_kettle.yaml

@@ -167,6 +167,7 @@ secondary_entities:
   - entity: number
     name: Boil temperature
     category: config
+    class: temperature
     icon: "mdi:coolant-temperature"
     dps:
       - id: 10

+ 2 - 0
custom_components/tuya_local/devices/t5e_wf_thermostat.yaml

@@ -194,6 +194,7 @@ secondary_entities:
   - entity: number
     name: Maximum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 18
@@ -231,6 +232,7 @@ secondary_entities:
   - entity: number
     name: Minimum temperature
     category: config
+    class: temperature
     icon: "mdi:thermometer-chevron-down"
     dps:
       - id: 20

+ 13 - 0
custom_components/tuya_local/number.py

@@ -5,6 +5,7 @@ from homeassistant.components.number import NumberEntity
 from homeassistant.components.number.const import (
     DEFAULT_MIN_VALUE,
     DEFAULT_MAX_VALUE,
+    NumberDeviceClass,
 )
 
 from .device import TuyaLocalDevice
@@ -45,6 +46,18 @@ class TuyaLocalNumber(TuyaLocalEntity, NumberEntity):
         self._max_dps = dps_map.pop("maximum", None)
         self._init_end(dps_map)
 
+    @property
+    def device_class(self):
+        """Return the class of this device"""
+        dclass = self._config.device_class
+        if dclass:
+            try:
+                return NumberDeviceClass(dclass)
+            except ValueError:
+                _LOGGER.warning(
+                    "Unrecognized number device class of %s ignored", dclass
+                )
+
     @property
     def native_min_value(self):
         if self._min_dps is not None:

+ 1 - 1
hacs.json

@@ -1,5 +1,5 @@
 {
   "name": "Tuya Local",
   "render_readme": true,
-  "homeassistant": "2022.11.0"
+  "homeassistant": "2023.2.0"
 }

+ 1 - 1
requirements-dev.txt

@@ -2,7 +2,7 @@ black
 fuzzywuzzy
 isort
 levenshtein
-pytest-homeassistant-custom-component>=0.12.42
+pytest-homeassistant-custom-component>=0.12.52
 pytest
 pytest-asyncio
 pytest-cov

+ 3 - 0
tests/devices/test_beok_tr9b_thermostat.py

@@ -3,6 +3,7 @@ from homeassistant.components.climate.const import (
     ClimateEntityFeature,
     HVACMode,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.const import PRECISION_TENTHS, UnitOfTemperature
 
 from ..const import BEOK_TR9B_PAYLOAD
@@ -102,6 +103,7 @@ class TestBeokTR9BThermostat(
                 {
                     "dps": MINTEMP_DPS,
                     "name": "number_low_temperature_limit",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 5.0,
                     "max": 1000.0,
                     "step": 1.0,
@@ -111,6 +113,7 @@ class TestBeokTR9BThermostat(
                 {
                     "dps": MAXTEMP_DPS,
                     "name": "number_high_temperature_limit",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 5.0,
                     "max": 1000.0,
                     "step": 1.0,

+ 6 - 0
tests/devices/test_hysen_hy08we2_thermostat.py

@@ -6,6 +6,7 @@ from homeassistant.components.climate.const import (
     HVACAction,
     HVACMode,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import UnitOfTime, UnitOfTemperature
 
@@ -137,6 +138,7 @@ class TestHysenHY08WE2Thermostat(
                 {
                     "dps": HOLIDAYTEMP_DPS,
                     "name": "number_holiday_temperature",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 5,
                     "max": 30,
                     "unit": UnitOfTemperature.CELSIUS,
@@ -169,6 +171,7 @@ class TestHysenHY08WE2Thermostat(
                 {
                     "dps": HIGHTEMP_DPS,
                     "name": "number_high_temperature_protection",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 35,
                     "max": 70,
                     "unit": UnitOfTemperature.CELSIUS,
@@ -176,6 +179,7 @@ class TestHysenHY08WE2Thermostat(
                 {
                     "dps": LOWTEMP_DPS,
                     "name": "number_low_temperature_protection",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 1,
                     "max": 10,
                     "unit": UnitOfTemperature.CELSIUS,
@@ -183,6 +187,7 @@ class TestHysenHY08WE2Thermostat(
                 {
                     "dps": MINTEMP_DPS,
                     "name": "number_low_temperature_limit",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 1,
                     "max": 10,
                     "unit": UnitOfTemperature.CELSIUS,
@@ -190,6 +195,7 @@ class TestHysenHY08WE2Thermostat(
                 {
                     "dps": MAXTEMP_DPS,
                     "name": "number_high_temperature_limit",
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 2,
                     "max": 70,
                     "unit": UnitOfTemperature.CELSIUS,

+ 3 - 0
tests/devices/test_inkbird_itc306a_thermostat.py

@@ -3,6 +3,7 @@ from homeassistant.components.climate.const import (
     ClimateEntityFeature,
     HVACAction,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.const import UnitOfTime, UnitOfTemperature
 
 
@@ -104,6 +105,7 @@ class TestInkbirdThermostat(
                 {
                     "name": "number_high_temperature_limit",
                     "dps": HIGH_THRES_DPS,
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "scale": 10,
                     "step": 0.1,
                     "min": -40,
@@ -113,6 +115,7 @@ class TestInkbirdThermostat(
                 {
                     "name": "number_low_temperature_limit",
                     "dps": LOW_THRES_DPS,
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "scale": 10,
                     "step": 0.1,
                     "min": -40,

+ 3 - 0
tests/devices/test_inkbird_itc308_thermostat.py

@@ -3,6 +3,7 @@ from homeassistant.components.climate.const import (
     ClimateEntityFeature,
     HVACAction,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.const import UnitOfTime, UnitOfTemperature
 
 
@@ -104,6 +105,7 @@ class TestInkbirdITC308Thermostat(
                 {
                     "name": "number_high_temperature_limit",
                     "dps": HIGH_THRES_DPS,
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "scale": 10,
                     "step": 0.1,
                     "min": -50,
@@ -113,6 +115,7 @@ class TestInkbirdITC308Thermostat(
                 {
                     "name": "number_low_temperature_limit",
                     "dps": LOW_THRES_DPS,
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "scale": 10,
                     "step": 0.1,
                     "min": -50,

+ 2 - 1
tests/devices/test_jiahong_et72w_thermostat.py

@@ -2,10 +2,10 @@ from homeassistant.components.climate.const import (
     ClimateEntityFeature,
     HVACMode,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.components.sensor import (
     SensorDeviceClass,
     STATE_CLASS_MEASUREMENT,
-    STATE_CLASS_TOTAL_INCREASING,
 )
 from homeassistant.const import (
     UnitOfEnergy,
@@ -98,6 +98,7 @@ class TestJiahongEt72wThermostat(
         self.setUpBasicNumber(
             TEMPLIMIT_DPS,
             self.entities.get("number_room_temperature_limit"),
+            device_class=NumberDeviceClass.TEMPERATURE,
             min=10.0,
             max=40.0,
             step=0.5,

+ 2 - 0
tests/devices/test_minco_mh1823d_thermostat.py

@@ -3,6 +3,7 @@ from homeassistant.components.climate.const import (
     HVACAction,
     HVACMode,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import UnitOfTemperature
 
@@ -100,6 +101,7 @@ class TestMincoMH1823DThermostat(
                 {
                     "name": "number_high_temperature_limit",
                     "dps": TEMPLIMIT_DPS,
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 5,
                     "max": 65,
                     "unit": UnitOfTemperature.CELSIUS,

+ 2 - 0
tests/devices/test_motion_sensor_light.py

@@ -1,3 +1,4 @@
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.const import LIGHT_LUX, UnitOfTime
 
 from ..const import MOTION_LIGHT_PAYLOAD
@@ -42,6 +43,7 @@ class TestMotionLight(BasicSwitchTests, MultiNumberTests, TuyaDeviceTestCase):
                 {
                     "dps": LUX_DPS,
                     "name": "number_light_level",
+                    "device_class": NumberDeviceClass.ILLUMINANCE,
                     "min": 0,
                     "max": 3900,
                     "unit": LIGHT_LUX,

+ 3 - 0
tests/devices/test_parkside_plgs2012a1_smart_charger.py

@@ -6,6 +6,7 @@ from homeassistant.const import (
     UnitOfTime,
     UnitOfTemperature,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.components.sensor import (
     SensorDeviceClass,
     STATE_CLASS_MEASUREMENT,
@@ -66,6 +67,7 @@ class TestParksidePLGS2012A1Charger(
                 {
                     "name": "number_charge_current",
                     "dps": CURRENT_DPS,
+                    "device_class": NumberDeviceClass.CURRENT,
                     "max": 30000,
                     "step": 100,
                     "unit": UnitOfElectricCurrent.MILLIAMPERE,
@@ -73,6 +75,7 @@ class TestParksidePLGS2012A1Charger(
                 {
                     "name": "number_charge_voltage",
                     "dps": VOLTAGE_DPS,
+                    "device_class": NumberDeviceClass.VOLTAGE,
                     "max": 25.0,
                     "scale": 1000,
                     "step": 0.1,

+ 3 - 0
tests/devices/test_saswell_c16_thermostat.py

@@ -5,6 +5,7 @@ from homeassistant.components.climate.const import (
     PRESET_AWAY,
     PRESET_HOME,
 )
+from homeassistant.components.number.const import NumberDeviceClass
 from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import UnitOfPower, UnitOfTemperature
 
@@ -78,6 +79,7 @@ class TestSaswellC16Thermostat(
                 {
                     "name": "number_floor_temperature_limit",
                     "dps": FLOORTEMPLIMIT_DPS,
+                    "device_class": NumberDeviceClass.TEMPERATURE,
                     "min": 20.0,
                     "max": 50.0,
                     "scale": 10,
@@ -87,6 +89,7 @@ class TestSaswellC16Thermostat(
                 {
                     "name": "number_power_rating",
                     "dps": POWERRATING_DPS,
+                    "device_class": NumberDeviceClass.POWER,
                     "max": 3500,
                     "unit": UnitOfPower.WATT,
                 },

+ 18 - 0
tests/mixins/number.py

@@ -14,6 +14,7 @@ class BasicNumberTests:
         scale=1,
         unit=None,
         testdata=None,
+        device_class=None,
     ):
         self.basicNumber = subject
         self.basicNumberDps = dps
@@ -24,6 +25,7 @@ class BasicNumberTests:
         self.basicNumberScale = scale
         self.basicNumberUnit = unit
         self.basicNumberTestData = testdata
+        self.basicNumberDevClass = device_class
 
     def test_number_min_value(self):
         self.assertEqual(self.basicNumber.native_min_value, self.basicNumberMin)
@@ -42,6 +44,12 @@ class BasicNumberTests:
             self.basicNumber.native_unit_of_measurement, self.basicNumberUnit
         )
 
+    def test_number_device_class(self):
+        self.assertEqual(
+            self.basicNumber.device_class,
+            self.basicNumberDevClass,
+        )
+
     def test_number_value(self):
         if self.basicNumberTestData:
             val = self.basicNumberTestData[0]
@@ -86,6 +94,7 @@ class MultiNumberTests:
         self.multiNumberScale = {}
         self.multiNumberUnit = {}
         self.multiNumberTestData = {}
+        self.multiNumberDevClass = {}
 
         for n in numbers:
             name = n.get("name")
@@ -101,6 +110,7 @@ class MultiNumberTests:
             self.multiNumberScale[name] = n.get("scale", 1)
             self.multiNumberUnit[name] = n.get("unit", None)
             self.multiNumberTestData[name] = n.get("testdata", None)
+            self.multiNumberDevClass[name] = n.get("device_class", None)
 
     def test_multi_number_min_value(self):
         for key, subject in self.multiNumber.items():
@@ -142,6 +152,14 @@ class MultiNumberTests:
                 f"{key} unit mismatch",
             )
 
+    def test_multi_number_device_class(self):
+        for key, subject in self.multiNumber.items():
+            self.assertEqual(
+                subject.device_class,
+                self.multiNumberDevClass[key],
+                f"{key} device class mismatch",
+            )
+
     def test_multi_number_value(self):
         for key, subject in self.multiNumber.items():
             if self.multiNumberTestData[key]: