Просмотр исходного кода

Use enums for device configs.

Since the required version has been bumped to 2022.2, we can now use the enums for device config that were introduced in 2021.12.
This prepares us for when the deprecated strings are removed in a future version like the entity category ones were in 2022.4.
Jason Rumney 3 лет назад
Родитель
Сommit
9315adf026
64 измененных файлов с 2439 добавлено и 2442 удалено
  1. 14 4
      custom_components/tuya_local/generic/binary_sensor.py
  2. 6 4
      custom_components/tuya_local/generic/cover.py
  3. 3 5
      custom_components/tuya_local/generic/humidifier.py
  4. 9 4
      custom_components/tuya_local/generic/sensor.py
  5. 3 7
      custom_components/tuya_local/generic/switch.py
  6. 0 2
      tests/devices/base_device_tests.py
  7. 3 2
      tests/devices/test_awow_th213_thermostat.py
  8. 4 4
      tests/devices/test_awow_th213v2_thermostat.py
  9. 2 2
      tests/devices/test_beca_bht002_thermostat.py
  10. 2 2
      tests/devices/test_beca_bht6000_thermostat.py
  11. 216 215
      tests/devices/test_beok_tr9b_thermostat.py
  12. 2 2
      tests/devices/test_bwt_heatpump.py
  13. 2 2
      tests/devices/test_digoo_dgsp01_dual_nightlight_switch.py
  14. 7 9
      tests/devices/test_digoo_dgsp202.py
  15. 2 2
      tests/devices/test_eanons_humidifier.py
  16. 3 4
      tests/devices/test_electriq_cd12_dehumidifier.py
  17. 2 2
      tests/devices/test_electriq_cd12pwv2_dehumidifier.py
  18. 3 4
      tests/devices/test_electriq_cd20_dehumidifier.py
  19. 3 4
      tests/devices/test_electriq_cd25_dehumidifier.py
  20. 2 2
      tests/devices/test_electriq_desd9lw_dehumidifier.py
  21. 2 2
      tests/devices/test_eurom_600_heater.py
  22. 2 2
      tests/devices/test_eurom_600v2_heater.py
  23. 2 2
      tests/devices/test_eurom_601_heater.py
  24. 2 2
      tests/devices/test_garage_door_opener.py
  25. 169 169
      tests/devices/test_gardenpac_heatpump.py
  26. 548 552
      tests/devices/test_goldair_dehumidifier.py
  27. 2 2
      tests/devices/test_goldair_geco_heater.py
  28. 2 2
      tests/devices/test_goldair_gpcv_heater.py
  29. 335 336
      tests/devices/test_goldair_gpph_heater.py
  30. 9 12
      tests/devices/test_grid_connect_double_power_point.py
  31. 2 2
      tests/devices/test_himox_h05_purifier.py
  32. 310 310
      tests/devices/test_hysen_hy08we2_thermostat.py
  33. 6 10
      tests/devices/test_inkbird_itc306a_thermostat.py
  34. 5 9
      tests/devices/test_inkbird_itc308_thermostat.py
  35. 2 2
      tests/devices/test_ips_pro_heatpump.py
  36. 256 260
      tests/devices/test_jjpro_jpd01_dehumidifier.py
  37. 6 7
      tests/devices/test_kogan_dehumidifier.py
  38. 6 6
      tests/devices/test_kogan_garage_door_opener.py
  39. 5 5
      tests/devices/test_logicom_powerstrip.py
  40. 9 11
      tests/devices/test_madimack_elitev3_heatpump.py
  41. 213 213
      tests/devices/test_madimack_heatpump.py
  42. 2 2
      tests/devices/test_minco_mh1823d_thermostat.py
  43. 6 8
      tests/devices/test_moes_rgb_socket.py
  44. 4 6
      tests/devices/test_parkside_plgs2012a1_smart_charger.py
  45. 137 137
      tests/devices/test_poiema_one_purifier.py
  46. 2 2
      tests/devices/test_poolex_silverline_heatpump.py
  47. 2 2
      tests/devices/test_poolex_vertigo_heatpump.py
  48. 2 2
      tests/devices/test_qoto_03_sprinkler.py
  49. 2 2
      tests/devices/test_remora_heatpump.py
  50. 2 2
      tests/devices/test_renpho_rp_ap001s.py
  51. 3 2
      tests/devices/test_saswell_c16_thermostat.py
  52. 2 2
      tests/devices/test_sd123_hpr01_presence.py
  53. 2 2
      tests/devices/test_simple_blinds.py
  54. 2 2
      tests/devices/test_simple_switch_with_timer.py
  55. 21 29
      tests/devices/test_smartmcb_smt006_energymeter.py
  56. 6 8
      tests/devices/test_smartplugv1.py
  57. 6 8
      tests/devices/test_smartplugv2.py
  58. 9 12
      tests/devices/test_smartplugv2_energy.py
  59. 2 2
      tests/devices/test_vork_vk6067aw_purifier.py
  60. 2 2
      tests/devices/test_wetair_wawh1210lw_humidifier.py
  61. 4 4
      tests/devices/test_woox_r4028_powerstrip.py
  62. 13 2
      tests/mixins/binary_sensor.py
  63. 13 2
      tests/mixins/sensor.py
  64. 14 4
      tests/mixins/switch.py

+ 14 - 4
custom_components/tuya_local/generic/binary_sensor.py

@@ -1,12 +1,18 @@
 """
 Platform to read Tuya binary sensors.
 """
-from homeassistant.components.binary_sensor import DEVICE_CLASSES, BinarySensorEntity
+from homeassistant.components.binary_sensor import (
+    BinarySensorEntity,
+    BinarySensorDeviceClass,
+)
+import logging
 
 from ..device import TuyaLocalDevice
 from ..helpers.device_config import TuyaEntityConfig
 from ..helpers.mixin import TuyaLocalEntity
 
+_LOGGER = logging.getLogger(__name__)
+
 
 class TuyaLocalBinarySensor(TuyaLocalEntity, BinarySensorEntity):
     """Representation of a Tuya Binary Sensor"""
@@ -28,9 +34,13 @@ class TuyaLocalBinarySensor(TuyaLocalEntity, BinarySensorEntity):
     def device_class(self):
         """Return the class of this device"""
         dclass = self._config.device_class
-        if dclass in DEVICE_CLASSES:
-            return dclass
-        else:
+        try:
+            return BinarySensorDeviceClass(dclass)
+        except ValueError:
+            if dclass:
+                _LOGGER.warning(
+                    f"Unrecognised binary_sensor device class of {dclass} ignored"
+                )
             return None
 
     @property

+ 6 - 4
custom_components/tuya_local/generic/cover.py

@@ -5,7 +5,7 @@ import logging
 
 from homeassistant.components.cover import (
     CoverEntity,
-    DEVICE_CLASSES,
+    CoverDeviceClass,
     SUPPORT_CLOSE,
     SUPPORT_OPEN,
     SUPPORT_SET_POSITION,
@@ -53,9 +53,11 @@ class TuyaLocalCover(TuyaLocalEntity, CoverEntity):
     def device_class(self):
         """Return the class of ths device"""
         dclass = self._config.device_class
-        if dclass in DEVICE_CLASSES:
-            return dclass
-        else:
+        try:
+            return CoverDeviceClass(dclass)
+        except ValueError:
+            if dclass:
+                _LOGGER.warning(f"Unrecognised cover device class of {dclass} ignored")
             return None
 
     @property

+ 3 - 5
custom_components/tuya_local/generic/humidifier.py

@@ -3,12 +3,10 @@ Platform to control tuya humidifier and dehumidifier devices.
 """
 import logging
 
-from homeassistant.components.humidifier import HumidifierEntity
+from homeassistant.components.humidifier import HumidifierEntity, HumidifierDeviceClass
 from homeassistant.components.humidifier.const import (
     DEFAULT_MAX_HUMIDITY,
     DEFAULT_MIN_HUMIDITY,
-    DEVICE_CLASS_DEHUMIDIFIER,
-    DEVICE_CLASS_HUMIDIFIER,
     SUPPORT_MODES,
 )
 
@@ -48,9 +46,9 @@ class TuyaLocalHumidifier(TuyaLocalEntity, HumidifierEntity):
     def device_class(self):
         """Return the class of this device"""
         return (
-            DEVICE_CLASS_DEHUMIDIFIER
+            HumidifierDeviceClass.DEHUMIDIFIER
             if self._config.device_class == "dehumidifier"
-            else DEVICE_CLASS_HUMIDIFIER
+            else HumidifierDeviceClass.HUMIDIFIER
         )
 
     @property

+ 9 - 4
custom_components/tuya_local/generic/sensor.py

@@ -2,15 +2,18 @@
 Platform to read Tuya sensors.
 """
 from homeassistant.components.sensor import (
-    DEVICE_CLASSES,
+    SensorDeviceClass,
     SensorEntity,
     STATE_CLASSES,
 )
+import logging
 
 from ..device import TuyaLocalDevice
 from ..helpers.device_config import TuyaEntityConfig
 from ..helpers.mixin import TuyaLocalEntity, unit_from_ascii
 
+_LOGGER = logging.getLogger(__name__)
+
 
 class TuyaLocalSensor(TuyaLocalEntity, SensorEntity):
     """Representation of a Tuya Sensor"""
@@ -34,9 +37,11 @@ class TuyaLocalSensor(TuyaLocalEntity, SensorEntity):
     def device_class(self):
         """Return the class of this device"""
         dclass = self._config.device_class
-        if dclass in DEVICE_CLASSES:
-            return dclass
-        else:
+        try:
+            return SensorDeviceClass(dclass)
+        except ValueError:
+            if dclass:
+                _LOGGER.warning(f"Unrecognized sensor device class of {dclass} ignored")
             return None
 
     @property

+ 3 - 7
custom_components/tuya_local/generic/switch.py

@@ -3,11 +3,7 @@ Platform to control Tuya switches.
 Initially based on the Kogan Switch and secondary switch for Purline M100
 heater open window detector toggle.
 """
-from homeassistant.components.switch import SwitchEntity
-from homeassistant.components.switch import (
-    DEVICE_CLASS_OUTLET,
-    DEVICE_CLASS_SWITCH,
-)
+from homeassistant.components.switch import SwitchEntity, SwitchDeviceClass
 
 from homeassistant.const import STATE_UNAVAILABLE
 
@@ -34,9 +30,9 @@ class TuyaLocalSwitch(TuyaLocalEntity, SwitchEntity):
     def device_class(self):
         """Return the class of this device"""
         return (
-            DEVICE_CLASS_OUTLET
+            SwitchDeviceClass.OUTLET
             if self._config.device_class == "outlet"
-            else DEVICE_CLASS_SWITCH
+            else SwitchDeviceClass.SWITCH
         )
 
     @property

+ 0 - 2
tests/devices/base_device_tests.py

@@ -22,8 +22,6 @@ from custom_components.tuya_local.helpers.device_config import (
     possible_matches,
 )
 
-from ..helpers import assert_device_properties_set
-
 DEVICE_TYPES = {
     "binary_sensor": TuyaLocalBinarySensor,
     "climate": TuyaLocalClimate,

+ 3 - 2
tests/devices/test_awow_th213_thermostat.py

@@ -7,8 +7,9 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
+
 from homeassistant.const import (
-    DEVICE_CLASS_TEMPERATURE,
     STATE_UNAVAILABLE,
     TEMP_CELSIUS,
 )
@@ -62,7 +63,7 @@ class TestAwowTH213Thermostat(
             EXTERNTEMP_DPS,
             self.entities.get("sensor_external_temperature"),
             unit=TEMP_CELSIUS,
-            device_class=DEVICE_CLASS_TEMPERATURE,
+            device_class=SensorDeviceClass.TEMPERATURE,
             state_class="measurement",
         )
         self.setUpBasicSelect(

+ 4 - 4
tests/devices/test_awow_th213v2_thermostat.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     CURRENT_HVAC_HEAT,
     CURRENT_HVAC_IDLE,
@@ -8,8 +8,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_TEMPERATURE,
     STATE_UNAVAILABLE,
     TEMP_CELSIUS,
 )
@@ -63,7 +63,7 @@ class TestAwowTH213v2Thermostat(
             EXTERNTEMP_DPS,
             self.entities.get("sensor_external_temperature"),
             unit=TEMP_CELSIUS,
-            device_class=DEVICE_CLASS_TEMPERATURE,
+            device_class=SensorDeviceClass.TEMPERATURE,
             state_class="measurement",
         )
         self.setUpBasicSelect(
@@ -78,7 +78,7 @@ class TestAwowTH213v2Thermostat(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.setUpMultiNumber(

+ 2 - 2
tests/devices/test_beca_bht002_thermostat.py

@@ -7,8 +7,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_TEMPERATURE,
     STATE_UNAVAILABLE,
     TEMP_CELSIUS,
 )
@@ -59,7 +59,7 @@ class TestBecaBHT002Thermostat(
             FLOOR_DPS,
             self.entities.get("sensor_external_temperature"),
             unit=TEMP_CELSIUS,
-            device_class=DEVICE_CLASS_TEMPERATURE,
+            device_class=SensorDeviceClass.TEMPERATURE,
             state_class="measurement",
             testdata=(30, 15),
         )

+ 2 - 2
tests/devices/test_beca_bht6000_thermostat.py

@@ -7,8 +7,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_TEMPERATURE,
     STATE_UNAVAILABLE,
     TEMP_CELSIUS,
 )
@@ -56,7 +56,7 @@ class TestBecaBHT6000Thermostat(
             FLOOR_DPS,
             self.entities.get("sensor_external_temperature"),
             unit=TEMP_CELSIUS,
-            device_class=DEVICE_CLASS_TEMPERATURE,
+            device_class=SensorDeviceClass.TEMPERATURE,
             state_class="measurement",
             testdata=(36, 18),
         )

+ 216 - 215
tests/devices/test_beok_tr9b_thermostat.py

@@ -1,215 +1,216 @@
-from homeassistant.components.climate.const import (
-    HVAC_MODE_AUTO,
-    HVAC_MODE_HEAT,
-    HVAC_MODE_OFF,
-    SUPPORT_TARGET_TEMPERATURE,
-)
-from homeassistant.const import STATE_UNAVAILABLE, TEMP_CELSIUS, TEMP_FAHRENHEIT
-
-from ..const import BEOK_TR9B_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.climate import TargetTemperatureTests
-from ..mixins.binary_sensor import MultiBinarySensorTests
-from ..mixins.lock import BasicLockTests
-from ..mixins.number import MultiNumberTests
-from ..mixins.select import MultiSelectTests
-from ..mixins.switch import BasicSwitchTests
-from .base_device_tests import TuyaDeviceTestCase
-
-POWER_DPS = "1"
-HVACMODE_DPS = "2"
-ANTIFROST_DPS = "10"
-TEMPERATURE_DPS = "16"
-MAXTEMP_DPS = "19"
-UNIT_DPS = "23"
-CURRENTTEMP_DPS = "24"
-MINTEMP_DPS = "26"
-SCHED_DPS = "31"
-VALVE_DPS = "36"
-LOCK_DPS = "40"
-ERROR_DPS = "45"
-UNKNOWN101_DPS = "101"
-UNKNOWN102_DPS = "102"
-
-
-class TestBeokTR9BThermostat(
-    MultiBinarySensorTests,
-    BasicLockTests,
-    MultiNumberTests,
-    MultiSelectTests,
-    BasicSwitchTests,
-    TargetTemperatureTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig(
-            "beok_tr9b_thermostat.yaml",
-            BEOK_TR9B_PAYLOAD,
-        )
-        self.subject = self.entities.get("climate")
-        self.setUpTargetTemperature(
-            TEMPERATURE_DPS,
-            self.subject,
-            min=41.0,
-            max=99.0,
-            scale=10,
-            step=10,
-        )
-        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
-        self.setUpMultiSelect(
-            [
-                {
-                    "dps": SCHED_DPS,
-                    "name": "select_schedule",
-                    "options": {
-                        "5_2": "Weekday+Weekend",
-                        "6_1": "Mon-Sat+Sun",
-                        "7": "Daily",
-                    },
-                },
-                {
-                    "dps": UNIT_DPS,
-                    "name": "select_temperature_unit",
-                    "options": {
-                        "c": "Celsius",
-                        "f": "Fahrenheit",
-                    },
-                },
-            ],
-        )
-        self.setUpBasicSwitch(
-            ANTIFROST_DPS,
-            self.entities.get("switch_anti_frost"),
-        )
-        self.setUpMultiBinarySensors(
-            [
-                {
-                    "dps": ERROR_DPS,
-                    "name": "binary_sensor_error",
-                    "device_class": "problem",
-                    "testdata": (1, 0),
-                },
-                {
-                    "dps": VALVE_DPS,
-                    "name": "binary_sensor_valve",
-                    "device_class": "opening",
-                    "testdata": ("open", "close"),
-                },
-            ],
-        )
-        self.setUpMultiNumber(
-            [
-                {
-                    "dps": MINTEMP_DPS,
-                    "name": "number_low_temperature_limit",
-                    "min": 5.0,
-                    "max": 1000.0,
-                    "step": 1.0,
-                    "scale": 10,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": MAXTEMP_DPS,
-                    "name": "number_high_temperature_limit",
-                    "min": 5.0,
-                    "max": 1000.0,
-                    "step": 1.0,
-                    "scale": 10,
-                    "unit": TEMP_CELSIUS,
-                },
-            ],
-        )
-        self.mark_secondary(
-            [
-                "binary_sensor_error",
-                "binary_sensor_valve",
-                "lock_child_lock",
-                "number_low_temperature_limit",
-                "number_high_temperature_limit",
-                "select_schedule",
-                "select_temperature_unit",
-                "switch_anti_frost",
-            ],
-        )
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_TARGET_TEMPERATURE,
-        )
-
-    def test_temperature_unit(self):
-        self.dps[UNIT_DPS] = "c"
-        self.assertEqual(
-            self.subject.temperature_unit,
-            TEMP_CELSIUS,
-        )
-        self.assertEqual(self.subject.target_temperature_step, 0.5)
-
-        self.dps[UNIT_DPS] = "f"
-        self.assertEqual(
-            self.subject.temperature_unit,
-            TEMP_FAHRENHEIT,
-        )
-        self.assertEqual(self.subject.target_temperature_step, 1.0)
-
-    def test_current_temperature(self):
-        self.dps[CURRENTTEMP_DPS] = 685
-        self.assertEqual(self.subject.current_temperature, 68.5)
-
-    def test_hvac_mode(self):
-        self.dps[POWER_DPS] = False
-        self.dps[HVACMODE_DPS] = "auto"
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[POWER_DPS] = True
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_AUTO)
-
-        self.dps[HVACMODE_DPS] = "manual"
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
-
-        self.dps[HVACMODE_DPS] = None
-        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_hvac_modes(self):
-        self.assertCountEqual(
-            self.subject.hvac_modes,
-            [
-                HVAC_MODE_HEAT,
-                HVAC_MODE_AUTO,
-                HVAC_MODE_OFF,
-            ],
-        )
-
-    # Override - since min and max are set by attributes, the range
-    # allowed when setting is wider than normal.  The thermostat seems
-    # to be configurable as at least a water heater (to 212F), as tuya
-    # doc says max 1000.0 (after scaling)
-    async def test_set_target_temperature_fails_outside_valid_range(self):
-        with self.assertRaisesRegex(
-            ValueError,
-            f"temperature \\(4.5\\) must be between 5.0 and 1000.0",
-        ):
-            await self.subject.async_set_target_temperature(4.5)
-        with self.assertRaisesRegex(
-            ValueError,
-            f"temperature \\(1001\\) must be between 5.0 and 1000.0",
-        ):
-            await self.subject.async_set_target_temperature(1001)
-
-    def test_extra_state_attributes(self):
-        self.dps[ERROR_DPS] = 8
-        self.dps[UNKNOWN101_DPS] = 101
-        self.dps[UNKNOWN102_DPS] = 102
-        self.assertDictEqual(
-            self.subject.extra_state_attributes,
-            {"Error Code": 8, "unknown_101": 101, "unknown_102": 102},
-        )
-
-    def test_icons(self):
-        self.dps[LOCK_DPS] = True
-        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right-off")
-        self.dps[LOCK_DPS] = False
-        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right")
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
+from homeassistant.components.climate.const import (
+    HVAC_MODE_AUTO,
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.const import STATE_UNAVAILABLE, TEMP_CELSIUS, TEMP_FAHRENHEIT
+
+from ..const import BEOK_TR9B_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.binary_sensor import MultiBinarySensorTests
+from ..mixins.lock import BasicLockTests
+from ..mixins.number import MultiNumberTests
+from ..mixins.select import MultiSelectTests
+from ..mixins.switch import BasicSwitchTests
+from .base_device_tests import TuyaDeviceTestCase
+
+POWER_DPS = "1"
+HVACMODE_DPS = "2"
+ANTIFROST_DPS = "10"
+TEMPERATURE_DPS = "16"
+MAXTEMP_DPS = "19"
+UNIT_DPS = "23"
+CURRENTTEMP_DPS = "24"
+MINTEMP_DPS = "26"
+SCHED_DPS = "31"
+VALVE_DPS = "36"
+LOCK_DPS = "40"
+ERROR_DPS = "45"
+UNKNOWN101_DPS = "101"
+UNKNOWN102_DPS = "102"
+
+
+class TestBeokTR9BThermostat(
+    MultiBinarySensorTests,
+    BasicLockTests,
+    MultiNumberTests,
+    MultiSelectTests,
+    BasicSwitchTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig(
+            "beok_tr9b_thermostat.yaml",
+            BEOK_TR9B_PAYLOAD,
+        )
+        self.subject = self.entities.get("climate")
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=41.0,
+            max=99.0,
+            scale=10,
+            step=10,
+        )
+        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
+        self.setUpMultiSelect(
+            [
+                {
+                    "dps": SCHED_DPS,
+                    "name": "select_schedule",
+                    "options": {
+                        "5_2": "Weekday+Weekend",
+                        "6_1": "Mon-Sat+Sun",
+                        "7": "Daily",
+                    },
+                },
+                {
+                    "dps": UNIT_DPS,
+                    "name": "select_temperature_unit",
+                    "options": {
+                        "c": "Celsius",
+                        "f": "Fahrenheit",
+                    },
+                },
+            ],
+        )
+        self.setUpBasicSwitch(
+            ANTIFROST_DPS,
+            self.entities.get("switch_anti_frost"),
+        )
+        self.setUpMultiBinarySensors(
+            [
+                {
+                    "dps": ERROR_DPS,
+                    "name": "binary_sensor_error",
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
+                    "testdata": (1, 0),
+                },
+                {
+                    "dps": VALVE_DPS,
+                    "name": "binary_sensor_valve",
+                    "device_class": BinarySensorDeviceClass.OPENING,
+                    "testdata": ("open", "close"),
+                },
+            ],
+        )
+        self.setUpMultiNumber(
+            [
+                {
+                    "dps": MINTEMP_DPS,
+                    "name": "number_low_temperature_limit",
+                    "min": 5.0,
+                    "max": 1000.0,
+                    "step": 1.0,
+                    "scale": 10,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": MAXTEMP_DPS,
+                    "name": "number_high_temperature_limit",
+                    "min": 5.0,
+                    "max": 1000.0,
+                    "step": 1.0,
+                    "scale": 10,
+                    "unit": TEMP_CELSIUS,
+                },
+            ],
+        )
+        self.mark_secondary(
+            [
+                "binary_sensor_error",
+                "binary_sensor_valve",
+                "lock_child_lock",
+                "number_low_temperature_limit",
+                "number_high_temperature_limit",
+                "select_schedule",
+                "select_temperature_unit",
+                "switch_anti_frost",
+            ],
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_TARGET_TEMPERATURE,
+        )
+
+    def test_temperature_unit(self):
+        self.dps[UNIT_DPS] = "c"
+        self.assertEqual(
+            self.subject.temperature_unit,
+            TEMP_CELSIUS,
+        )
+        self.assertEqual(self.subject.target_temperature_step, 0.5)
+
+        self.dps[UNIT_DPS] = "f"
+        self.assertEqual(
+            self.subject.temperature_unit,
+            TEMP_FAHRENHEIT,
+        )
+        self.assertEqual(self.subject.target_temperature_step, 1.0)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 685
+        self.assertEqual(self.subject.current_temperature, 68.5)
+
+    def test_hvac_mode(self):
+        self.dps[POWER_DPS] = False
+        self.dps[HVACMODE_DPS] = "auto"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
+
+        self.dps[POWER_DPS] = True
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_AUTO)
+
+        self.dps[HVACMODE_DPS] = "manual"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(
+            self.subject.hvac_modes,
+            [
+                HVAC_MODE_HEAT,
+                HVAC_MODE_AUTO,
+                HVAC_MODE_OFF,
+            ],
+        )
+
+    # Override - since min and max are set by attributes, the range
+    # allowed when setting is wider than normal.  The thermostat seems
+    # to be configurable as at least a water heater (to 212F), as tuya
+    # doc says max 1000.0 (after scaling)
+    async def test_set_target_temperature_fails_outside_valid_range(self):
+        with self.assertRaisesRegex(
+            ValueError,
+            f"temperature \\(4.5\\) must be between 5.0 and 1000.0",
+        ):
+            await self.subject.async_set_target_temperature(4.5)
+        with self.assertRaisesRegex(
+            ValueError,
+            f"temperature \\(1001\\) must be between 5.0 and 1000.0",
+        ):
+            await self.subject.async_set_target_temperature(1001)
+
+    def test_extra_state_attributes(self):
+        self.dps[ERROR_DPS] = 8
+        self.dps[UNKNOWN101_DPS] = 101
+        self.dps[UNKNOWN102_DPS] = 102
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {"Error Code": 8, "unknown_101": 101, "unknown_102": 102},
+        )
+
+    def test_icons(self):
+        self.dps[LOCK_DPS] = True
+        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right-off")
+        self.dps[LOCK_DPS] = False
+        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right")

+ 2 - 2
tests/devices/test_bwt_heatpump.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -39,7 +39,7 @@ class TestBWTHeatpump(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_water_flow"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(["binary_sensor_water_flow"])

+ 2 - 2
tests/devices/test_digoo_dgsp01_dual_nightlight_switch.py

@@ -1,5 +1,5 @@
 """Tests for the switch entity."""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.components.light import (
     COLOR_MODE_RGBW,
     COLOR_MODE_WHITE,
@@ -36,7 +36,7 @@ class TestDigooNightlightSwitch(BasicSwitchTests, TuyaDeviceTestCase):
         self.light = self.entities.get("light_night_light")
 
         self.setUpBasicSwitch(
-            SWITCH_DPS, self.subject, device_class=DEVICE_CLASS_OUTLET
+            SWITCH_DPS, self.subject, device_class=SwitchDeviceClass.OUTLET
         )
 
     def test_light_is_on(self):

+ 7 - 9
tests/devices/test_digoo_dgsp202.py

@@ -1,9 +1,7 @@
 """Tests for Digoo DSSP202 dual switch with timers and energy monitoring"""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.switch import SwitchDeviceClass
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_VOLTAGE,
     ELECTRIC_CURRENT_MILLIAMPERE,
     ELECTRIC_POTENTIAL_VOLT,
     POWER_WATT,
@@ -37,14 +35,14 @@ class TestDigooDGSP202Switch(
                 {
                     "dps": SWITCH1_DPS,
                     "name": "switch_outlet_1",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                     "power_dps": POWER_DPS,
                     "power_scale": 10,
                 },
                 {
                     "dps": SWITCH2_DPS,
                     "name": "switch_outlet_2",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
             ]
         )
@@ -72,7 +70,7 @@ class TestDigooDGSP202Switch(
                     "name": "sensor_voltage",
                     "dps": VOLTAGE_DPS,
                     "unit": ELECTRIC_POTENTIAL_VOLT,
-                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "device_class": SensorDeviceClass.VOLTAGE,
                     "state_class": "measurement",
                     "testdata": (2300, 230.0),
                 },
@@ -80,14 +78,14 @@ class TestDigooDGSP202Switch(
                     "name": "sensor_current",
                     "dps": CURRENT_DPS,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_power",
                     "dps": POWER_DPS,
                     "unit": POWER_WATT,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": SensorDeviceClass.POWER,
                     "state_class": "measurement",
                     "testdata": (1234, 123.4),
                 },

+ 2 - 2
tests/devices/test_eanons_humidifier.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     FAN_HIGH,
     FAN_MEDIUM,
@@ -83,7 +83,7 @@ class TestEanonsHumidifier(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_tank"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(["select_timer", "sensor_timer", "binary_sensor_tank"])

+ 3 - 4
tests/devices/test_electriq_cd12_dehumidifier.py

@@ -1,7 +1,6 @@
 from homeassistant.components.humidifier import SUPPORT_MODES
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
-    DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     TEMP_CELSIUS,
 )
@@ -39,14 +38,14 @@ class TestElectriqCD12PWDehumidifier(
                     "name": "sensor_current_temperature",
                     "dps": CURRENTTEMP_DPS,
                     "unit": TEMP_CELSIUS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_current_humidity",
                     "dps": CURRENTHUMID_DPS,
                     "unit": PERCENTAGE,
-                    "device_class": DEVICE_CLASS_HUMIDITY,
+                    "device_class": SensorDeviceClass.HUMIDITY,
                     "state_class": "measurement",
                 },
             ]

+ 2 - 2
tests/devices/test_electriq_cd12pwv2_dehumidifier.py

@@ -1,6 +1,6 @@
 from homeassistant.components.humidifier import SUPPORT_MODES
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
     PERCENTAGE,
 )
 
@@ -46,7 +46,7 @@ class TestElectriqCD12PWV2Dehumidifier(
             CURRENTHUMID_DPS,
             self.entities.get("sensor_current_humidity"),
             unit=PERCENTAGE,
-            device_class=DEVICE_CLASS_HUMIDITY,
+            device_class=SensorDeviceClass.HUMIDITY,
             state_class="measurement",
         )
         self.setUpBasicSwitch(

+ 3 - 4
tests/devices/test_electriq_cd20_dehumidifier.py

@@ -1,8 +1,7 @@
 from homeassistant.components.fan import SUPPORT_PRESET_MODE
 from homeassistant.components.humidifier import SUPPORT_MODES
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
-    DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     TEMP_CELSIUS,
 )
@@ -54,14 +53,14 @@ class TestElectriqCD20ProDehumidifier(
                     "name": "sensor_current_temperature",
                     "dps": CURRENTTEMP_DPS,
                     "unit": TEMP_CELSIUS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_current_humidity",
                     "dps": CURRENTHUMID_DPS,
                     "unit": PERCENTAGE,
-                    "device_class": DEVICE_CLASS_HUMIDITY,
+                    "device_class": SensorDeviceClass.HUMIDITY,
                     "state_class": "measurement",
                 },
             ]

+ 3 - 4
tests/devices/test_electriq_cd25_dehumidifier.py

@@ -1,8 +1,7 @@
 from homeassistant.components.fan import SUPPORT_PRESET_MODE
 from homeassistant.components.humidifier import SUPPORT_MODES
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
-    DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     TEMP_CELSIUS,
 )
@@ -52,14 +51,14 @@ class TestElectriqCD25ProDehumidifier(
                     "name": "sensor_current_temperature",
                     "dps": CURRENTTEMP_DPS,
                     "unit": TEMP_CELSIUS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_current_humidity",
                     "dps": CURRENTHUMID_DPS,
                     "unit": PERCENTAGE,
-                    "device_class": DEVICE_CLASS_HUMIDITY,
+                    "device_class": SensorDeviceClass.HUMIDITY,
                     "state_class": "measurement",
                 },
             ]

+ 2 - 2
tests/devices/test_electriq_desd9lw_dehumidifier.py

@@ -9,8 +9,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_TARGET_HUMIDITY,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
     PERCENTAGE,
     STATE_UNAVAILABLE,
 )
@@ -62,7 +62,7 @@ class TestElectriqDESD9LWDehumidifier(
             CURRENTHUM_DPS,
             self.entities.get("sensor_current_humidity"),
             unit=PERCENTAGE,
-            device_class=DEVICE_CLASS_HUMIDITY,
+            device_class=SensorDeviceClass.HUMIDITY,
             state_class="measurement",
         )
 

+ 2 - 2
tests/devices/test_eurom_600_heater.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -35,7 +35,7 @@ class TestEurom600Heater(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(["binary_sensor_error"])

+ 2 - 2
tests/devices/test_eurom_600v2_heater.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -35,7 +35,7 @@ class TestEurom600Heater(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(["binary_sensor_error"])

+ 2 - 2
tests/devices/test_eurom_601_heater.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -39,7 +39,7 @@ class TestEurom601Heater(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(["binary_sensor_error"])

+ 2 - 2
tests/devices/test_garage_door_opener.py

@@ -1,6 +1,6 @@
 """Tests for the simple garage door opener."""
 from homeassistant.components.cover import (
-    DEVICE_CLASS_GARAGE,
+    CoverDeviceClass,
     SUPPORT_CLOSE,
     SUPPORT_OPEN,
 )
@@ -21,7 +21,7 @@ class TestSimpleGarageOpener(TuyaDeviceTestCase):
         self.subject = self.entities["cover"]
 
     def test_device_class_is_garage(self):
-        self.assertEqual(self.subject.device_class, DEVICE_CLASS_GARAGE)
+        self.assertEqual(self.subject.device_class, CoverDeviceClass.GARAGE)
 
     def test_supported_features(self):
         self.assertEqual(

+ 169 - 169
tests/devices/test_gardenpac_heatpump.py

@@ -1,169 +1,169 @@
-from homeassistant.components.climate.const import (
-    HVAC_MODE_HEAT,
-    HVAC_MODE_OFF,
-    CURRENT_HVAC_HEAT,
-    CURRENT_HVAC_IDLE,
-    CURRENT_HVAC_OFF,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_TARGET_TEMPERATURE,
-)
-from homeassistant.const import (
-    DEVICE_CLASS_POWER_FACTOR,
-    PERCENTAGE,
-    STATE_UNAVAILABLE,
-    TEMP_CELSIUS,
-    TEMP_FAHRENHEIT,
-)
-
-from ..const import GARDENPAC_HEATPUMP_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.climate import TargetTemperatureTests
-from ..mixins.sensor import BasicSensorTests
-from .base_device_tests import TuyaDeviceTestCase
-
-HVACMODE_DPS = "1"
-CURRENTTEMP_DPS = "102"
-UNITS_DPS = "103"
-POWERLEVEL_DPS = "104"
-OPMODE_DPS = "105"
-TEMPERATURE_DPS = "106"
-UNKNOWN107_DPS = "107"
-UNKNOWN108_DPS = "108"
-UNKNOWN115_DPS = "115"
-UNKNOWN116_DPS = "116"
-PRESET_DPS = "117"
-
-
-class TestGardenPACPoolHeatpump(
-    BasicSensorTests,
-    TargetTemperatureTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig("gardenpac_heatpump.yaml", GARDENPAC_HEATPUMP_PAYLOAD)
-        self.subject = self.entities.get("climate")
-        self.setUpTargetTemperature(
-            TEMPERATURE_DPS,
-            self.subject,
-            min=18,
-            max=45,
-        )
-        self.setUpBasicSensor(
-            POWERLEVEL_DPS,
-            self.entities.get("sensor_power_level"),
-            unit=PERCENTAGE,
-            device_class=DEVICE_CLASS_POWER_FACTOR,
-            state_class="measurement",
-        )
-        self.mark_secondary(["sensor_power_level"])
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE,
-        )
-
-    def test_icon(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.icon, "mdi:hot-tub")
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.icon, "mdi:hvac-off")
-
-    def test_temperature_unit(self):
-        self.dps[UNITS_DPS] = False
-        self.assertEqual(self.subject.temperature_unit, TEMP_FAHRENHEIT)
-        self.dps[UNITS_DPS] = True
-        self.assertEqual(self.subject.temperature_unit, TEMP_CELSIUS)
-
-    def test_minimum_fahrenheit_temperature(self):
-        self.dps[UNITS_DPS] = False
-        self.assertEqual(self.subject.min_temp, 60)
-
-    def test_maximum_fahrenheit_temperature(self):
-        self.dps[UNITS_DPS] = False
-        self.assertEqual(self.subject.max_temp, 115)
-
-    def test_current_temperature(self):
-        self.dps[CURRENTTEMP_DPS] = 25
-        self.assertEqual(self.subject.current_temperature, 25)
-
-    def test_hvac_mode(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[HVACMODE_DPS] = None
-        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_hvac_modes(self):
-        self.assertCountEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT])
-
-    async def test_turn_on(self):
-        async with assert_device_properties_set(
-            self.subject._device, {HVACMODE_DPS: True}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
-
-    async def test_turn_off(self):
-        async with assert_device_properties_set(
-            self.subject._device, {HVACMODE_DPS: False}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
-
-    def test_preset_mode(self):
-        self.dps[PRESET_DPS] = False
-        self.assertEqual(self.subject.preset_mode, "Silent")
-
-        self.dps[PRESET_DPS] = True
-        self.assertEqual(self.subject.preset_mode, "Smart")
-
-        self.dps[PRESET_DPS] = None
-        self.assertIs(self.subject.preset_mode, None)
-
-    def test_preset_modes(self):
-        self.assertCountEqual(self.subject.preset_modes, ["Silent", "Smart"])
-
-    async def test_set_preset_mode_to_silent(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: False},
-        ):
-            await self.subject.async_set_preset_mode("Silent")
-
-    async def test_set_preset_mode_to_smart(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: True},
-        ):
-            await self.subject.async_set_preset_mode("Smart")
-
-    def test_hvac_action(self):
-        self.dps[HVACMODE_DPS] = True
-        self.dps[OPMODE_DPS] = "heating"
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
-        self.dps[OPMODE_DPS] = "warm"
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
-
-    def test_extra_state_attributes(self):
-        self.dps[POWERLEVEL_DPS] = 50
-        self.dps[UNKNOWN107_DPS] = 1
-        self.dps[UNKNOWN108_DPS] = 2
-        self.dps[UNKNOWN115_DPS] = 3
-        self.dps[UNKNOWN116_DPS] = 4
-        self.assertDictEqual(
-            self.subject.extra_state_attributes,
-            {
-                "power_level": 50,
-                "unknown_107": 1,
-                "unknown_108": 2,
-                "unknown_115": 3,
-                "unknown_116": 4,
-            },
-        )
+from homeassistant.components.climate.const import (
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    CURRENT_HVAC_HEAT,
+    CURRENT_HVAC_IDLE,
+    CURRENT_HVAC_OFF,
+    SUPPORT_PRESET_MODE,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    PERCENTAGE,
+    STATE_UNAVAILABLE,
+    TEMP_CELSIUS,
+    TEMP_FAHRENHEIT,
+)
+
+from ..const import GARDENPAC_HEATPUMP_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.sensor import BasicSensorTests
+from .base_device_tests import TuyaDeviceTestCase
+
+HVACMODE_DPS = "1"
+CURRENTTEMP_DPS = "102"
+UNITS_DPS = "103"
+POWERLEVEL_DPS = "104"
+OPMODE_DPS = "105"
+TEMPERATURE_DPS = "106"
+UNKNOWN107_DPS = "107"
+UNKNOWN108_DPS = "108"
+UNKNOWN115_DPS = "115"
+UNKNOWN116_DPS = "116"
+PRESET_DPS = "117"
+
+
+class TestGardenPACPoolHeatpump(
+    BasicSensorTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("gardenpac_heatpump.yaml", GARDENPAC_HEATPUMP_PAYLOAD)
+        self.subject = self.entities.get("climate")
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=18,
+            max=45,
+        )
+        self.setUpBasicSensor(
+            POWERLEVEL_DPS,
+            self.entities.get("sensor_power_level"),
+            unit=PERCENTAGE,
+            device_class=SensorDeviceClass.POWER_FACTOR,
+            state_class="measurement",
+        )
+        self.mark_secondary(["sensor_power_level"])
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE,
+        )
+
+    def test_icon(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.icon, "mdi:hot-tub")
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.icon, "mdi:hvac-off")
+
+    def test_temperature_unit(self):
+        self.dps[UNITS_DPS] = False
+        self.assertEqual(self.subject.temperature_unit, TEMP_FAHRENHEIT)
+        self.dps[UNITS_DPS] = True
+        self.assertEqual(self.subject.temperature_unit, TEMP_CELSIUS)
+
+    def test_minimum_fahrenheit_temperature(self):
+        self.dps[UNITS_DPS] = False
+        self.assertEqual(self.subject.min_temp, 60)
+
+    def test_maximum_fahrenheit_temperature(self):
+        self.dps[UNITS_DPS] = False
+        self.assertEqual(self.subject.max_temp, 115)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 25
+        self.assertEqual(self.subject.current_temperature, 25)
+
+    def test_hvac_mode(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT])
+
+    async def test_turn_on(self):
+        async with assert_device_properties_set(
+            self.subject._device, {HVACMODE_DPS: True}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
+
+    async def test_turn_off(self):
+        async with assert_device_properties_set(
+            self.subject._device, {HVACMODE_DPS: False}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
+
+    def test_preset_mode(self):
+        self.dps[PRESET_DPS] = False
+        self.assertEqual(self.subject.preset_mode, "Silent")
+
+        self.dps[PRESET_DPS] = True
+        self.assertEqual(self.subject.preset_mode, "Smart")
+
+        self.dps[PRESET_DPS] = None
+        self.assertIs(self.subject.preset_mode, None)
+
+    def test_preset_modes(self):
+        self.assertCountEqual(self.subject.preset_modes, ["Silent", "Smart"])
+
+    async def test_set_preset_mode_to_silent(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: False},
+        ):
+            await self.subject.async_set_preset_mode("Silent")
+
+    async def test_set_preset_mode_to_smart(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: True},
+        ):
+            await self.subject.async_set_preset_mode("Smart")
+
+    def test_hvac_action(self):
+        self.dps[HVACMODE_DPS] = True
+        self.dps[OPMODE_DPS] = "heating"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
+        self.dps[OPMODE_DPS] = "warm"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
+
+    def test_extra_state_attributes(self):
+        self.dps[POWERLEVEL_DPS] = 50
+        self.dps[UNKNOWN107_DPS] = 1
+        self.dps[UNKNOWN108_DPS] = 2
+        self.dps[UNKNOWN115_DPS] = 3
+        self.dps[UNKNOWN116_DPS] = 4
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {
+                "power_level": 50,
+                "unknown_107": 1,
+                "unknown_108": 2,
+                "unknown_115": 3,
+                "unknown_116": 4,
+            },
+        )

+ 548 - 552
tests/devices/test_goldair_dehumidifier.py

@@ -1,552 +1,548 @@
-from unittest.mock import ANY
-
-from homeassistant.components.binary_sensor import (
-    DEVICE_CLASS_COLD,
-    DEVICE_CLASS_PROBLEM,
-)
-from homeassistant.components.climate.const import (
-    FAN_HIGH,
-    FAN_LOW,
-    HVAC_MODE_DRY,
-    HVAC_MODE_OFF,
-    SUPPORT_FAN_MODE,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_TARGET_HUMIDITY,
-)
-from homeassistant.components.light import COLOR_MODE_ONOFF
-from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
-    DEVICE_CLASS_TEMPERATURE,
-    STATE_UNAVAILABLE,
-    TEMP_CELSIUS,
-    TIME_HOURS,
-)
-
-from ..const import DEHUMIDIFIER_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.binary_sensor import MultiBinarySensorTests
-from ..mixins.lock import BasicLockTests
-from ..mixins.number import BasicNumberTests
-from ..mixins.sensor import MultiSensorTests
-from ..mixins.switch import BasicSwitchTests, SwitchableTests
-from .base_device_tests import TuyaDeviceTestCase
-
-HVACMODE_DPS = "1"
-PRESET_DPS = "2"
-HUMIDITY_DPS = "4"
-AIRCLEAN_DPS = "5"
-FANMODE_DPS = "6"
-LOCK_DPS = "7"
-ERROR_DPS = "11"
-TIMER_DPS = "12"
-UNKNOWN101_DPS = "101"
-LIGHTOFF_DPS = "102"
-CURRENTTEMP_DPS = "103"
-CURRENTHUMID_DPS = "104"
-DEFROST_DPS = "105"
-
-PRESET_NORMAL = "0"
-PRESET_LOW = "1"
-PRESET_HIGH = "2"
-PRESET_DRY_CLOTHES = "3"
-
-ERROR_TANK = "Tank full or missing"
-
-
-class TestGoldairDehumidifier(
-    BasicLockTests,
-    BasicNumberTests,
-    BasicSwitchTests,
-    MultiBinarySensorTests,
-    MultiSensorTests,
-    SwitchableTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig("goldair_dehumidifier.yaml", DEHUMIDIFIER_PAYLOAD)
-        self.subject = self.entities.get("humidifier")
-        self.setUpSwitchable(HVACMODE_DPS, self.subject)
-        self.fan = self.entities.get("fan")
-        self.climate = self.entities.get("climate_dehumidifier_as_climate")
-        # BasicLightTests mixin is not used here because the switch is inverted
-        self.light = self.entities.get("light_display")
-        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
-        self.setUpBasicSwitch(AIRCLEAN_DPS, self.entities.get("switch_air_clean"))
-        self.setUpBasicNumber(
-            TIMER_DPS,
-            self.entities.get("number_timer"),
-            max=24,
-            unit=TIME_HOURS,
-        )
-
-        self.setUpMultiSensors(
-            [
-                {
-                    "name": "sensor_current_temperature",
-                    "dps": CURRENTTEMP_DPS,
-                    "unit": TEMP_CELSIUS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
-                    "state_class": "measurement",
-                },
-                {
-                    "name": "sensor_current_humidity",
-                    "dps": CURRENTHUMID_DPS,
-                    "unit": "%",
-                    "device_class": DEVICE_CLASS_HUMIDITY,
-                    "state_class": "measurement",
-                },
-            ]
-        )
-        self.setUpMultiBinarySensors(
-            [
-                {
-                    "name": "binary_sensor_tank",
-                    "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
-                    "testdata": (8, 0),
-                },
-                {
-                    "name": "binary_sensor_defrost",
-                    "dps": DEFROST_DPS,
-                    "device_class": DEVICE_CLASS_COLD,
-                },
-            ]
-        )
-        self.mark_secondary(
-            [
-                "light_display",
-                "lock_child_lock",
-                "number_timer",
-                "binary_sensor_tank",
-                "binary_sensor_defrost",
-            ],
-        )
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.climate.supported_features,
-            SUPPORT_TARGET_HUMIDITY | SUPPORT_PRESET_MODE | SUPPORT_FAN_MODE,
-        )
-
-    def test_icon_is_always_standard_when_off_without_error(self):
-        self.dps[ERROR_DPS] = None
-        self.dps[HVACMODE_DPS] = False
-
-        self.dps[AIRCLEAN_DPS] = False
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.assertEqual(self.climate.icon, "mdi:air-humidifier-off")
-
-        self.dps[AIRCLEAN_DPS] = True
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.assertEqual(self.climate.icon, "mdi:air-humidifier-off")
-
-    def test_icon_is_purifier_when_air_clean_is_active(self):
-        self.dps[ERROR_DPS] = None
-        self.dps[HVACMODE_DPS] = True
-        self.dps[AIRCLEAN_DPS] = True
-        self.assertEqual(self.climate.icon, "mdi:air-purifier")
-
-    def test_icon_is_tshirt_when_dry_clothes_is_active(self):
-        self.dps[ERROR_DPS] = None
-        self.dps[HVACMODE_DPS] = True
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.assertEqual(self.climate.icon, "mdi:tshirt-crew-outline")
-
-    def test_icon_is_always_melting_snowflake_when_defrosting_and_tank_not_full(self):
-        self.dps[DEFROST_DPS] = True
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
-
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
-
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
-
-        self.dps[AIRCLEAN_DPS] = True
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
-
-    def test_icon_is_always_tank_when_tank_full_error_is_present(self):
-        self.dps[ERROR_DPS] = 8
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.climate.icon, "mdi:cup-water")
-
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.climate.icon, "mdi:cup-water")
-
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.assertEqual(self.climate.icon, "mdi:cup-water")
-
-        self.dps[AIRCLEAN_DPS] = True
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.assertEqual(self.climate.icon, "mdi:cup-water")
-
-        self.dps[DEFROST_DPS] = True
-        self.assertEqual(self.climate.icon, "mdi:cup-water")
-
-    def test_current_humidity(self):
-        self.dps[CURRENTHUMID_DPS] = 47
-        self.assertEqual(self.climate.current_humidity, 47)
-
-    def test_min_target_humidity(self):
-        self.assertEqual(self.climate.min_humidity, 30)
-        self.assertEqual(self.subject.min_humidity, 30)
-
-    def test_max_target_humidity(self):
-        self.assertEqual(self.climate.max_humidity, 80)
-        self.assertEqual(self.subject.max_humidity, 80)
-
-    def test_target_humidity_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.dps[HUMIDITY_DPS] = 55
-
-        self.assertEqual(self.climate.target_humidity, 55)
-
-    def test_target_humidity_in_humidifier(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.dps[HUMIDITY_DPS] = 45
-
-        self.assertEqual(self.subject.target_humidity, 45)
-
-    def test_target_humidity_outside_normal_preset(self):
-        self.dps[HUMIDITY_DPS] = 55
-
-        self.dps[PRESET_DPS] = PRESET_HIGH
-        self.assertIs(self.climate.target_humidity, None)
-
-        self.dps[PRESET_DPS] = PRESET_LOW
-        self.assertIs(self.climate.target_humidity, None)
-
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.assertIs(self.climate.target_humidity, None)
-
-    async def test_set_target_humidity_in_normal_preset_rounds_up_to_5_percent(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.climate._device,
-            {HUMIDITY_DPS: 55},
-        ):
-            await self.climate.async_set_humidity(53)
-
-    async def test_set_target_humidity_in_normal_preset_rounds_down_to_5_percent(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-
-        async with assert_device_properties_set(
-            self.climate._device,
-            {HUMIDITY_DPS: 50},
-        ):
-            await self.climate.async_set_humidity(52)
-
-    async def test_set_humidity_in_humidifier_rounds_up_to_5_percent(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.subject._device,
-            {HUMIDITY_DPS: 45},
-        ):
-            await self.subject.async_set_humidity(43)
-
-    async def test_set_humidity_in_humidifier_rounds_down_to_5_percent(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.subject._device,
-            {HUMIDITY_DPS: 40},
-        ):
-            await self.subject.async_set_humidity(42)
-
-    async def test_set_target_humidity_raises_error_outside_of_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_LOW
-        with self.assertRaisesRegex(
-            AttributeError, "humidity cannot be set at this time"
-        ):
-            await self.climate.async_set_humidity(50)
-
-        self.dps[PRESET_DPS] = PRESET_HIGH
-        with self.assertRaisesRegex(
-            AttributeError, "humidity cannot be set at this time"
-        ):
-            await self.climate.async_set_humidity(50)
-
-        self.dps[PRESET_DPS] = PRESET_LOW
-        with self.assertRaisesRegex(
-            AttributeError, "humidity cannot be set at this time"
-        ):
-            await self.climate.async_set_humidity(50)
-
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        with self.assertRaisesRegex(
-            AttributeError, "humidity cannot be set at this time"
-        ):
-            await self.climate.async_set_humidity(50)
-
-    def test_temperature_unit_returns_device_temperature_unit(self):
-        self.assertEqual(
-            self.climate.temperature_unit,
-            self.climate._device.temperature_unit,
-        )
-
-    def test_minimum_target_temperature(self):
-        self.assertIs(self.climate.min_temp, None)
-
-    def test_maximum_target_temperature(self):
-        self.assertIs(self.climate.max_temp, None)
-
-    def test_current_temperature(self):
-        self.dps[CURRENTTEMP_DPS] = 25
-        self.assertEqual(self.climate.current_temperature, 25)
-
-    def test_climate_hvac_mode(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.climate.hvac_mode, HVAC_MODE_DRY)
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.climate.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[HVACMODE_DPS] = None
-        self.assertEqual(self.climate.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_climate_hvac_modes(self):
-        self.assertCountEqual(self.climate.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_DRY])
-
-    async def test_climate_set_hvac_mode_to_dry(self):
-        async with assert_device_properties_set(
-            self.climate._device, {HVACMODE_DPS: True}
-        ):
-            await self.climate.async_set_hvac_mode(HVAC_MODE_DRY)
-
-    async def test_climate_set_hvac_mode_to_off(self):
-
-        async with assert_device_properties_set(
-            self.climate._device, {HVACMODE_DPS: False}
-        ):
-            await self.climate.async_set_hvac_mode(HVAC_MODE_OFF)
-
-    def test_preset_mode(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.assertEqual(self.climate.preset_mode, "Normal")
-        self.assertEqual(self.subject.mode, "Normal")
-
-        self.dps[PRESET_DPS] = PRESET_LOW
-        self.assertEqual(self.climate.preset_mode, "Low")
-        self.assertEqual(self.subject.mode, "Low")
-
-        self.dps[PRESET_DPS] = PRESET_HIGH
-        self.assertEqual(self.climate.preset_mode, "High")
-        self.assertEqual(self.subject.mode, "High")
-
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.assertEqual(self.climate.preset_mode, "Dry clothes")
-        self.assertEqual(self.subject.mode, "Dry clothes")
-
-        self.dps[PRESET_DPS] = None
-        self.assertEqual(self.climate.preset_mode, None)
-        self.assertEqual(self.subject.mode, None)
-
-    def test_air_clean_is_surfaced_in_preset_mode(self):
-        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
-        self.dps[AIRCLEAN_DPS] = True
-
-        self.assertEqual(self.climate.preset_mode, "Air clean")
-
-    def test_preset_modes(self):
-        self.assertCountEqual(
-            self.climate.preset_modes,
-            [
-                "Normal",
-                "Low",
-                "High",
-                "Dry clothes",
-                "Air clean",
-            ],
-        )
-
-    async def test_set_preset_mode_to_normal(self):
-        async with assert_device_properties_set(
-            self.climate._device,
-            {
-                PRESET_DPS: PRESET_NORMAL,
-                AIRCLEAN_DPS: False,
-            },
-        ):
-            await self.climate.async_set_preset_mode("Normal")
-            self.climate._device.anticipate_property_value.assert_not_called()
-
-    async def test_set_preset_mode_to_low(self):
-        async with assert_device_properties_set(
-            self.climate._device,
-            {
-                PRESET_DPS: PRESET_LOW,
-                AIRCLEAN_DPS: False,
-            },
-        ):
-            await self.climate.async_set_preset_mode("Low")
-
-    async def test_set_preset_mode_to_high(self):
-        async with assert_device_properties_set(
-            self.climate._device,
-            {
-                PRESET_DPS: PRESET_HIGH,
-                AIRCLEAN_DPS: False,
-            },
-        ):
-            await self.climate.async_set_preset_mode("High")
-
-    async def test_set_preset_mode_to_dry_clothes(self):
-        async with assert_device_properties_set(
-            self.climate._device,
-            {
-                PRESET_DPS: PRESET_DRY_CLOTHES,
-                AIRCLEAN_DPS: False,
-            },
-        ):
-            await self.climate.async_set_preset_mode("Dry clothes")
-
-    async def test_set_preset_mode_to_air_clean(self):
-        async with assert_device_properties_set(
-            self.climate._device, {AIRCLEAN_DPS: True, PRESET_DPS: ANY}
-        ):
-            await self.climate.async_set_preset_mode("Air clean")
-
-    def test_fan_mode_reflects_dps_mode_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        self.dps[FANMODE_DPS] = "1"
-        self.assertEqual(self.climate.fan_mode, FAN_LOW)
-        self.assertEqual(self.fan.percentage, 50)
-
-        self.dps[FANMODE_DPS] = "3"
-        self.assertEqual(self.climate.fan_mode, FAN_HIGH)
-        self.assertEqual(self.fan.percentage, 100)
-
-        self.dps[FANMODE_DPS] = None
-        self.assertEqual(self.climate.fan_mode, None)
-        self.assertEqual(self.fan.percentage, None)
-
-    async def test_set_fan_mode_to_low_succeeds_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.climate._device,
-            {FANMODE_DPS: "1"},
-        ):
-            await self.climate.async_set_fan_mode(FAN_LOW)
-
-    async def test_set_fan_mode_to_high_succeeds_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.climate._device,
-            {FANMODE_DPS: "3"},
-        ):
-            await self.climate.async_set_fan_mode(FAN_HIGH)
-
-    async def test_set_fan_50_succeeds_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.fan._device,
-            {FANMODE_DPS: "1"},
-        ):
-            await self.fan.async_set_percentage(50)
-
-    async def test_set_fan_100_succeeds_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.fan._device,
-            {FANMODE_DPS: "3"},
-        ):
-            await self.fan.async_set_percentage(100)
-
-    async def test_set_fan_30_snaps_to_50_in_normal_preset(self):
-        self.dps[PRESET_DPS] = PRESET_NORMAL
-        async with assert_device_properties_set(
-            self.fan._device,
-            {FANMODE_DPS: "1"},
-        ):
-            await self.fan.async_set_percentage(30)
-
-    def test_extra_state_attributes(self):
-        self.dps[ERROR_DPS] = None
-        self.dps[DEFROST_DPS] = False
-        self.dps[AIRCLEAN_DPS] = False
-        self.dps[UNKNOWN101_DPS] = False
-        self.assertDictEqual(
-            self.climate.extra_state_attributes,
-            {
-                "error": None,
-                "defrosting": False,
-                "air_clean_on": False,
-                "unknown_101": False,
-            },
-        )
-
-        self.dps[ERROR_DPS] = 8
-        self.dps[DEFROST_DPS] = True
-        self.dps[AIRCLEAN_DPS] = True
-        self.dps[UNKNOWN101_DPS] = True
-        self.assertDictEqual(
-            self.climate.extra_state_attributes,
-            {
-                "error": ERROR_TANK,
-                "defrosting": True,
-                "air_clean_on": True,
-                "unknown_101": True,
-            },
-        )
-
-    def test_light_supported_color_modes(self):
-        self.assertCountEqual(
-            self.light.supported_color_modes,
-            [COLOR_MODE_ONOFF],
-        )
-
-    def test_light_color_mode(self):
-        self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
-
-    def test_light_icon(self):
-        self.dps[LIGHTOFF_DPS] = False
-        self.assertEqual(self.light.icon, "mdi:led-on")
-
-        self.dps[LIGHTOFF_DPS] = True
-        self.assertEqual(self.light.icon, "mdi:led-off")
-
-    def test_light_is_on(self):
-        self.dps[LIGHTOFF_DPS] = False
-        self.assertEqual(self.light.is_on, True)
-
-        self.dps[LIGHTOFF_DPS] = True
-        self.assertEqual(self.light.is_on, False)
-
-    def test_light_state_attributes(self):
-        self.assertEqual(self.light.extra_state_attributes, {})
-
-    async def test_light_turn_on(self):
-        async with assert_device_properties_set(
-            self.light._device, {LIGHTOFF_DPS: False}
-        ):
-            await self.light.async_turn_on()
-
-    async def test_light_turn_off(self):
-        async with assert_device_properties_set(
-            self.light._device, {LIGHTOFF_DPS: True}
-        ):
-            await self.light.async_turn_off()
-
-    async def test_toggle_turns_the_light_on_when_it_was_off(self):
-        self.dps[LIGHTOFF_DPS] = True
-
-        async with assert_device_properties_set(
-            self.light._device, {LIGHTOFF_DPS: False}
-        ):
-            await self.light.async_toggle()
-
-    async def test_toggle_turns_the_light_off_when_it_was_on(self):
-        self.dps[LIGHTOFF_DPS] = False
-
-        async with assert_device_properties_set(
-            self.light._device, {LIGHTOFF_DPS: True}
-        ):
-            await self.light.async_toggle()
-
-    def test_switch_icon(self):
-        self.assertEqual(self.basicSwitch.icon, "mdi:air-purifier")
+from unittest.mock import ANY
+
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
+from homeassistant.components.climate.const import (
+    FAN_HIGH,
+    FAN_LOW,
+    HVAC_MODE_DRY,
+    HVAC_MODE_OFF,
+    SUPPORT_FAN_MODE,
+    SUPPORT_PRESET_MODE,
+    SUPPORT_TARGET_HUMIDITY,
+)
+from homeassistant.components.light import COLOR_MODE_ONOFF
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    STATE_UNAVAILABLE,
+    TEMP_CELSIUS,
+    TIME_HOURS,
+)
+
+from ..const import DEHUMIDIFIER_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.binary_sensor import MultiBinarySensorTests
+from ..mixins.lock import BasicLockTests
+from ..mixins.number import BasicNumberTests
+from ..mixins.sensor import MultiSensorTests
+from ..mixins.switch import BasicSwitchTests, SwitchableTests
+from .base_device_tests import TuyaDeviceTestCase
+
+HVACMODE_DPS = "1"
+PRESET_DPS = "2"
+HUMIDITY_DPS = "4"
+AIRCLEAN_DPS = "5"
+FANMODE_DPS = "6"
+LOCK_DPS = "7"
+ERROR_DPS = "11"
+TIMER_DPS = "12"
+UNKNOWN101_DPS = "101"
+LIGHTOFF_DPS = "102"
+CURRENTTEMP_DPS = "103"
+CURRENTHUMID_DPS = "104"
+DEFROST_DPS = "105"
+
+PRESET_NORMAL = "0"
+PRESET_LOW = "1"
+PRESET_HIGH = "2"
+PRESET_DRY_CLOTHES = "3"
+
+ERROR_TANK = "Tank full or missing"
+
+
+class TestGoldairDehumidifier(
+    BasicLockTests,
+    BasicNumberTests,
+    BasicSwitchTests,
+    MultiBinarySensorTests,
+    MultiSensorTests,
+    SwitchableTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("goldair_dehumidifier.yaml", DEHUMIDIFIER_PAYLOAD)
+        self.subject = self.entities.get("humidifier")
+        self.setUpSwitchable(HVACMODE_DPS, self.subject)
+        self.fan = self.entities.get("fan")
+        self.climate = self.entities.get("climate_dehumidifier_as_climate")
+        # BasicLightTests mixin is not used here because the switch is inverted
+        self.light = self.entities.get("light_display")
+        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
+        self.setUpBasicSwitch(AIRCLEAN_DPS, self.entities.get("switch_air_clean"))
+        self.setUpBasicNumber(
+            TIMER_DPS,
+            self.entities.get("number_timer"),
+            max=24,
+            unit=TIME_HOURS,
+        )
+
+        self.setUpMultiSensors(
+            [
+                {
+                    "name": "sensor_current_temperature",
+                    "dps": CURRENTTEMP_DPS,
+                    "unit": TEMP_CELSIUS,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
+                    "state_class": "measurement",
+                },
+                {
+                    "name": "sensor_current_humidity",
+                    "dps": CURRENTHUMID_DPS,
+                    "unit": "%",
+                    "device_class": SensorDeviceClass.HUMIDITY,
+                    "state_class": "measurement",
+                },
+            ]
+        )
+        self.setUpMultiBinarySensors(
+            [
+                {
+                    "name": "binary_sensor_tank",
+                    "dps": ERROR_DPS,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
+                    "testdata": (8, 0),
+                },
+                {
+                    "name": "binary_sensor_defrost",
+                    "dps": DEFROST_DPS,
+                    "device_class": BinarySensorDeviceClass.COLD,
+                },
+            ]
+        )
+        self.mark_secondary(
+            [
+                "light_display",
+                "lock_child_lock",
+                "number_timer",
+                "binary_sensor_tank",
+                "binary_sensor_defrost",
+            ],
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.climate.supported_features,
+            SUPPORT_TARGET_HUMIDITY | SUPPORT_PRESET_MODE | SUPPORT_FAN_MODE,
+        )
+
+    def test_icon_is_always_standard_when_off_without_error(self):
+        self.dps[ERROR_DPS] = None
+        self.dps[HVACMODE_DPS] = False
+
+        self.dps[AIRCLEAN_DPS] = False
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.assertEqual(self.climate.icon, "mdi:air-humidifier-off")
+
+        self.dps[AIRCLEAN_DPS] = True
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.assertEqual(self.climate.icon, "mdi:air-humidifier-off")
+
+    def test_icon_is_purifier_when_air_clean_is_active(self):
+        self.dps[ERROR_DPS] = None
+        self.dps[HVACMODE_DPS] = True
+        self.dps[AIRCLEAN_DPS] = True
+        self.assertEqual(self.climate.icon, "mdi:air-purifier")
+
+    def test_icon_is_tshirt_when_dry_clothes_is_active(self):
+        self.dps[ERROR_DPS] = None
+        self.dps[HVACMODE_DPS] = True
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.assertEqual(self.climate.icon, "mdi:tshirt-crew-outline")
+
+    def test_icon_is_always_melting_snowflake_when_defrosting_and_tank_not_full(self):
+        self.dps[DEFROST_DPS] = True
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
+
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
+
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
+
+        self.dps[AIRCLEAN_DPS] = True
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.assertEqual(self.climate.icon, "mdi:snowflake-melt")
+
+    def test_icon_is_always_tank_when_tank_full_error_is_present(self):
+        self.dps[ERROR_DPS] = 8
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.climate.icon, "mdi:cup-water")
+
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.climate.icon, "mdi:cup-water")
+
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.assertEqual(self.climate.icon, "mdi:cup-water")
+
+        self.dps[AIRCLEAN_DPS] = True
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.assertEqual(self.climate.icon, "mdi:cup-water")
+
+        self.dps[DEFROST_DPS] = True
+        self.assertEqual(self.climate.icon, "mdi:cup-water")
+
+    def test_current_humidity(self):
+        self.dps[CURRENTHUMID_DPS] = 47
+        self.assertEqual(self.climate.current_humidity, 47)
+
+    def test_min_target_humidity(self):
+        self.assertEqual(self.climate.min_humidity, 30)
+        self.assertEqual(self.subject.min_humidity, 30)
+
+    def test_max_target_humidity(self):
+        self.assertEqual(self.climate.max_humidity, 80)
+        self.assertEqual(self.subject.max_humidity, 80)
+
+    def test_target_humidity_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.dps[HUMIDITY_DPS] = 55
+
+        self.assertEqual(self.climate.target_humidity, 55)
+
+    def test_target_humidity_in_humidifier(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.dps[HUMIDITY_DPS] = 45
+
+        self.assertEqual(self.subject.target_humidity, 45)
+
+    def test_target_humidity_outside_normal_preset(self):
+        self.dps[HUMIDITY_DPS] = 55
+
+        self.dps[PRESET_DPS] = PRESET_HIGH
+        self.assertIs(self.climate.target_humidity, None)
+
+        self.dps[PRESET_DPS] = PRESET_LOW
+        self.assertIs(self.climate.target_humidity, None)
+
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.assertIs(self.climate.target_humidity, None)
+
+    async def test_set_target_humidity_in_normal_preset_rounds_up_to_5_percent(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.climate._device,
+            {HUMIDITY_DPS: 55},
+        ):
+            await self.climate.async_set_humidity(53)
+
+    async def test_set_target_humidity_in_normal_preset_rounds_down_to_5_percent(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+
+        async with assert_device_properties_set(
+            self.climate._device,
+            {HUMIDITY_DPS: 50},
+        ):
+            await self.climate.async_set_humidity(52)
+
+    async def test_set_humidity_in_humidifier_rounds_up_to_5_percent(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.subject._device,
+            {HUMIDITY_DPS: 45},
+        ):
+            await self.subject.async_set_humidity(43)
+
+    async def test_set_humidity_in_humidifier_rounds_down_to_5_percent(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.subject._device,
+            {HUMIDITY_DPS: 40},
+        ):
+            await self.subject.async_set_humidity(42)
+
+    async def test_set_target_humidity_raises_error_outside_of_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_LOW
+        with self.assertRaisesRegex(
+            AttributeError, "humidity cannot be set at this time"
+        ):
+            await self.climate.async_set_humidity(50)
+
+        self.dps[PRESET_DPS] = PRESET_HIGH
+        with self.assertRaisesRegex(
+            AttributeError, "humidity cannot be set at this time"
+        ):
+            await self.climate.async_set_humidity(50)
+
+        self.dps[PRESET_DPS] = PRESET_LOW
+        with self.assertRaisesRegex(
+            AttributeError, "humidity cannot be set at this time"
+        ):
+            await self.climate.async_set_humidity(50)
+
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        with self.assertRaisesRegex(
+            AttributeError, "humidity cannot be set at this time"
+        ):
+            await self.climate.async_set_humidity(50)
+
+    def test_temperature_unit_returns_device_temperature_unit(self):
+        self.assertEqual(
+            self.climate.temperature_unit,
+            self.climate._device.temperature_unit,
+        )
+
+    def test_minimum_target_temperature(self):
+        self.assertIs(self.climate.min_temp, None)
+
+    def test_maximum_target_temperature(self):
+        self.assertIs(self.climate.max_temp, None)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 25
+        self.assertEqual(self.climate.current_temperature, 25)
+
+    def test_climate_hvac_mode(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.climate.hvac_mode, HVAC_MODE_DRY)
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.climate.hvac_mode, HVAC_MODE_OFF)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.climate.hvac_mode, STATE_UNAVAILABLE)
+
+    def test_climate_hvac_modes(self):
+        self.assertCountEqual(self.climate.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_DRY])
+
+    async def test_climate_set_hvac_mode_to_dry(self):
+        async with assert_device_properties_set(
+            self.climate._device, {HVACMODE_DPS: True}
+        ):
+            await self.climate.async_set_hvac_mode(HVAC_MODE_DRY)
+
+    async def test_climate_set_hvac_mode_to_off(self):
+
+        async with assert_device_properties_set(
+            self.climate._device, {HVACMODE_DPS: False}
+        ):
+            await self.climate.async_set_hvac_mode(HVAC_MODE_OFF)
+
+    def test_preset_mode(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.assertEqual(self.climate.preset_mode, "Normal")
+        self.assertEqual(self.subject.mode, "Normal")
+
+        self.dps[PRESET_DPS] = PRESET_LOW
+        self.assertEqual(self.climate.preset_mode, "Low")
+        self.assertEqual(self.subject.mode, "Low")
+
+        self.dps[PRESET_DPS] = PRESET_HIGH
+        self.assertEqual(self.climate.preset_mode, "High")
+        self.assertEqual(self.subject.mode, "High")
+
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.assertEqual(self.climate.preset_mode, "Dry clothes")
+        self.assertEqual(self.subject.mode, "Dry clothes")
+
+        self.dps[PRESET_DPS] = None
+        self.assertEqual(self.climate.preset_mode, None)
+        self.assertEqual(self.subject.mode, None)
+
+    def test_air_clean_is_surfaced_in_preset_mode(self):
+        self.dps[PRESET_DPS] = PRESET_DRY_CLOTHES
+        self.dps[AIRCLEAN_DPS] = True
+
+        self.assertEqual(self.climate.preset_mode, "Air clean")
+
+    def test_preset_modes(self):
+        self.assertCountEqual(
+            self.climate.preset_modes,
+            [
+                "Normal",
+                "Low",
+                "High",
+                "Dry clothes",
+                "Air clean",
+            ],
+        )
+
+    async def test_set_preset_mode_to_normal(self):
+        async with assert_device_properties_set(
+            self.climate._device,
+            {
+                PRESET_DPS: PRESET_NORMAL,
+                AIRCLEAN_DPS: False,
+            },
+        ):
+            await self.climate.async_set_preset_mode("Normal")
+            self.climate._device.anticipate_property_value.assert_not_called()
+
+    async def test_set_preset_mode_to_low(self):
+        async with assert_device_properties_set(
+            self.climate._device,
+            {
+                PRESET_DPS: PRESET_LOW,
+                AIRCLEAN_DPS: False,
+            },
+        ):
+            await self.climate.async_set_preset_mode("Low")
+
+    async def test_set_preset_mode_to_high(self):
+        async with assert_device_properties_set(
+            self.climate._device,
+            {
+                PRESET_DPS: PRESET_HIGH,
+                AIRCLEAN_DPS: False,
+            },
+        ):
+            await self.climate.async_set_preset_mode("High")
+
+    async def test_set_preset_mode_to_dry_clothes(self):
+        async with assert_device_properties_set(
+            self.climate._device,
+            {
+                PRESET_DPS: PRESET_DRY_CLOTHES,
+                AIRCLEAN_DPS: False,
+            },
+        ):
+            await self.climate.async_set_preset_mode("Dry clothes")
+
+    async def test_set_preset_mode_to_air_clean(self):
+        async with assert_device_properties_set(
+            self.climate._device, {AIRCLEAN_DPS: True, PRESET_DPS: ANY}
+        ):
+            await self.climate.async_set_preset_mode("Air clean")
+
+    def test_fan_mode_reflects_dps_mode_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        self.dps[FANMODE_DPS] = "1"
+        self.assertEqual(self.climate.fan_mode, FAN_LOW)
+        self.assertEqual(self.fan.percentage, 50)
+
+        self.dps[FANMODE_DPS] = "3"
+        self.assertEqual(self.climate.fan_mode, FAN_HIGH)
+        self.assertEqual(self.fan.percentage, 100)
+
+        self.dps[FANMODE_DPS] = None
+        self.assertEqual(self.climate.fan_mode, None)
+        self.assertEqual(self.fan.percentage, None)
+
+    async def test_set_fan_mode_to_low_succeeds_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.climate._device,
+            {FANMODE_DPS: "1"},
+        ):
+            await self.climate.async_set_fan_mode(FAN_LOW)
+
+    async def test_set_fan_mode_to_high_succeeds_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.climate._device,
+            {FANMODE_DPS: "3"},
+        ):
+            await self.climate.async_set_fan_mode(FAN_HIGH)
+
+    async def test_set_fan_50_succeeds_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.fan._device,
+            {FANMODE_DPS: "1"},
+        ):
+            await self.fan.async_set_percentage(50)
+
+    async def test_set_fan_100_succeeds_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.fan._device,
+            {FANMODE_DPS: "3"},
+        ):
+            await self.fan.async_set_percentage(100)
+
+    async def test_set_fan_30_snaps_to_50_in_normal_preset(self):
+        self.dps[PRESET_DPS] = PRESET_NORMAL
+        async with assert_device_properties_set(
+            self.fan._device,
+            {FANMODE_DPS: "1"},
+        ):
+            await self.fan.async_set_percentage(30)
+
+    def test_extra_state_attributes(self):
+        self.dps[ERROR_DPS] = None
+        self.dps[DEFROST_DPS] = False
+        self.dps[AIRCLEAN_DPS] = False
+        self.dps[UNKNOWN101_DPS] = False
+        self.assertDictEqual(
+            self.climate.extra_state_attributes,
+            {
+                "error": None,
+                "defrosting": False,
+                "air_clean_on": False,
+                "unknown_101": False,
+            },
+        )
+
+        self.dps[ERROR_DPS] = 8
+        self.dps[DEFROST_DPS] = True
+        self.dps[AIRCLEAN_DPS] = True
+        self.dps[UNKNOWN101_DPS] = True
+        self.assertDictEqual(
+            self.climate.extra_state_attributes,
+            {
+                "error": ERROR_TANK,
+                "defrosting": True,
+                "air_clean_on": True,
+                "unknown_101": True,
+            },
+        )
+
+    def test_light_supported_color_modes(self):
+        self.assertCountEqual(
+            self.light.supported_color_modes,
+            [COLOR_MODE_ONOFF],
+        )
+
+    def test_light_color_mode(self):
+        self.assertEqual(self.light.color_mode, COLOR_MODE_ONOFF)
+
+    def test_light_icon(self):
+        self.dps[LIGHTOFF_DPS] = False
+        self.assertEqual(self.light.icon, "mdi:led-on")
+
+        self.dps[LIGHTOFF_DPS] = True
+        self.assertEqual(self.light.icon, "mdi:led-off")
+
+    def test_light_is_on(self):
+        self.dps[LIGHTOFF_DPS] = False
+        self.assertEqual(self.light.is_on, True)
+
+        self.dps[LIGHTOFF_DPS] = True
+        self.assertEqual(self.light.is_on, False)
+
+    def test_light_state_attributes(self):
+        self.assertEqual(self.light.extra_state_attributes, {})
+
+    async def test_light_turn_on(self):
+        async with assert_device_properties_set(
+            self.light._device, {LIGHTOFF_DPS: False}
+        ):
+            await self.light.async_turn_on()
+
+    async def test_light_turn_off(self):
+        async with assert_device_properties_set(
+            self.light._device, {LIGHTOFF_DPS: True}
+        ):
+            await self.light.async_turn_off()
+
+    async def test_toggle_turns_the_light_on_when_it_was_off(self):
+        self.dps[LIGHTOFF_DPS] = True
+
+        async with assert_device_properties_set(
+            self.light._device, {LIGHTOFF_DPS: False}
+        ):
+            await self.light.async_toggle()
+
+    async def test_toggle_turns_the_light_off_when_it_was_on(self):
+        self.dps[LIGHTOFF_DPS] = False
+
+        async with assert_device_properties_set(
+            self.light._device, {LIGHTOFF_DPS: True}
+        ):
+            await self.light.async_toggle()
+
+    def test_switch_icon(self):
+        self.assertEqual(self.basicSwitch.icon, "mdi:air-purifier")

+ 2 - 2
tests/devices/test_goldair_geco_heater.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -50,7 +50,7 @@ class TestGoldairGECOHeater(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(

+ 2 - 2
tests/devices/test_goldair_gpcv_heater.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -52,7 +52,7 @@ class TestGoldairGPCVHeater(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(

+ 335 - 336
tests/devices/test_goldair_gpph_heater.py

@@ -1,336 +1,335 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
-from homeassistant.components.climate.const import (
-    HVAC_MODE_HEAT,
-    HVAC_MODE_OFF,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_SWING_MODE,
-    SUPPORT_TARGET_TEMPERATURE,
-)
-
-from homeassistant.const import (
-    DEVICE_CLASS_POWER_FACTOR,
-    PERCENTAGE,
-    STATE_UNAVAILABLE,
-    TIME_MINUTES,
-)
-
-from ..const import GPPH_HEATER_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.binary_sensor import BasicBinarySensorTests
-from ..mixins.climate import TargetTemperatureTests
-from ..mixins.light import BasicLightTests
-from ..mixins.lock import BasicLockTests
-from ..mixins.number import BasicNumberTests
-from ..mixins.sensor import BasicSensorTests
-from .base_device_tests import TuyaDeviceTestCase
-
-HVACMODE_DPS = "1"
-TEMPERATURE_DPS = "2"
-CURRENTTEMP_DPS = "3"
-PRESET_DPS = "4"
-LOCK_DPS = "6"
-ERROR_DPS = "12"
-POWERLEVEL_DPS = "101"
-TIMER_DPS = "102"
-TIMERACT_DPS = "103"
-LIGHT_DPS = "104"
-SWING_DPS = "105"
-ECOTEMP_DPS = "106"
-
-
-class TestGoldairHeater(
-    BasicBinarySensorTests,
-    BasicLightTests,
-    BasicLockTests,
-    BasicNumberTests,
-    BasicSensorTests,
-    TargetTemperatureTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig("goldair_gpph_heater.yaml", GPPH_HEATER_PAYLOAD)
-        self.subject = self.entities.get("climate")
-        self.setUpTargetTemperature(
-            TEMPERATURE_DPS,
-            self.subject,
-            min=5,
-            max=35,
-        )
-        self.setUpBasicLight(LIGHT_DPS, self.entities.get("light_display"))
-        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
-        self.setUpBasicNumber(
-            TIMER_DPS,
-            self.entities.get("number_timer"),
-            max=1440,
-            step=60,
-            unit=TIME_MINUTES,
-        )
-        self.setUpBasicSensor(
-            POWERLEVEL_DPS,
-            self.entities.get("sensor_power_level"),
-            unit=PERCENTAGE,
-            device_class=DEVICE_CLASS_POWER_FACTOR,
-            testdata=("2", 40),
-        )
-        self.setUpBasicBinarySensor(
-            ERROR_DPS,
-            self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
-            testdata=(1, 0),
-        )
-        self.mark_secondary(
-            [
-                "light_display",
-                "lock_child_lock",
-                "number_timer",
-                "sensor_power_level",
-                "binary_sensor_error",
-            ]
-        )
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE | SUPPORT_SWING_MODE,
-        )
-
-    def test_icon(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.icon, "mdi:radiator")
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.icon, "mdi:radiator-disabled")
-
-        self.dps[HVACMODE_DPS] = True
-        self.dps[POWERLEVEL_DPS] = "stop"
-        self.assertEqual(self.subject.icon, "mdi:radiator-disabled")
-
-    def test_temperature_unit_returns_device_temperature_unit(self):
-        self.assertEqual(
-            self.subject.temperature_unit, self.subject._device.temperature_unit
-        )
-
-    def test_target_temperature_in_eco_and_af_modes(self):
-        self.dps[TEMPERATURE_DPS] = 25
-        self.dps[ECOTEMP_DPS] = 15
-
-        self.dps[PRESET_DPS] = "ECO"
-        self.assertEqual(self.subject.target_temperature, 15)
-
-        self.dps[PRESET_DPS] = "AF"
-        self.assertIs(self.subject.target_temperature, None)
-
-    def test_minimum_temperature(self):
-        self.dps[PRESET_DPS] = "C"
-        self.assertEqual(self.subject.min_temp, 5)
-
-        self.dps[PRESET_DPS] = "ECO"
-        self.assertEqual(self.subject.min_temp, 5)
-
-        self.dps[PRESET_DPS] = "AF"
-        self.assertIs(self.subject.min_temp, 5)
-
-    def test_maximum_target_temperature(self):
-        self.dps[PRESET_DPS] = "C"
-        self.assertEqual(self.subject.max_temp, 35)
-
-        self.dps[PRESET_DPS] = "ECO"
-        self.assertEqual(self.subject.max_temp, 21)
-
-        self.dps[PRESET_DPS] = "AF"
-        self.assertIs(self.subject.max_temp, 5)
-
-    async def test_legacy_set_temperature_with_preset_mode(self):
-        async with assert_device_properties_set(
-            self.subject._device, {PRESET_DPS: "C"}
-        ):
-            await self.subject.async_set_temperature(preset_mode="comfort")
-
-    async def test_legacy_set_temperature_with_both_properties(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                TEMPERATURE_DPS: 25,
-                PRESET_DPS: "C",
-            },
-        ):
-            await self.subject.async_set_temperature(
-                temperature=25, preset_mode="comfort"
-            )
-
-    async def test_set_target_temperature_in_eco_mode(self):
-        self.dps[PRESET_DPS] = "ECO"
-
-        async with assert_device_properties_set(
-            self.subject._device, {ECOTEMP_DPS: 15}
-        ):
-            await self.subject.async_set_target_temperature(15)
-
-    async def test_set_target_temperature_fails_outside_valid_range_in_eco(self):
-        self.dps[PRESET_DPS] = "ECO"
-
-        with self.assertRaisesRegex(
-            ValueError, "eco_temperature \\(4\\) must be between 5 and 21"
-        ):
-            await self.subject.async_set_target_temperature(4)
-
-        with self.assertRaisesRegex(
-            ValueError, "eco_temperature \\(22\\) must be between 5 and 21"
-        ):
-            await self.subject.async_set_target_temperature(22)
-
-    async def test_set_target_temperature_fails_in_anti_freeze(self):
-        self.dps[PRESET_DPS] = "AF"
-
-        with self.assertRaisesRegex(
-            AttributeError, "temperature cannot be set at this time"
-        ):
-            await self.subject.async_set_target_temperature(25)
-
-    def test_current_temperature(self):
-        self.dps[CURRENTTEMP_DPS] = 25
-        self.assertEqual(self.subject.current_temperature, 25)
-
-    def test_humidity_unsupported(self):
-        self.assertIsNone(self.subject.min_humidity)
-        self.assertIsNone(self.subject.max_humidity)
-        self.assertIsNone(self.subject.current_humidity)
-        with self.assertRaises(NotImplementedError):
-            self.subject.target_humidity
-
-    async def test_set_humidity_unsupported(self):
-        with self.assertRaises(NotImplementedError):
-            await self.subject.async_set_humidity(50)
-
-    def test_hvac_mode(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[HVACMODE_DPS] = None
-        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_hvac_modes(self):
-        self.assertCountEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT])
-
-    async def test_turn_on(self):
-        async with assert_device_properties_set(
-            self.subject._device, {HVACMODE_DPS: True}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
-
-    async def test_turn_off(self):
-        async with assert_device_properties_set(
-            self.subject._device, {HVACMODE_DPS: False}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
-
-    def test_preset_mode(self):
-        self.dps[PRESET_DPS] = "C"
-        self.assertEqual(self.subject.preset_mode, "comfort")
-
-        self.dps[PRESET_DPS] = "ECO"
-        self.assertEqual(self.subject.preset_mode, "eco")
-
-        self.dps[PRESET_DPS] = "AF"
-        self.assertEqual(self.subject.preset_mode, "away")
-
-        self.dps[PRESET_DPS] = None
-        self.assertIs(self.subject.preset_mode, None)
-
-    def test_preset_modes(self):
-        self.assertCountEqual(self.subject.preset_modes, ["comfort", "eco", "away"])
-
-    async def test_set_preset_mode_to_comfort(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: "C"},
-        ):
-            await self.subject.async_set_preset_mode("comfort")
-
-    async def test_set_preset_mode_to_eco(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: "ECO"},
-        ):
-            await self.subject.async_set_preset_mode("eco")
-
-    async def test_set_preset_mode_to_anti_freeze(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: "AF"},
-        ):
-            await self.subject.async_set_preset_mode("away")
-
-    def test_power_level_returns_user_power_level(self):
-        self.dps[SWING_DPS] = "user"
-
-        self.dps[POWERLEVEL_DPS] = "stop"
-        self.assertEqual(self.subject.swing_mode, "Stop")
-
-        self.dps[POWERLEVEL_DPS] = "3"
-        self.assertEqual(self.subject.swing_mode, "3")
-
-    def test_non_user_swing_mode(self):
-        self.dps[SWING_DPS] = "stop"
-        self.assertEqual(self.subject.swing_mode, "Stop")
-
-        self.dps[SWING_DPS] = "auto"
-        self.assertEqual(self.subject.swing_mode, "Auto")
-
-        self.dps[SWING_DPS] = None
-        self.assertIs(self.subject.swing_mode, None)
-
-    def test_swing_modes(self):
-        self.assertCountEqual(
-            self.subject.swing_modes,
-            ["Stop", "1", "2", "3", "4", "5", "Auto"],
-        )
-
-    async def test_set_power_level_to_stop(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {POWERLEVEL_DPS: "stop", SWING_DPS: "stop"},
-        ):
-            await self.subject.async_set_swing_mode("Stop")
-
-    async def test_set_swing_mode_to_auto(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {SWING_DPS: "auto"},
-        ):
-            await self.subject.async_set_swing_mode("Auto")
-
-    async def test_set_power_level_to_numeric_value(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {SWING_DPS: "user", POWERLEVEL_DPS: "3"},
-        ):
-            await self.subject.async_set_swing_mode("3")
-
-    def test_extra_state_attributes(self):
-        self.dps[ERROR_DPS] = "something"
-        self.dps[TIMER_DPS] = 5
-        self.dps[TIMERACT_DPS] = True
-        self.dps[POWERLEVEL_DPS] = 4
-
-        self.assertDictEqual(
-            self.subject.extra_state_attributes,
-            {
-                "error": "something",
-                "timer": 5,
-                "timer_mode": True,
-                "power_level": "4",
-            },
-        )
-
-    def test_light_icon(self):
-        self.dps[LIGHT_DPS] = True
-        self.assertEqual(self.basicLight.icon, "mdi:led-on")
-
-        self.dps[LIGHT_DPS] = False
-        self.assertEqual(self.basicLight.icon, "mdi:led-off")
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
+from homeassistant.components.climate.const import (
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    SUPPORT_PRESET_MODE,
+    SUPPORT_SWING_MODE,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    PERCENTAGE,
+    STATE_UNAVAILABLE,
+    TIME_MINUTES,
+)
+
+from ..const import GPPH_HEATER_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.binary_sensor import BasicBinarySensorTests
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.light import BasicLightTests
+from ..mixins.lock import BasicLockTests
+from ..mixins.number import BasicNumberTests
+from ..mixins.sensor import BasicSensorTests
+from .base_device_tests import TuyaDeviceTestCase
+
+HVACMODE_DPS = "1"
+TEMPERATURE_DPS = "2"
+CURRENTTEMP_DPS = "3"
+PRESET_DPS = "4"
+LOCK_DPS = "6"
+ERROR_DPS = "12"
+POWERLEVEL_DPS = "101"
+TIMER_DPS = "102"
+TIMERACT_DPS = "103"
+LIGHT_DPS = "104"
+SWING_DPS = "105"
+ECOTEMP_DPS = "106"
+
+
+class TestGoldairHeater(
+    BasicBinarySensorTests,
+    BasicLightTests,
+    BasicLockTests,
+    BasicNumberTests,
+    BasicSensorTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("goldair_gpph_heater.yaml", GPPH_HEATER_PAYLOAD)
+        self.subject = self.entities.get("climate")
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=5,
+            max=35,
+        )
+        self.setUpBasicLight(LIGHT_DPS, self.entities.get("light_display"))
+        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
+        self.setUpBasicNumber(
+            TIMER_DPS,
+            self.entities.get("number_timer"),
+            max=1440,
+            step=60,
+            unit=TIME_MINUTES,
+        )
+        self.setUpBasicSensor(
+            POWERLEVEL_DPS,
+            self.entities.get("sensor_power_level"),
+            unit=PERCENTAGE,
+            device_class=SensorDeviceClass.POWER_FACTOR,
+            testdata=("2", 40),
+        )
+        self.setUpBasicBinarySensor(
+            ERROR_DPS,
+            self.entities.get("binary_sensor_error"),
+            device_class=BinarySensorDeviceClass.PROBLEM,
+            testdata=(1, 0),
+        )
+        self.mark_secondary(
+            [
+                "light_display",
+                "lock_child_lock",
+                "number_timer",
+                "sensor_power_level",
+                "binary_sensor_error",
+            ]
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE | SUPPORT_SWING_MODE,
+        )
+
+    def test_icon(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.icon, "mdi:radiator")
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.icon, "mdi:radiator-disabled")
+
+        self.dps[HVACMODE_DPS] = True
+        self.dps[POWERLEVEL_DPS] = "stop"
+        self.assertEqual(self.subject.icon, "mdi:radiator-disabled")
+
+    def test_temperature_unit_returns_device_temperature_unit(self):
+        self.assertEqual(
+            self.subject.temperature_unit, self.subject._device.temperature_unit
+        )
+
+    def test_target_temperature_in_eco_and_af_modes(self):
+        self.dps[TEMPERATURE_DPS] = 25
+        self.dps[ECOTEMP_DPS] = 15
+
+        self.dps[PRESET_DPS] = "ECO"
+        self.assertEqual(self.subject.target_temperature, 15)
+
+        self.dps[PRESET_DPS] = "AF"
+        self.assertIs(self.subject.target_temperature, None)
+
+    def test_minimum_temperature(self):
+        self.dps[PRESET_DPS] = "C"
+        self.assertEqual(self.subject.min_temp, 5)
+
+        self.dps[PRESET_DPS] = "ECO"
+        self.assertEqual(self.subject.min_temp, 5)
+
+        self.dps[PRESET_DPS] = "AF"
+        self.assertIs(self.subject.min_temp, 5)
+
+    def test_maximum_target_temperature(self):
+        self.dps[PRESET_DPS] = "C"
+        self.assertEqual(self.subject.max_temp, 35)
+
+        self.dps[PRESET_DPS] = "ECO"
+        self.assertEqual(self.subject.max_temp, 21)
+
+        self.dps[PRESET_DPS] = "AF"
+        self.assertIs(self.subject.max_temp, 5)
+
+    async def test_legacy_set_temperature_with_preset_mode(self):
+        async with assert_device_properties_set(
+            self.subject._device, {PRESET_DPS: "C"}
+        ):
+            await self.subject.async_set_temperature(preset_mode="comfort")
+
+    async def test_legacy_set_temperature_with_both_properties(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                TEMPERATURE_DPS: 25,
+                PRESET_DPS: "C",
+            },
+        ):
+            await self.subject.async_set_temperature(
+                temperature=25, preset_mode="comfort"
+            )
+
+    async def test_set_target_temperature_in_eco_mode(self):
+        self.dps[PRESET_DPS] = "ECO"
+
+        async with assert_device_properties_set(
+            self.subject._device, {ECOTEMP_DPS: 15}
+        ):
+            await self.subject.async_set_target_temperature(15)
+
+    async def test_set_target_temperature_fails_outside_valid_range_in_eco(self):
+        self.dps[PRESET_DPS] = "ECO"
+
+        with self.assertRaisesRegex(
+            ValueError, "eco_temperature \\(4\\) must be between 5 and 21"
+        ):
+            await self.subject.async_set_target_temperature(4)
+
+        with self.assertRaisesRegex(
+            ValueError, "eco_temperature \\(22\\) must be between 5 and 21"
+        ):
+            await self.subject.async_set_target_temperature(22)
+
+    async def test_set_target_temperature_fails_in_anti_freeze(self):
+        self.dps[PRESET_DPS] = "AF"
+
+        with self.assertRaisesRegex(
+            AttributeError, "temperature cannot be set at this time"
+        ):
+            await self.subject.async_set_target_temperature(25)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 25
+        self.assertEqual(self.subject.current_temperature, 25)
+
+    def test_humidity_unsupported(self):
+        self.assertIsNone(self.subject.min_humidity)
+        self.assertIsNone(self.subject.max_humidity)
+        self.assertIsNone(self.subject.current_humidity)
+        with self.assertRaises(NotImplementedError):
+            self.subject.target_humidity
+
+    async def test_set_humidity_unsupported(self):
+        with self.assertRaises(NotImplementedError):
+            await self.subject.async_set_humidity(50)
+
+    def test_hvac_mode(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT])
+
+    async def test_turn_on(self):
+        async with assert_device_properties_set(
+            self.subject._device, {HVACMODE_DPS: True}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
+
+    async def test_turn_off(self):
+        async with assert_device_properties_set(
+            self.subject._device, {HVACMODE_DPS: False}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
+
+    def test_preset_mode(self):
+        self.dps[PRESET_DPS] = "C"
+        self.assertEqual(self.subject.preset_mode, "comfort")
+
+        self.dps[PRESET_DPS] = "ECO"
+        self.assertEqual(self.subject.preset_mode, "eco")
+
+        self.dps[PRESET_DPS] = "AF"
+        self.assertEqual(self.subject.preset_mode, "away")
+
+        self.dps[PRESET_DPS] = None
+        self.assertIs(self.subject.preset_mode, None)
+
+    def test_preset_modes(self):
+        self.assertCountEqual(self.subject.preset_modes, ["comfort", "eco", "away"])
+
+    async def test_set_preset_mode_to_comfort(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: "C"},
+        ):
+            await self.subject.async_set_preset_mode("comfort")
+
+    async def test_set_preset_mode_to_eco(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: "ECO"},
+        ):
+            await self.subject.async_set_preset_mode("eco")
+
+    async def test_set_preset_mode_to_anti_freeze(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: "AF"},
+        ):
+            await self.subject.async_set_preset_mode("away")
+
+    def test_power_level_returns_user_power_level(self):
+        self.dps[SWING_DPS] = "user"
+
+        self.dps[POWERLEVEL_DPS] = "stop"
+        self.assertEqual(self.subject.swing_mode, "Stop")
+
+        self.dps[POWERLEVEL_DPS] = "3"
+        self.assertEqual(self.subject.swing_mode, "3")
+
+    def test_non_user_swing_mode(self):
+        self.dps[SWING_DPS] = "stop"
+        self.assertEqual(self.subject.swing_mode, "Stop")
+
+        self.dps[SWING_DPS] = "auto"
+        self.assertEqual(self.subject.swing_mode, "Auto")
+
+        self.dps[SWING_DPS] = None
+        self.assertIs(self.subject.swing_mode, None)
+
+    def test_swing_modes(self):
+        self.assertCountEqual(
+            self.subject.swing_modes,
+            ["Stop", "1", "2", "3", "4", "5", "Auto"],
+        )
+
+    async def test_set_power_level_to_stop(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {POWERLEVEL_DPS: "stop", SWING_DPS: "stop"},
+        ):
+            await self.subject.async_set_swing_mode("Stop")
+
+    async def test_set_swing_mode_to_auto(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {SWING_DPS: "auto"},
+        ):
+            await self.subject.async_set_swing_mode("Auto")
+
+    async def test_set_power_level_to_numeric_value(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {SWING_DPS: "user", POWERLEVEL_DPS: "3"},
+        ):
+            await self.subject.async_set_swing_mode("3")
+
+    def test_extra_state_attributes(self):
+        self.dps[ERROR_DPS] = "something"
+        self.dps[TIMER_DPS] = 5
+        self.dps[TIMERACT_DPS] = True
+        self.dps[POWERLEVEL_DPS] = 4
+
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {
+                "error": "something",
+                "timer": 5,
+                "timer_mode": True,
+                "power_level": "4",
+            },
+        )
+
+    def test_light_icon(self):
+        self.dps[LIGHT_DPS] = True
+        self.assertEqual(self.basicLight.icon, "mdi:led-on")
+
+        self.dps[LIGHT_DPS] = False
+        self.assertEqual(self.basicLight.icon, "mdi:led-off")

+ 9 - 12
tests/devices/test_grid_connect_double_power_point.py

@@ -1,10 +1,7 @@
 """Tests for the switch entity."""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_ENERGY,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_VOLTAGE,
     ELECTRIC_CURRENT_MILLIAMPERE,
     ELECTRIC_POTENTIAL_VOLT,
     ENERGY_WATT_HOUR,
@@ -71,17 +68,17 @@ class TestGridConnectDoubleSwitch(
                 {
                     "name": "switch_outlet_1",
                     "dps": SWITCH1_DPS,
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "name": "switch_outlet_2",
                     "dps": SWITCH2_DPS,
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "name": "switch_master",
                     "dps": MASTER_DPS,
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                     "power_dps": POWER_DPS,
                     "power_scale": 10,
                 },
@@ -92,21 +89,21 @@ class TestGridConnectDoubleSwitch(
                 {
                     "name": "sensor_energy",
                     "dps": ENERGY_DPS,
-                    "device_class": DEVICE_CLASS_ENERGY,
+                    "device_class": SensorDeviceClass.ENERGY,
                     "unit": ENERGY_WATT_HOUR,
                     "state_class": "total_increasing",
                 },
                 {
                     "name": "sensor_current",
                     "dps": CURRENT_DPS,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_power",
                     "dps": POWER_DPS,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": SensorDeviceClass.POWER,
                     "unit": POWER_WATT,
                     "state_class": "measurement",
                     "testdata": (1234, 123.4),
@@ -114,7 +111,7 @@ class TestGridConnectDoubleSwitch(
                 {
                     "name": "sensor_voltage",
                     "dps": VOLTAGE_DPS,
-                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "device_class": SensorDeviceClass.VOLTAGE,
                     "unit": ELECTRIC_POTENTIAL_VOLT,
                     "state_class": "measurement",
                     "testdata": (2345, 234.5),

+ 2 - 2
tests/devices/test_himox_h05_purifier.py

@@ -1,6 +1,6 @@
 from homeassistant.components.fan import SUPPORT_PRESET_MODE
 from homeassistant.components.sensor import (
-    DEVICE_CLASS_TEMPERATURE,
+    SensorDeviceClass,
     STATE_CLASS_MEASUREMENT,
 )
 from homeassistant.const import (
@@ -60,7 +60,7 @@ class TestHimoxH05Purifier(
                     "dps": TEMP_DPS,
                     "name": "sensor_current_temperature",
                     "unit": TEMP_CELSIUS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "state_class": STATE_CLASS_MEASUREMENT,
                 },
                 {

+ 310 - 310
tests/devices/test_hysen_hy08we2_thermostat.py

@@ -1,310 +1,310 @@
-from homeassistant.components.climate.const import (
-    CURRENT_HVAC_HEAT,
-    CURRENT_HVAC_IDLE,
-    CURRENT_HVAC_OFF,
-    HVAC_MODE_HEAT,
-    HVAC_MODE_OFF,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_TARGET_TEMPERATURE,
-)
-from homeassistant.const import (
-    DEVICE_CLASS_TEMPERATURE,
-    STATE_UNAVAILABLE,
-    TEMP_CELSIUS,
-    TIME_DAYS,
-)
-
-from ..const import HYSEN_HY08WE2_THERMOSTAT_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.climate import TargetTemperatureTests
-from ..mixins.lock import BasicLockTests
-from ..mixins.number import MultiNumberTests
-from ..mixins.select import MultiSelectTests
-from ..mixins.sensor import BasicSensorTests
-from .base_device_tests import TuyaDeviceTestCase
-
-HVACMODE_DPS = "1"
-TEMPERATURE_DPS = "2"
-CURRENTTEMP_DPS = "3"
-PRESET_DPS = "4"
-LOCK_DPS = "6"
-UNKNOWN12_DPS = "12"
-UNKNOWN101_DPS = "101"
-HVACACTION_DPS = "102"
-EXTTEMP_DPS = "103"
-HOLIDAYS_DPS = "104"
-HOLIDAYTEMP_DPS = "105"
-UNKNOWN106_DPS = "106"
-UNKNOWN107_DPS = "107"
-UNKNOWN108_DPS = "108"
-CALIBOFFSET_DPS = "109"
-CALIBSWINGINT_DPS = "110"
-CALIBSWINGEXT_DPS = "111"
-HIGHTEMP_DPS = "112"
-LOWTEMP_DPS = "113"
-MAXTEMP_DPS = "114"
-MINTEMP_DPS = "115"
-SENSOR_DPS = "116"
-INITIAL_DPS = "117"
-SCHED_DPS = "118"
-
-
-class TestHysenHY08WE2Thermostat(
-    BasicLockTests,
-    MultiNumberTests,
-    MultiSelectTests,
-    BasicSensorTests,
-    TargetTemperatureTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig(
-            "hysen_hy08we2_thermostat.yaml",
-            HYSEN_HY08WE2_THERMOSTAT_PAYLOAD,
-        )
-        self.subject = self.entities.get("climate")
-        self.setUpTargetTemperature(
-            TEMPERATURE_DPS,
-            self.subject,
-            min=5.0,
-            max=30.0,
-            scale=10,
-            step=5,
-        )
-        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
-        self.setUpMultiSelect(
-            [
-                {
-                    "dps": SCHED_DPS,
-                    "name": "select_schedule",
-                    "options": {
-                        "2days": "5 + 2 day",
-                        "1days": "6 + 1 day",
-                        "0days": "7 day",
-                    },
-                },
-                {
-                    "dps": INITIAL_DPS,
-                    "name": "select_initial_state",
-                    "options": {
-                        "keep": "Previous",
-                        "on": "On",
-                        "off": "Off",
-                    },
-                },
-                {
-                    "dps": SENSOR_DPS,
-                    "name": "select_temperature_sensor",
-                    "options": {
-                        "in": "Internal",
-                        "ext": "External",
-                        "all": "Both",
-                    },
-                },
-            ],
-        )
-        self.setUpBasicSensor(
-            EXTTEMP_DPS,
-            self.entities.get("sensor_external_temperature"),
-            device_class=DEVICE_CLASS_TEMPERATURE,
-            testdata=(205, 20.5),
-            unit=TEMP_CELSIUS,
-            state_class="measurement",
-        )
-        self.setUpMultiNumber(
-            [
-                {
-                    "dps": HOLIDAYS_DPS,
-                    "name": "number_holiday_days",
-                    "min": 1,
-                    "max": 30,
-                    "unit": TIME_DAYS,
-                },
-                {
-                    "dps": HOLIDAYTEMP_DPS,
-                    "name": "number_holiday_temperature",
-                    "min": 5,
-                    "max": 30,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": CALIBOFFSET_DPS,
-                    "name": "number_calibration_offset",
-                    "min": -9,
-                    "max": 9,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": CALIBSWINGINT_DPS,
-                    "name": "number_calibration_swing_internal",
-                    "min": 0.5,
-                    "max": 2.5,
-                    "scale": 10,
-                    "step": 0.1,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": CALIBSWINGEXT_DPS,
-                    "name": "number_calibration_swing_external",
-                    "min": 0.1,
-                    "max": 1.0,
-                    "scale": 10,
-                    "step": 0.1,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": HIGHTEMP_DPS,
-                    "name": "number_high_temperature_protection",
-                    "min": 35,
-                    "max": 70,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": LOWTEMP_DPS,
-                    "name": "number_low_temperature_protection",
-                    "min": 1,
-                    "max": 10,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": MINTEMP_DPS,
-                    "name": "number_low_temperature_limit",
-                    "min": 1,
-                    "max": 10,
-                    "unit": TEMP_CELSIUS,
-                },
-                {
-                    "dps": MAXTEMP_DPS,
-                    "name": "number_high_temperature_limit",
-                    "min": 2,
-                    "max": 70,
-                    "unit": TEMP_CELSIUS,
-                },
-            ],
-        )
-        self.mark_secondary(
-            [
-                "lock_child_lock",
-                "number_holiday_days",
-                "number_holiday_temperature",
-                "number_calibration_offset",
-                "number_calibration_swing_internal",
-                "number_calibration_swing_external",
-                "number_high_temperature_protection",
-                "number_low_temperature_protection",
-                "number_low_temperature_limit",
-                "number_high_temperature_limit",
-                "select_temperature_sensor",
-                "select_initial_state",
-                "select_schedule",
-            ],
-        )
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_PRESET_MODE | SUPPORT_TARGET_TEMPERATURE,
-        )
-
-    def test_current_temperature(self):
-        self.dps[CURRENTTEMP_DPS] = 685
-        self.assertEqual(self.subject.current_temperature, 68.5)
-
-    def test_hvac_mode(self):
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
-
-        self.dps[HVACMODE_DPS] = None
-        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_hvac_modes(self):
-        self.assertCountEqual(
-            self.subject.hvac_modes,
-            [
-                HVAC_MODE_HEAT,
-                HVAC_MODE_OFF,
-            ],
-        )
-
-    async def test_set_hvac_mode_heat(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {HVACMODE_DPS: True},
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
-
-    async def test_set_hvac_mode_off(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {HVACMODE_DPS: False},
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
-
-    def test_hvac_action(self):
-        self.dps[HVACMODE_DPS] = True
-        self.dps[HVACACTION_DPS] = True
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
-        self.dps[HVACACTION_DPS] = False
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
-
-    def test_preset_modes(self):
-        self.assertCountEqual(
-            self.subject.preset_modes,
-            ["Manual", "Program", "Program Override", "Holiday"],
-        )
-
-    def test_preset_mode(self):
-        self.dps[PRESET_DPS] = "Manual"
-        self.assertEqual(self.subject.preset_mode, "Manual")
-        self.dps[PRESET_DPS] = "Program"
-        self.assertEqual(self.subject.preset_mode, "Program")
-        self.dps[PRESET_DPS] = "TempProg"
-        self.assertEqual(self.subject.preset_mode, "Program Override")
-        self.dps[PRESET_DPS] = "Holiday"
-        self.assertEqual(self.subject.preset_mode, "Holiday")
-
-    # Override - since min and max are set by attributes, the range
-    # allowed when setting is wider than normal.  The thermostat seems
-    # to be configurable as at least a water heater (to 212F), as tuya
-    # doc says max 1000.0 (after scaling)
-    async def test_set_target_temperature_fails_outside_valid_range(self):
-        with self.assertRaisesRegex(
-            ValueError,
-            f"temperature \\(0\\) must be between 0.5 and 122.0",
-        ):
-            await self.subject.async_set_target_temperature(0)
-        with self.assertRaisesRegex(
-            ValueError,
-            f"temperature \\(122.5\\) must be between 0.5 and 122.0",
-        ):
-            await self.subject.async_set_target_temperature(122.5)
-
-    def test_extra_state_attributes(self):
-        self.dps[UNKNOWN12_DPS] = 12
-        self.dps[UNKNOWN101_DPS] = True
-        self.dps[UNKNOWN106_DPS] = False
-        self.dps[UNKNOWN107_DPS] = True
-        self.dps[UNKNOWN108_DPS] = False
-        self.assertDictEqual(
-            self.subject.extra_state_attributes,
-            {
-                "unknown_12": 12,
-                "unknown_101": True,
-                "unknown_106": False,
-                "unknown_107": True,
-                "unknown_108": False,
-            },
-        )
-
-    def test_icons(self):
-        self.dps[LOCK_DPS] = True
-        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right-off")
-        self.dps[LOCK_DPS] = False
-        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right")
+from homeassistant.components.climate.const import (
+    CURRENT_HVAC_HEAT,
+    CURRENT_HVAC_IDLE,
+    CURRENT_HVAC_OFF,
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    SUPPORT_PRESET_MODE,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    STATE_UNAVAILABLE,
+    TEMP_CELSIUS,
+    TIME_DAYS,
+)
+
+from ..const import HYSEN_HY08WE2_THERMOSTAT_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.lock import BasicLockTests
+from ..mixins.number import MultiNumberTests
+from ..mixins.select import MultiSelectTests
+from ..mixins.sensor import BasicSensorTests
+from .base_device_tests import TuyaDeviceTestCase
+
+HVACMODE_DPS = "1"
+TEMPERATURE_DPS = "2"
+CURRENTTEMP_DPS = "3"
+PRESET_DPS = "4"
+LOCK_DPS = "6"
+UNKNOWN12_DPS = "12"
+UNKNOWN101_DPS = "101"
+HVACACTION_DPS = "102"
+EXTTEMP_DPS = "103"
+HOLIDAYS_DPS = "104"
+HOLIDAYTEMP_DPS = "105"
+UNKNOWN106_DPS = "106"
+UNKNOWN107_DPS = "107"
+UNKNOWN108_DPS = "108"
+CALIBOFFSET_DPS = "109"
+CALIBSWINGINT_DPS = "110"
+CALIBSWINGEXT_DPS = "111"
+HIGHTEMP_DPS = "112"
+LOWTEMP_DPS = "113"
+MAXTEMP_DPS = "114"
+MINTEMP_DPS = "115"
+SENSOR_DPS = "116"
+INITIAL_DPS = "117"
+SCHED_DPS = "118"
+
+
+class TestHysenHY08WE2Thermostat(
+    BasicLockTests,
+    MultiNumberTests,
+    MultiSelectTests,
+    BasicSensorTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig(
+            "hysen_hy08we2_thermostat.yaml",
+            HYSEN_HY08WE2_THERMOSTAT_PAYLOAD,
+        )
+        self.subject = self.entities.get("climate")
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=5.0,
+            max=30.0,
+            scale=10,
+            step=5,
+        )
+        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
+        self.setUpMultiSelect(
+            [
+                {
+                    "dps": SCHED_DPS,
+                    "name": "select_schedule",
+                    "options": {
+                        "2days": "5 + 2 day",
+                        "1days": "6 + 1 day",
+                        "0days": "7 day",
+                    },
+                },
+                {
+                    "dps": INITIAL_DPS,
+                    "name": "select_initial_state",
+                    "options": {
+                        "keep": "Previous",
+                        "on": "On",
+                        "off": "Off",
+                    },
+                },
+                {
+                    "dps": SENSOR_DPS,
+                    "name": "select_temperature_sensor",
+                    "options": {
+                        "in": "Internal",
+                        "ext": "External",
+                        "all": "Both",
+                    },
+                },
+            ],
+        )
+        self.setUpBasicSensor(
+            EXTTEMP_DPS,
+            self.entities.get("sensor_external_temperature"),
+            device_class=SensorDeviceClass.TEMPERATURE,
+            testdata=(205, 20.5),
+            unit=TEMP_CELSIUS,
+            state_class="measurement",
+        )
+        self.setUpMultiNumber(
+            [
+                {
+                    "dps": HOLIDAYS_DPS,
+                    "name": "number_holiday_days",
+                    "min": 1,
+                    "max": 30,
+                    "unit": TIME_DAYS,
+                },
+                {
+                    "dps": HOLIDAYTEMP_DPS,
+                    "name": "number_holiday_temperature",
+                    "min": 5,
+                    "max": 30,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": CALIBOFFSET_DPS,
+                    "name": "number_calibration_offset",
+                    "min": -9,
+                    "max": 9,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": CALIBSWINGINT_DPS,
+                    "name": "number_calibration_swing_internal",
+                    "min": 0.5,
+                    "max": 2.5,
+                    "scale": 10,
+                    "step": 0.1,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": CALIBSWINGEXT_DPS,
+                    "name": "number_calibration_swing_external",
+                    "min": 0.1,
+                    "max": 1.0,
+                    "scale": 10,
+                    "step": 0.1,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": HIGHTEMP_DPS,
+                    "name": "number_high_temperature_protection",
+                    "min": 35,
+                    "max": 70,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": LOWTEMP_DPS,
+                    "name": "number_low_temperature_protection",
+                    "min": 1,
+                    "max": 10,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": MINTEMP_DPS,
+                    "name": "number_low_temperature_limit",
+                    "min": 1,
+                    "max": 10,
+                    "unit": TEMP_CELSIUS,
+                },
+                {
+                    "dps": MAXTEMP_DPS,
+                    "name": "number_high_temperature_limit",
+                    "min": 2,
+                    "max": 70,
+                    "unit": TEMP_CELSIUS,
+                },
+            ],
+        )
+        self.mark_secondary(
+            [
+                "lock_child_lock",
+                "number_holiday_days",
+                "number_holiday_temperature",
+                "number_calibration_offset",
+                "number_calibration_swing_internal",
+                "number_calibration_swing_external",
+                "number_high_temperature_protection",
+                "number_low_temperature_protection",
+                "number_low_temperature_limit",
+                "number_high_temperature_limit",
+                "select_temperature_sensor",
+                "select_initial_state",
+                "select_schedule",
+            ],
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_PRESET_MODE | SUPPORT_TARGET_TEMPERATURE,
+        )
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 685
+        self.assertEqual(self.subject.current_temperature, 68.5)
+
+    def test_hvac_mode(self):
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
+
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(
+            self.subject.hvac_modes,
+            [
+                HVAC_MODE_HEAT,
+                HVAC_MODE_OFF,
+            ],
+        )
+
+    async def test_set_hvac_mode_heat(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {HVACMODE_DPS: True},
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
+
+    async def test_set_hvac_mode_off(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {HVACMODE_DPS: False},
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
+
+    def test_hvac_action(self):
+        self.dps[HVACMODE_DPS] = True
+        self.dps[HVACACTION_DPS] = True
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
+        self.dps[HVACACTION_DPS] = False
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
+
+    def test_preset_modes(self):
+        self.assertCountEqual(
+            self.subject.preset_modes,
+            ["Manual", "Program", "Program Override", "Holiday"],
+        )
+
+    def test_preset_mode(self):
+        self.dps[PRESET_DPS] = "Manual"
+        self.assertEqual(self.subject.preset_mode, "Manual")
+        self.dps[PRESET_DPS] = "Program"
+        self.assertEqual(self.subject.preset_mode, "Program")
+        self.dps[PRESET_DPS] = "TempProg"
+        self.assertEqual(self.subject.preset_mode, "Program Override")
+        self.dps[PRESET_DPS] = "Holiday"
+        self.assertEqual(self.subject.preset_mode, "Holiday")
+
+    # Override - since min and max are set by attributes, the range
+    # allowed when setting is wider than normal.  The thermostat seems
+    # to be configurable as at least a water heater (to 212F), as tuya
+    # doc says max 1000.0 (after scaling)
+    async def test_set_target_temperature_fails_outside_valid_range(self):
+        with self.assertRaisesRegex(
+            ValueError,
+            f"temperature \\(0\\) must be between 0.5 and 122.0",
+        ):
+            await self.subject.async_set_target_temperature(0)
+        with self.assertRaisesRegex(
+            ValueError,
+            f"temperature \\(122.5\\) must be between 0.5 and 122.0",
+        ):
+            await self.subject.async_set_target_temperature(122.5)
+
+    def test_extra_state_attributes(self):
+        self.dps[UNKNOWN12_DPS] = 12
+        self.dps[UNKNOWN101_DPS] = True
+        self.dps[UNKNOWN106_DPS] = False
+        self.dps[UNKNOWN107_DPS] = True
+        self.dps[UNKNOWN108_DPS] = False
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {
+                "unknown_12": 12,
+                "unknown_101": True,
+                "unknown_106": False,
+                "unknown_107": True,
+                "unknown_108": False,
+            },
+        )
+
+    def test_icons(self):
+        self.dps[LOCK_DPS] = True
+        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right-off")
+        self.dps[LOCK_DPS] = False
+        self.assertEqual(self.basicLock.icon, "mdi:hand-back-right")

+ 6 - 10
tests/devices/test_inkbird_itc306a_thermostat.py

@@ -1,8 +1,4 @@
-from homeassistant.components.binary_sensor import (
-    DEVICE_CLASS_COLD,
-    DEVICE_CLASS_HEAT,
-    DEVICE_CLASS_PROBLEM,
-)
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     CURRENT_HVAC_HEAT,
     CURRENT_HVAC_IDLE,
@@ -66,27 +62,27 @@ class TestInkbirdThermostat(
                 {
                     "name": "binary_sensor_high_temperature",
                     "dps": ALARM_HIGH_DPS,
-                    "device_class": DEVICE_CLASS_HEAT,
+                    "device_class": BinarySensorDeviceClass.HEAT,
                 },
                 {
                     "name": "binary_sensor_low_temperature",
                     "dps": ALARM_LOW_DPS,
-                    "device_class": DEVICE_CLASS_COLD,
+                    "device_class": BinarySensorDeviceClass.COLD,
                 },
                 {
                     "name": "binary_sensor_continuous_heat",
                     "dps": ALARM_TIME_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                 },
                 {
                     "name": "binary_sensor_unbalanced",
                     "dps": ALARM_DIFF_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                 },
                 {
                     "name": "binary_sensor_error",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (1, 0),
                 },
             ]

+ 5 - 9
tests/devices/test_inkbird_itc308_thermostat.py

@@ -1,8 +1,4 @@
-from homeassistant.components.binary_sensor import (
-    DEVICE_CLASS_COLD,
-    DEVICE_CLASS_HEAT,
-    DEVICE_CLASS_PROBLEM,
-)
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     CURRENT_HVAC_COOL,
     CURRENT_HVAC_HEAT,
@@ -71,22 +67,22 @@ class TestInkbirdITC308Thermostat(
                 {
                     "name": "binary_sensor_high_temperature",
                     "dps": ALARM_HIGH_DPS,
-                    "device_class": DEVICE_CLASS_HEAT,
+                    "device_class": BinarySensorDeviceClass.HEAT,
                 },
                 {
                     "name": "binary_sensor_low_temperature",
                     "dps": ALARM_LOW_DPS,
-                    "device_class": DEVICE_CLASS_COLD,
+                    "device_class": BinarySensorDeviceClass.COLD,
                 },
                 {
                     "name": "binary_sensor_sensor_fault",
                     "dps": ALARM_SENSOR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                 },
                 {
                     "name": "binary_sensor_error",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (1, 0),
                 },
             ]

+ 2 - 2
tests/devices/test_ips_pro_heatpump.py

@@ -7,8 +7,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_POWER_FACTOR,
     PERCENTAGE,
     STATE_UNAVAILABLE,
     TEMP_CELSIUS,
@@ -54,7 +54,7 @@ class TestIpsProHeatpump(
             POWERLEVEL_DPS,
             self.entities.get("sensor_power_level"),
             unit=PERCENTAGE,
-            device_class=DEVICE_CLASS_POWER_FACTOR,
+            device_class=SensorDeviceClass.POWER_FACTOR,
             state_class="measurement",
         )
         self.mark_secondary(["sensor_power_level"])

+ 256 - 260
tests/devices/test_jjpro_jpd01_dehumidifier.py

@@ -1,260 +1,256 @@
-from homeassistant.components.binary_sensor import (
-    DEVICE_CLASS_COLD,
-    DEVICE_CLASS_PROBLEM,
-)
-from homeassistant.components.fan import SUPPORT_SET_SPEED
-from homeassistant.components.humidifier import SUPPORT_MODES
-from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
-    DEVICE_CLASS_TEMPERATURE,
-    PERCENTAGE,
-    TIME_HOURS,
-    TEMP_CELSIUS,
-)
-from ..const import JJPRO_JPD01_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.binary_sensor import MultiBinarySensorTests
-from ..mixins.number import BasicNumberTests
-from ..mixins.sensor import MultiSensorTests
-from ..mixins.switch import MultiSwitchTests, SwitchableTests
-from .base_device_tests import TuyaDeviceTestCase
-
-SWITCH_DPS = "1"
-MODE_DPS = "2"
-HUMIDITY_DPS = "4"
-ANION_DPS = "5"
-FAN_DPS = "6"
-ERROR_DPS = "11"
-TIMER_DPS = "12"
-UNKNOWN101_DPS = "101"
-SLEEP_DPS = "102"
-CURRENTTEMP_DPS = "103"
-CURRENTHUMID_DPS = "104"
-DEFROST_DPS = "105"
-
-
-class TestJJProJPD01Dehumidifier(
-    BasicNumberTests,
-    MultiBinarySensorTests,
-    MultiSensorTests,
-    MultiSwitchTests,
-    SwitchableTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig("jjpro_jpd01_dehumidifier.yaml", JJPRO_JPD01_PAYLOAD)
-        self.subject = self.entities.get("humidifier")
-        self.setUpSwitchable(SWITCH_DPS, self.subject)
-        self.fan = self.entities.get("fan")
-        self.setUpBasicNumber(
-            TIMER_DPS,
-            self.entities.get("number_timer"),
-            max=24,
-            unit=TIME_HOURS,
-        )
-        self.setUpMultiBinarySensors(
-            [
-                {
-                    "dps": ERROR_DPS,
-                    "name": "binary_sensor_tank",
-                    "device_class": DEVICE_CLASS_PROBLEM,
-                    "testdata": (1, 0),
-                },
-                {
-                    "dps": DEFROST_DPS,
-                    "name": "binary_sensor_defrost",
-                    "device_class": DEVICE_CLASS_COLD,
-                },
-            ]
-        )
-        self.setUpMultiSensors(
-            [
-                {
-                    "dps": CURRENTHUMID_DPS,
-                    "name": "sensor_current_humidity",
-                    "device_class": DEVICE_CLASS_HUMIDITY,
-                    "state_class": "measurement",
-                    "unit": PERCENTAGE,
-                },
-                {
-                    "dps": CURRENTTEMP_DPS,
-                    "name": "sensor_current_temperature",
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
-                    "state_class": "measurement",
-                    "unit": TEMP_CELSIUS,
-                },
-            ]
-        )
-        self.setUpMultiSwitch(
-            [
-                {
-                    "dps": SLEEP_DPS,
-                    "name": "switch_sleep",
-                },
-                {
-                    "dps": ANION_DPS,
-                    "name": "switch_ionizer",
-                },
-            ]
-        )
-        self.mark_secondary(
-            [
-                "binary_sensor_tank",
-                "binary_sensor_defrost",
-                "number_timer",
-            ]
-        )
-
-    def test_supported_features(self):
-        self.assertEqual(self.subject.supported_features, SUPPORT_MODES)
-        self.assertEqual(self.fan.supported_features, SUPPORT_SET_SPEED)
-
-    def test_icon(self):
-        """Test that the icon is as expected."""
-        self.dps[SWITCH_DPS] = True
-        self.dps[ANION_DPS] = False
-        self.dps[SLEEP_DPS] = False
-        self.dps[DEFROST_DPS] = False
-        self.dps[MODE_DPS] = "0"
-        self.assertEqual(self.subject.icon, "mdi:water-outline")
-
-        self.dps[SWITCH_DPS] = False
-        self.assertEqual(self.subject.icon, "mdi:air-humidifier-off")
-        self.dps[MODE_DPS] = "1"
-        self.assertEqual(self.subject.icon, "mdi:air-humidifier-off")
-
-        self.dps[SWITCH_DPS] = True
-        self.assertEqual(self.subject.icon, "mdi:water-plus-outline")
-        self.dps[MODE_DPS] = "2"
-        self.assertEqual(self.subject.icon, "mdi:tshirt-crew-outline")
-        self.dps[MODE_DPS] = "3"
-        self.assertEqual(self.subject.icon, "mdi:tailwind")
-        self.dps[ERROR_DPS] = 8
-        self.assertEqual(self.subject.icon, "mdi:cup-water")
-        self.dps[DEFROST_DPS] = True
-        self.assertEqual(self.subject.icon, "mdi:cup-water")
-        self.dps[ERROR_DPS] = 0
-        self.assertEqual(self.subject.icon, "mdi:snowflake-melt")
-
-    def test_min_target_humidity(self):
-        self.assertEqual(self.subject.min_humidity, 30)
-
-    def test_max_target_humidity(self):
-        self.assertEqual(self.subject.max_humidity, 80)
-
-    def test_target_humidity(self):
-        self.dps[HUMIDITY_DPS] = 55
-        self.assertEqual(self.subject.target_humidity, 55)
-
-    async def test_fan_turn_on(self):
-        async with assert_device_properties_set(
-            self.subject._device, {SWITCH_DPS: True}
-        ):
-            await self.fan.async_turn_on()
-
-    async def test_fan_turn_off(self):
-        async with assert_device_properties_set(
-            self.subject._device, {SWITCH_DPS: False}
-        ):
-            await self.fan.async_turn_off()
-
-    def test_modes(self):
-        self.assertCountEqual(
-            self.subject.available_modes,
-            [
-                "Normal",
-                "Continuous",
-                "Strong",
-                "Ventilation",
-            ],
-        )
-
-    def test_mode(self):
-        self.dps[MODE_DPS] = "0"
-        self.assertEqual(self.subject.mode, "Normal")
-        self.dps[MODE_DPS] = "1"
-        self.assertEqual(self.subject.mode, "Continuous")
-        self.dps[MODE_DPS] = "2"
-        self.assertEqual(self.subject.mode, "Strong")
-        self.dps[MODE_DPS] = "3"
-        self.assertEqual(self.subject.mode, "Ventilation")
-
-    async def test_set_mode_to_normal(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                MODE_DPS: "0",
-            },
-        ):
-            await self.subject.async_set_mode("Normal")
-            self.subject._device.anticipate_property_value.assert_not_called()
-
-    async def test_set_mode_to_continuous(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                MODE_DPS: "1",
-            },
-        ):
-            await self.subject.async_set_mode("Continuous")
-            self.subject._device.anticipate_property_value.assert_not_called()
-
-    async def test_set_mode_to_strong(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                MODE_DPS: "2",
-            },
-        ):
-            await self.subject.async_set_mode("Strong")
-            self.subject._device.anticipate_property_value.assert_not_called()
-
-    async def test_set_mode_to_ventilation(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                MODE_DPS: "3",
-            },
-        ):
-            await self.subject.async_set_mode("Ventilation")
-            self.subject._device.anticipate_property_value.assert_not_called()
-
-    def test_fan_speed_steps(self):
-        self.assertEqual(self.fan.speed_count, 2)
-
-    def test_fan_speed(self):
-        self.dps[FAN_DPS] = "1"
-        self.assertEqual(self.fan.percentage, 50)
-        self.dps[FAN_DPS] = "3"
-
-    async def test_fan_set_speed_to_low(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                FAN_DPS: "1",
-            },
-        ):
-            await self.fan.async_set_percentage(50)
-
-    async def test_fan_set_speed_to_high(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {
-                FAN_DPS: "3",
-            },
-        ):
-            await self.fan.async_set_percentage(100)
-
-    def test_extra_state_attributes(self):
-        self.dps[UNKNOWN101_DPS] = True
-        self.dps[ERROR_DPS] = 5
-        self.assertDictEqual(
-            self.subject.extra_state_attributes,
-            {
-                "error": 5,
-                "unknown_101": True,
-            },
-        )
-        self.assertEqual(self.fan.extra_state_attributes, {})
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
+from homeassistant.components.fan import SUPPORT_SET_SPEED
+from homeassistant.components.humidifier import SUPPORT_MODES
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    PERCENTAGE,
+    TIME_HOURS,
+    TEMP_CELSIUS,
+)
+from ..const import JJPRO_JPD01_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.binary_sensor import MultiBinarySensorTests
+from ..mixins.number import BasicNumberTests
+from ..mixins.sensor import MultiSensorTests
+from ..mixins.switch import MultiSwitchTests, SwitchableTests
+from .base_device_tests import TuyaDeviceTestCase
+
+SWITCH_DPS = "1"
+MODE_DPS = "2"
+HUMIDITY_DPS = "4"
+ANION_DPS = "5"
+FAN_DPS = "6"
+ERROR_DPS = "11"
+TIMER_DPS = "12"
+UNKNOWN101_DPS = "101"
+SLEEP_DPS = "102"
+CURRENTTEMP_DPS = "103"
+CURRENTHUMID_DPS = "104"
+DEFROST_DPS = "105"
+
+
+class TestJJProJPD01Dehumidifier(
+    BasicNumberTests,
+    MultiBinarySensorTests,
+    MultiSensorTests,
+    MultiSwitchTests,
+    SwitchableTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("jjpro_jpd01_dehumidifier.yaml", JJPRO_JPD01_PAYLOAD)
+        self.subject = self.entities.get("humidifier")
+        self.setUpSwitchable(SWITCH_DPS, self.subject)
+        self.fan = self.entities.get("fan")
+        self.setUpBasicNumber(
+            TIMER_DPS,
+            self.entities.get("number_timer"),
+            max=24,
+            unit=TIME_HOURS,
+        )
+        self.setUpMultiBinarySensors(
+            [
+                {
+                    "dps": ERROR_DPS,
+                    "name": "binary_sensor_tank",
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
+                    "testdata": (1, 0),
+                },
+                {
+                    "dps": DEFROST_DPS,
+                    "name": "binary_sensor_defrost",
+                    "device_class": BinarySensorDeviceClass.COLD,
+                },
+            ]
+        )
+        self.setUpMultiSensors(
+            [
+                {
+                    "dps": CURRENTHUMID_DPS,
+                    "name": "sensor_current_humidity",
+                    "device_class": SensorDeviceClass.HUMIDITY,
+                    "state_class": "measurement",
+                    "unit": PERCENTAGE,
+                },
+                {
+                    "dps": CURRENTTEMP_DPS,
+                    "name": "sensor_current_temperature",
+                    "device_class": SensorDeviceClass.TEMPERATURE,
+                    "state_class": "measurement",
+                    "unit": TEMP_CELSIUS,
+                },
+            ]
+        )
+        self.setUpMultiSwitch(
+            [
+                {
+                    "dps": SLEEP_DPS,
+                    "name": "switch_sleep",
+                },
+                {
+                    "dps": ANION_DPS,
+                    "name": "switch_ionizer",
+                },
+            ]
+        )
+        self.mark_secondary(
+            [
+                "binary_sensor_tank",
+                "binary_sensor_defrost",
+                "number_timer",
+            ]
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(self.subject.supported_features, SUPPORT_MODES)
+        self.assertEqual(self.fan.supported_features, SUPPORT_SET_SPEED)
+
+    def test_icon(self):
+        """Test that the icon is as expected."""
+        self.dps[SWITCH_DPS] = True
+        self.dps[ANION_DPS] = False
+        self.dps[SLEEP_DPS] = False
+        self.dps[DEFROST_DPS] = False
+        self.dps[MODE_DPS] = "0"
+        self.assertEqual(self.subject.icon, "mdi:water-outline")
+
+        self.dps[SWITCH_DPS] = False
+        self.assertEqual(self.subject.icon, "mdi:air-humidifier-off")
+        self.dps[MODE_DPS] = "1"
+        self.assertEqual(self.subject.icon, "mdi:air-humidifier-off")
+
+        self.dps[SWITCH_DPS] = True
+        self.assertEqual(self.subject.icon, "mdi:water-plus-outline")
+        self.dps[MODE_DPS] = "2"
+        self.assertEqual(self.subject.icon, "mdi:tshirt-crew-outline")
+        self.dps[MODE_DPS] = "3"
+        self.assertEqual(self.subject.icon, "mdi:tailwind")
+        self.dps[ERROR_DPS] = 8
+        self.assertEqual(self.subject.icon, "mdi:cup-water")
+        self.dps[DEFROST_DPS] = True
+        self.assertEqual(self.subject.icon, "mdi:cup-water")
+        self.dps[ERROR_DPS] = 0
+        self.assertEqual(self.subject.icon, "mdi:snowflake-melt")
+
+    def test_min_target_humidity(self):
+        self.assertEqual(self.subject.min_humidity, 30)
+
+    def test_max_target_humidity(self):
+        self.assertEqual(self.subject.max_humidity, 80)
+
+    def test_target_humidity(self):
+        self.dps[HUMIDITY_DPS] = 55
+        self.assertEqual(self.subject.target_humidity, 55)
+
+    async def test_fan_turn_on(self):
+        async with assert_device_properties_set(
+            self.subject._device, {SWITCH_DPS: True}
+        ):
+            await self.fan.async_turn_on()
+
+    async def test_fan_turn_off(self):
+        async with assert_device_properties_set(
+            self.subject._device, {SWITCH_DPS: False}
+        ):
+            await self.fan.async_turn_off()
+
+    def test_modes(self):
+        self.assertCountEqual(
+            self.subject.available_modes,
+            [
+                "Normal",
+                "Continuous",
+                "Strong",
+                "Ventilation",
+            ],
+        )
+
+    def test_mode(self):
+        self.dps[MODE_DPS] = "0"
+        self.assertEqual(self.subject.mode, "Normal")
+        self.dps[MODE_DPS] = "1"
+        self.assertEqual(self.subject.mode, "Continuous")
+        self.dps[MODE_DPS] = "2"
+        self.assertEqual(self.subject.mode, "Strong")
+        self.dps[MODE_DPS] = "3"
+        self.assertEqual(self.subject.mode, "Ventilation")
+
+    async def test_set_mode_to_normal(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                MODE_DPS: "0",
+            },
+        ):
+            await self.subject.async_set_mode("Normal")
+            self.subject._device.anticipate_property_value.assert_not_called()
+
+    async def test_set_mode_to_continuous(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                MODE_DPS: "1",
+            },
+        ):
+            await self.subject.async_set_mode("Continuous")
+            self.subject._device.anticipate_property_value.assert_not_called()
+
+    async def test_set_mode_to_strong(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                MODE_DPS: "2",
+            },
+        ):
+            await self.subject.async_set_mode("Strong")
+            self.subject._device.anticipate_property_value.assert_not_called()
+
+    async def test_set_mode_to_ventilation(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                MODE_DPS: "3",
+            },
+        ):
+            await self.subject.async_set_mode("Ventilation")
+            self.subject._device.anticipate_property_value.assert_not_called()
+
+    def test_fan_speed_steps(self):
+        self.assertEqual(self.fan.speed_count, 2)
+
+    def test_fan_speed(self):
+        self.dps[FAN_DPS] = "1"
+        self.assertEqual(self.fan.percentage, 50)
+        self.dps[FAN_DPS] = "3"
+
+    async def test_fan_set_speed_to_low(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                FAN_DPS: "1",
+            },
+        ):
+            await self.fan.async_set_percentage(50)
+
+    async def test_fan_set_speed_to_high(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {
+                FAN_DPS: "3",
+            },
+        ):
+            await self.fan.async_set_percentage(100)
+
+    def test_extra_state_attributes(self):
+        self.dps[UNKNOWN101_DPS] = True
+        self.dps[ERROR_DPS] = 5
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {
+                "error": 5,
+                "unknown_101": True,
+            },
+        )
+        self.assertEqual(self.fan.extra_state_attributes, {})

+ 6 - 7
tests/devices/test_kogan_dehumidifier.py

@@ -1,10 +1,9 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.fan import SUPPORT_OSCILLATE, SUPPORT_SET_SPEED
 from homeassistant.components.humidifier import SUPPORT_MODES
-from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
-    PERCENTAGE,
-)
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import PERCENTAGE
+
 from ..const import KOGAN_DEHUMIDIFIER_PAYLOAD
 from ..helpers import assert_device_properties_set
 from ..mixins.binary_sensor import BasicBinarySensorTests
@@ -35,13 +34,13 @@ class TestKoganDehumidifier(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_tank"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.setUpBasicSensor(
             CURRENTHUMID_DPS,
             self.entities.get("sensor_current_humidity"),
-            device_class=DEVICE_CLASS_HUMIDITY,
+            device_class=SensorDeviceClass.HUMIDITY,
             state_class="measurement",
             unit=PERCENTAGE,
         )

+ 6 - 6
tests/devices/test_kogan_garage_door_opener.py

@@ -1,11 +1,11 @@
 """Tests for the simple garage door opener."""
-from homeassistant.components.binary_sensor import DEVICE_CLASS_GARAGE_DOOR
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.cover import (
-    DEVICE_CLASS_GARAGE,
+    CoverDeviceClass,
     SUPPORT_CLOSE,
     SUPPORT_OPEN,
 )
-from homeassistant.components.sensor import DEVICE_CLASS_BATTERY
+from homeassistant.components.sensor import SensorDeviceClass
 
 from ..const import KOGAN_GARAGE_DOOR_PAYLOAD
 from ..helpers import assert_device_properties_set
@@ -32,17 +32,17 @@ class TestKoganGarageOpener(
         self.setUpBasicBinarySensor(
             LEFTOPEN_DPS,
             self.entities.get("binary_sensor_door_open"),
-            device_class=DEVICE_CLASS_GARAGE_DOOR,
+            device_class=BinarySensorDeviceClass.GARAGE_DOOR,
         )
         self.setUpBasicSensor(
             BATTERY_DPS,
             self.entities.get("sensor_battery"),
-            device_class=DEVICE_CLASS_BATTERY,
+            device_class=SensorDeviceClass.BATTERY,
         )
         self.mark_secondary(["binary_sensor_door_open", "sensor_battery"])
 
     def test_device_class_is_garage(self):
-        self.assertEqual(self.subject.device_class, DEVICE_CLASS_GARAGE)
+        self.assertEqual(self.subject.device_class, CoverDeviceClass.GARAGE)
 
     def test_supported_features(self):
         self.assertEqual(

+ 5 - 5
tests/devices/test_logicom_powerstrip.py

@@ -1,5 +1,5 @@
 """Tests for the Logicom Strippy 4-way+USB powerstrip."""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import TIME_MINUTES
 
 from ..const import LOGICOM_STRIPPY_PAYLOAD
@@ -33,22 +33,22 @@ class TestLogicomPowerstrip(
                 {
                     "dps": SWITCH1_DPS,
                     "name": "switch_outlet_1",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "dps": SWITCH2_DPS,
                     "name": "switch_outlet_2",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "dps": SWITCH3_DPS,
                     "name": "switch_outlet_3",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "dps": SWITCH4_DPS,
                     "name": "switch_outlet_4",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {"dps": SWITCHUSB_DPS, "name": "switch_usb_switch"},
             ]

+ 9 - 11
tests/devices/test_madimack_elitev3_heatpump.py

@@ -6,10 +6,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
-
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_POWER_FACTOR,
-    DEVICE_CLASS_TEMPERATURE,
     PERCENTAGE,
     TEMP_CELSIUS,
     TEMP_FAHRENHEIT,
@@ -67,49 +65,49 @@ class TestMadimackEliteV3Heatpump(
                 {
                     "name": "sensor_power_level",
                     "dps": PWRLEVEL_DPS,
-                    "device_class": DEVICE_CLASS_POWER_FACTOR,
+                    "device_class": SensorDeviceClass.POWER_FACTOR,
                     "unit": PERCENTAGE,
                 },
                 {
                     "name": "sensor_evaporator_coil_pipe_temperature",
                     "dps": COILTEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {
                     "name": "sensor_exhaust_gas_temperature",
                     "dps": EXHAUSTTEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {
                     "name": "sensor_outlet_water_temperature",
                     "dps": OUTLETTEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {
                     "name": "sensor_ambient_temperature",
                     "dps": AMBIENTTEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {
                     "name": "sensor_return_gas_temperature",
                     "dps": RETURNGASTEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {
                     "name": "sensor_cooling_coil_pipe_temperature",
                     "dps": COOLCOILTEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {
                     "name": "sensor_cooling_plate_temperature",
                     "dps": COOLPLATETEMP_DPS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "unit": TEMP_CELSIUS,
                 },
                 {

+ 213 - 213
tests/devices/test_madimack_heatpump.py

@@ -1,213 +1,213 @@
-from homeassistant.components.climate.const import (
-    CURRENT_HVAC_HEAT,
-    CURRENT_HVAC_IDLE,
-    CURRENT_HVAC_OFF,
-    HVAC_MODE_HEAT,
-    HVAC_MODE_OFF,
-    SUPPORT_PRESET_MODE,
-    SUPPORT_TARGET_TEMPERATURE,
-)
-from homeassistant.const import (
-    DEVICE_CLASS_POWER_FACTOR,
-    PERCENTAGE,
-    STATE_UNAVAILABLE,
-    TEMP_CELSIUS,
-    TEMP_FAHRENHEIT,
-)
-
-from ..const import MADIMACK_HEATPUMP_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.climate import TargetTemperatureTests
-from ..mixins.sensor import BasicSensorTests
-from .base_device_tests import TuyaDeviceTestCase
-
-HVACMODE_DPS = "1"
-CURRENTTEMP_DPS = "102"
-UNITS_DPS = "103"
-POWERLEVEL_DPS = "104"
-OPMODE_DPS = "105"
-TEMPERATURE_DPS = "106"
-UNKNOWN107_DPS = "107"
-UNKNOWN108_DPS = "108"
-UNKNOWN115_DPS = "115"
-UNKNOWN116_DPS = "116"
-UNKNOWN118_DPS = "118"
-UNKNOWN120_DPS = "120"
-UNKNOWN122_DPS = "122"
-UNKNOWN124_DPS = "124"
-UNKNOWN125_DPS = "125"
-UNKNOWN126_DPS = "126"
-UNKNOWN127_DPS = "127"
-UNKNOWN128_DPS = "128"
-UNKNOWN129_DPS = "129"
-UNKNOWN130_DPS = "130"
-UNKNOWN134_DPS = "134"
-UNKNOWN135_DPS = "135"
-UNKNOWN136_DPS = "136"
-UNKNOWN139_DPS = "139"
-UNKNOWN140_DPS = "140"
-PRESET_DPS = "117"
-
-
-class TestMadimackPoolHeatpump(
-    BasicSensorTests,
-    TargetTemperatureTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig("madimack_heatpump.yaml", MADIMACK_HEATPUMP_PAYLOAD)
-        self.subject = self.entities.get("climate")
-        self.setUpTargetTemperature(
-            TEMPERATURE_DPS,
-            self.subject,
-            min=18,
-            max=45,
-        )
-        self.setUpBasicSensor(
-            POWERLEVEL_DPS,
-            self.entities.get("sensor_power_level"),
-            device_class=DEVICE_CLASS_POWER_FACTOR,
-            unit=PERCENTAGE,
-        )
-        self.mark_secondary(["sensor_power_level"])
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE,
-        )
-
-    def test_icon(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.icon, "mdi:hot-tub")
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.icon, "mdi:hvac-off")
-
-    def test_temperature_unit(self):
-        self.dps[UNITS_DPS] = False
-        self.assertEqual(self.subject.temperature_unit, TEMP_FAHRENHEIT)
-        self.dps[UNITS_DPS] = True
-        self.assertEqual(self.subject.temperature_unit, TEMP_CELSIUS)
-
-    def test_minimum_fahrenheit_temperature(self):
-        self.dps[UNITS_DPS] = False
-        self.assertEqual(self.subject.min_temp, 60)
-
-    def test_maximum_fahrenheit_temperature(self):
-        self.dps[UNITS_DPS] = False
-        self.assertEqual(self.subject.max_temp, 115)
-
-    def test_current_temperature(self):
-        self.dps[CURRENTTEMP_DPS] = 25
-        self.assertEqual(self.subject.current_temperature, 25)
-
-    def test_hvac_mode(self):
-        self.dps[HVACMODE_DPS] = True
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
-
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
-
-        self.dps[HVACMODE_DPS] = None
-        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
-
-    def test_hvac_modes(self):
-        self.assertCountEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT])
-
-    async def test_turn_on(self):
-        async with assert_device_properties_set(
-            self.subject._device, {HVACMODE_DPS: True}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
-
-    async def test_turn_off(self):
-        async with assert_device_properties_set(
-            self.subject._device, {HVACMODE_DPS: False}
-        ):
-            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
-
-    def test_preset_mode(self):
-        self.dps[PRESET_DPS] = False
-        self.assertEqual(self.subject.preset_mode, "Silent")
-
-        self.dps[PRESET_DPS] = True
-        self.assertEqual(self.subject.preset_mode, "Boost")
-
-        self.dps[PRESET_DPS] = None
-        self.assertIs(self.subject.preset_mode, None)
-
-    def test_preset_modes(self):
-        self.assertCountEqual(self.subject.preset_modes, ["Silent", "Boost"])
-
-    async def test_set_preset_mode_to_silent(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: False},
-        ):
-            await self.subject.async_set_preset_mode("Silent")
-
-    async def test_set_preset_mode_to_boost(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {PRESET_DPS: True},
-        ):
-            await self.subject.async_set_preset_mode("Boost")
-
-    def test_hvac_action(self):
-        self.dps[HVACMODE_DPS] = True
-        self.dps[OPMODE_DPS] = "heating"
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
-        self.dps[OPMODE_DPS] = "warm"
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
-        self.dps[HVACMODE_DPS] = False
-        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
-
-    def test_extra_state_attributes(self):
-        self.dps[POWERLEVEL_DPS] = 50
-        self.dps[UNKNOWN107_DPS] = 1
-        self.dps[UNKNOWN108_DPS] = 2
-        self.dps[UNKNOWN115_DPS] = 3
-        self.dps[UNKNOWN116_DPS] = 4
-        self.dps[UNKNOWN118_DPS] = 5
-        self.dps[UNKNOWN120_DPS] = 6
-        self.dps[UNKNOWN122_DPS] = 7
-        self.dps[UNKNOWN124_DPS] = 8
-        self.dps[UNKNOWN125_DPS] = 9
-        self.dps[UNKNOWN126_DPS] = 10
-        self.dps[UNKNOWN127_DPS] = 11
-        self.dps[UNKNOWN128_DPS] = 12
-        self.dps[UNKNOWN129_DPS] = 13
-        self.dps[UNKNOWN130_DPS] = True
-        self.dps[UNKNOWN134_DPS] = False
-        self.dps[UNKNOWN135_DPS] = True
-        self.dps[UNKNOWN136_DPS] = False
-        self.dps[UNKNOWN139_DPS] = True
-        self.dps[UNKNOWN140_DPS] = "test"
-        self.assertDictEqual(
-            self.subject.extra_state_attributes,
-            {
-                "power_level": 50,
-                "unknown_107": 1,
-                "unknown_108": 2,
-                "unknown_115": 3,
-                "unknown_116": 4,
-                "unknown_118": 5,
-                "unknown_120": 6,
-                "unknown_122": 7,
-                "unknown_124": 8,
-                "unknown_125": 9,
-                "unknown_126": 10,
-                "unknown_127": 11,
-                "unknown_128": 12,
-                "unknown_129": 13,
-                "unknown_130": True,
-                "unknown_134": False,
-                "unknown_135": True,
-                "unknown_136": False,
-                "unknown_139": True,
-                "unknown_140": "test",
-            },
-        )
+from homeassistant.components.climate.const import (
+    CURRENT_HVAC_HEAT,
+    CURRENT_HVAC_IDLE,
+    CURRENT_HVAC_OFF,
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    SUPPORT_PRESET_MODE,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    PERCENTAGE,
+    STATE_UNAVAILABLE,
+    TEMP_CELSIUS,
+    TEMP_FAHRENHEIT,
+)
+
+from ..const import MADIMACK_HEATPUMP_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.sensor import BasicSensorTests
+from .base_device_tests import TuyaDeviceTestCase
+
+HVACMODE_DPS = "1"
+CURRENTTEMP_DPS = "102"
+UNITS_DPS = "103"
+POWERLEVEL_DPS = "104"
+OPMODE_DPS = "105"
+TEMPERATURE_DPS = "106"
+UNKNOWN107_DPS = "107"
+UNKNOWN108_DPS = "108"
+UNKNOWN115_DPS = "115"
+UNKNOWN116_DPS = "116"
+UNKNOWN118_DPS = "118"
+UNKNOWN120_DPS = "120"
+UNKNOWN122_DPS = "122"
+UNKNOWN124_DPS = "124"
+UNKNOWN125_DPS = "125"
+UNKNOWN126_DPS = "126"
+UNKNOWN127_DPS = "127"
+UNKNOWN128_DPS = "128"
+UNKNOWN129_DPS = "129"
+UNKNOWN130_DPS = "130"
+UNKNOWN134_DPS = "134"
+UNKNOWN135_DPS = "135"
+UNKNOWN136_DPS = "136"
+UNKNOWN139_DPS = "139"
+UNKNOWN140_DPS = "140"
+PRESET_DPS = "117"
+
+
+class TestMadimackPoolHeatpump(
+    BasicSensorTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("madimack_heatpump.yaml", MADIMACK_HEATPUMP_PAYLOAD)
+        self.subject = self.entities.get("climate")
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=18,
+            max=45,
+        )
+        self.setUpBasicSensor(
+            POWERLEVEL_DPS,
+            self.entities.get("sensor_power_level"),
+            device_class=SensorDeviceClass.POWER_FACTOR,
+            unit=PERCENTAGE,
+        )
+        self.mark_secondary(["sensor_power_level"])
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE,
+        )
+
+    def test_icon(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.icon, "mdi:hot-tub")
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.icon, "mdi:hvac-off")
+
+    def test_temperature_unit(self):
+        self.dps[UNITS_DPS] = False
+        self.assertEqual(self.subject.temperature_unit, TEMP_FAHRENHEIT)
+        self.dps[UNITS_DPS] = True
+        self.assertEqual(self.subject.temperature_unit, TEMP_CELSIUS)
+
+    def test_minimum_fahrenheit_temperature(self):
+        self.dps[UNITS_DPS] = False
+        self.assertEqual(self.subject.min_temp, 60)
+
+    def test_maximum_fahrenheit_temperature(self):
+        self.dps[UNITS_DPS] = False
+        self.assertEqual(self.subject.max_temp, 115)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 25
+        self.assertEqual(self.subject.current_temperature, 25)
+
+    def test_hvac_mode(self):
+        self.dps[HVACMODE_DPS] = True
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
+
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(self.subject.hvac_modes, [HVAC_MODE_OFF, HVAC_MODE_HEAT])
+
+    async def test_turn_on(self):
+        async with assert_device_properties_set(
+            self.subject._device, {HVACMODE_DPS: True}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_HEAT)
+
+    async def test_turn_off(self):
+        async with assert_device_properties_set(
+            self.subject._device, {HVACMODE_DPS: False}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
+
+    def test_preset_mode(self):
+        self.dps[PRESET_DPS] = False
+        self.assertEqual(self.subject.preset_mode, "Silent")
+
+        self.dps[PRESET_DPS] = True
+        self.assertEqual(self.subject.preset_mode, "Boost")
+
+        self.dps[PRESET_DPS] = None
+        self.assertIs(self.subject.preset_mode, None)
+
+    def test_preset_modes(self):
+        self.assertCountEqual(self.subject.preset_modes, ["Silent", "Boost"])
+
+    async def test_set_preset_mode_to_silent(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: False},
+        ):
+            await self.subject.async_set_preset_mode("Silent")
+
+    async def test_set_preset_mode_to_boost(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: True},
+        ):
+            await self.subject.async_set_preset_mode("Boost")
+
+    def test_hvac_action(self):
+        self.dps[HVACMODE_DPS] = True
+        self.dps[OPMODE_DPS] = "heating"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
+        self.dps[OPMODE_DPS] = "warm"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+        self.dps[HVACMODE_DPS] = False
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
+
+    def test_extra_state_attributes(self):
+        self.dps[POWERLEVEL_DPS] = 50
+        self.dps[UNKNOWN107_DPS] = 1
+        self.dps[UNKNOWN108_DPS] = 2
+        self.dps[UNKNOWN115_DPS] = 3
+        self.dps[UNKNOWN116_DPS] = 4
+        self.dps[UNKNOWN118_DPS] = 5
+        self.dps[UNKNOWN120_DPS] = 6
+        self.dps[UNKNOWN122_DPS] = 7
+        self.dps[UNKNOWN124_DPS] = 8
+        self.dps[UNKNOWN125_DPS] = 9
+        self.dps[UNKNOWN126_DPS] = 10
+        self.dps[UNKNOWN127_DPS] = 11
+        self.dps[UNKNOWN128_DPS] = 12
+        self.dps[UNKNOWN129_DPS] = 13
+        self.dps[UNKNOWN130_DPS] = True
+        self.dps[UNKNOWN134_DPS] = False
+        self.dps[UNKNOWN135_DPS] = True
+        self.dps[UNKNOWN136_DPS] = False
+        self.dps[UNKNOWN139_DPS] = True
+        self.dps[UNKNOWN140_DPS] = "test"
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {
+                "power_level": 50,
+                "unknown_107": 1,
+                "unknown_108": 2,
+                "unknown_115": 3,
+                "unknown_116": 4,
+                "unknown_118": 5,
+                "unknown_120": 6,
+                "unknown_122": 7,
+                "unknown_124": 8,
+                "unknown_125": 9,
+                "unknown_126": 10,
+                "unknown_127": 11,
+                "unknown_128": 12,
+                "unknown_129": 13,
+                "unknown_130": True,
+                "unknown_134": False,
+                "unknown_135": True,
+                "unknown_136": False,
+                "unknown_139": True,
+                "unknown_140": "test",
+            },
+        )

+ 2 - 2
tests/devices/test_minco_mh1823d_thermostat.py

@@ -8,8 +8,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_TEMPERATURE,
     STATE_UNAVAILABLE,
     TEMP_CELSIUS,
     TEMP_FAHRENHEIT,
@@ -78,7 +78,7 @@ class TestMincoMH1823DThermostat(
             EXTERNTEMP_DPS,
             self.entities.get("sensor_external_temperature"),
             unit=TEMP_CELSIUS,
-            device_class=DEVICE_CLASS_TEMPERATURE,
+            device_class=SensorDeviceClass.TEMPERATURE,
             state_class="measurement",
             testdata=(300, 30.0),
         )

+ 6 - 8
tests/devices/test_moes_rgb_socket.py

@@ -5,11 +5,9 @@ from homeassistant.components.light import (
     EFFECT_COLORLOOP,
     SUPPORT_EFFECT,
 )
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_VOLTAGE,
     ELECTRIC_CURRENT_MILLIAMPERE,
     ELECTRIC_POTENTIAL_VOLT,
     POWER_WATT,
@@ -55,7 +53,7 @@ class TestMoesRGBWSocket(
         self.setUpBasicSwitch(
             SWITCH_DPS,
             self.entities.get("switch"),
-            device_class=DEVICE_CLASS_OUTLET,
+            device_class=SwitchDeviceClass.OUTLET,
             power_dps=POWER_DPS,
             power_scale=10,
         )
@@ -72,7 +70,7 @@ class TestMoesRGBWSocket(
                     "name": "sensor_voltage",
                     "dps": VOLTAGE_DPS,
                     "unit": ELECTRIC_POTENTIAL_VOLT,
-                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "device_class": SensorDeviceClass.VOLTAGE,
                     "state_class": "measurement",
                     "testdata": (2300, 230.0),
                 },
@@ -80,14 +78,14 @@ class TestMoesRGBWSocket(
                     "name": "sensor_current",
                     "dps": CURRENT_DPS,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_power",
                     "dps": POWER_DPS,
                     "unit": POWER_WATT,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": SensorDeviceClass.POWER,
                     "state_class": "measurement",
                     "testdata": (1234, 123.4),
                 },

+ 4 - 6
tests/devices/test_parkside_plgs2012a1_smart_charger.py

@@ -7,9 +7,7 @@ from homeassistant.const import (
     TIME_MINUTES,
 )
 from homeassistant.components.sensor import (
-    DEVICE_CLASS_BATTERY,
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_TEMPERATURE,
+    SensorDeviceClass,
     STATE_CLASS_MEASUREMENT,
 )
 from ..const import PARKSIDE_PLGS2012A1_PAYLOAD
@@ -98,7 +96,7 @@ class TestParksidePLGS2012A1Charger(
                     "name": "sensor_battery",
                     "dps": BATTERY_DPS,
                     "unit": PERCENTAGE,
-                    "device_class": DEVICE_CLASS_BATTERY,
+                    "device_class": SensorDeviceClass.BATTERY,
                 },
                 {
                     "name": "sensor_time_remaining",
@@ -109,14 +107,14 @@ class TestParksidePLGS2012A1Charger(
                     "name": "sensor_current_temperature",
                     "dps": TEMPERATURE_DPS,
                     "unit": TEMP_CELSIUS,
-                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "device_class": SensorDeviceClass.TEMPERATURE,
                     "state_class": STATE_CLASS_MEASUREMENT,
                 },
                 {
                     "name": "sensor_max_current",
                     "dps": MAXCURRENT_DPS,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                 },
                 {
                     "name": "sensor_max_temperature_count",

+ 137 - 137
tests/devices/test_poiema_one_purifier.py

@@ -1,137 +1,137 @@
-from homeassistant.components.fan import SUPPORT_PRESET_MODE, SUPPORT_SET_SPEED
-from homeassistant.const import (
-    CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
-    DEVICE_CLASS_PM25,
-    TIME_MINUTES,
-)
-
-from ..const import POIEMA_ONE_PURIFIER_PAYLOAD
-from ..helpers import assert_device_properties_set
-from ..mixins.lock import BasicLockTests
-from ..mixins.select import BasicSelectTests
-from ..mixins.sensor import MultiSensorTests
-from ..mixins.switch import BasicSwitchTests, SwitchableTests
-from .base_device_tests import TuyaDeviceTestCase
-
-SWITCH_DPS = "1"
-PM25_DPS = "2"
-MODE_DPS = "3"
-SPEED_DPS = "4"
-LOCK_DPS = "7"
-RESET_DPS = "11"
-TIMER_DPS = "18"
-COUNTDOWN_DPS = "19"
-
-
-class TestPoeimaOnePurifier(
-    BasicLockTests,
-    BasicSelectTests,
-    BasicSwitchTests,
-    MultiSensorTests,
-    SwitchableTests,
-    TuyaDeviceTestCase,
-):
-    __test__ = True
-
-    def setUp(self):
-        self.setUpForConfig("poiema_one_purifier.yaml", POIEMA_ONE_PURIFIER_PAYLOAD)
-        self.subject = self.entities["fan"]
-        self.setUpSwitchable(SWITCH_DPS, self.subject)
-        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
-        self.setUpBasicSelect(
-            TIMER_DPS,
-            self.entities.get("select_timer"),
-            {
-                "cancel": "off",
-                "1h": "1 hour",
-                "2h": "2 hours",
-                "3h": "3 hours",
-                "4h": "4 hours",
-                "5h": "5 hours",
-            },
-        )
-        self.setUpBasicSwitch(RESET_DPS, self.entities.get("switch_filter_reset"))
-        self.setUpMultiSensors(
-            [
-                {
-                    "dps": PM25_DPS,
-                    "name": "sensor_pm2_5",
-                    "device_class": DEVICE_CLASS_PM25,
-                    "state_class": "measurement",
-                    "unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
-                },
-                {
-                    "dps": COUNTDOWN_DPS,
-                    "name": "sensor_timer",
-                    "unit": TIME_MINUTES,
-                },
-            ]
-        )
-        self.mark_secondary(
-            [
-                "lock_child_lock",
-                "switch_filter_reset",
-                "select_timer",
-                "sensor_timer",
-            ]
-        )
-
-    def test_supported_features(self):
-        self.assertEqual(
-            self.subject.supported_features,
-            SUPPORT_PRESET_MODE | SUPPORT_SET_SPEED,
-        )
-
-    def test_speed(self):
-        self.dps[SPEED_DPS] = "low"
-        self.assertEqual(self.subject.percentage, 25)
-
-    def test_speed_step(self):
-        self.assertEqual(self.subject.percentage_step, 25)
-
-    async def test_set_speed(self):
-        async with assert_device_properties_set(
-            self.subject._device, {SPEED_DPS: "mid"}
-        ):
-            await self.subject.async_set_percentage(50)
-
-    async def test_set_speed_snaps(self):
-        async with assert_device_properties_set(
-            self.subject._device, {SPEED_DPS: "high"}
-        ):
-            await self.subject.async_set_percentage(70)
-
-    def test_preset_modes(self):
-        self.assertCountEqual(
-            self.subject.preset_modes,
-            ["Manual", "Auto", "Sleep"],
-        )
-
-    def test_preset_mode(self):
-        self.dps[MODE_DPS] = "manual"
-        self.assertEqual(self.subject.preset_mode, "Manual")
-        self.dps[MODE_DPS] = "auto"
-        self.assertEqual(self.subject.preset_mode, "Auto")
-        self.dps[MODE_DPS] = "sleep"
-        self.assertEqual(self.subject.preset_mode, "Sleep")
-
-    async def test_set_preset_to_manual(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {MODE_DPS: "manual"},
-        ):
-            await self.subject.async_set_preset_mode("Manual")
-
-    async def test_set_preset_to_auto(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {MODE_DPS: "auto"},
-        ):
-            await self.subject.async_set_preset_mode("Auto")
-
-    async def test_set_preset_to_sleep(self):
-        async with assert_device_properties_set(
-            self.subject._device,
-            {MODE_DPS: "sleep"},
-        ):
-            await self.subject.async_set_preset_mode("Sleep")
+from homeassistant.components.fan import SUPPORT_PRESET_MODE, SUPPORT_SET_SPEED
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import (
+    CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
+    TIME_MINUTES,
+)
+
+from ..const import POIEMA_ONE_PURIFIER_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.lock import BasicLockTests
+from ..mixins.select import BasicSelectTests
+from ..mixins.sensor import MultiSensorTests
+from ..mixins.switch import BasicSwitchTests, SwitchableTests
+from .base_device_tests import TuyaDeviceTestCase
+
+SWITCH_DPS = "1"
+PM25_DPS = "2"
+MODE_DPS = "3"
+SPEED_DPS = "4"
+LOCK_DPS = "7"
+RESET_DPS = "11"
+TIMER_DPS = "18"
+COUNTDOWN_DPS = "19"
+
+
+class TestPoeimaOnePurifier(
+    BasicLockTests,
+    BasicSelectTests,
+    BasicSwitchTests,
+    MultiSensorTests,
+    SwitchableTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("poiema_one_purifier.yaml", POIEMA_ONE_PURIFIER_PAYLOAD)
+        self.subject = self.entities["fan"]
+        self.setUpSwitchable(SWITCH_DPS, self.subject)
+        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
+        self.setUpBasicSelect(
+            TIMER_DPS,
+            self.entities.get("select_timer"),
+            {
+                "cancel": "off",
+                "1h": "1 hour",
+                "2h": "2 hours",
+                "3h": "3 hours",
+                "4h": "4 hours",
+                "5h": "5 hours",
+            },
+        )
+        self.setUpBasicSwitch(RESET_DPS, self.entities.get("switch_filter_reset"))
+        self.setUpMultiSensors(
+            [
+                {
+                    "dps": PM25_DPS,
+                    "name": "sensor_pm2_5",
+                    "device_class": SensorDeviceClass.PM25,
+                    "state_class": "measurement",
+                    "unit": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
+                },
+                {
+                    "dps": COUNTDOWN_DPS,
+                    "name": "sensor_timer",
+                    "unit": TIME_MINUTES,
+                },
+            ]
+        )
+        self.mark_secondary(
+            [
+                "lock_child_lock",
+                "switch_filter_reset",
+                "select_timer",
+                "sensor_timer",
+            ]
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_PRESET_MODE | SUPPORT_SET_SPEED,
+        )
+
+    def test_speed(self):
+        self.dps[SPEED_DPS] = "low"
+        self.assertEqual(self.subject.percentage, 25)
+
+    def test_speed_step(self):
+        self.assertEqual(self.subject.percentage_step, 25)
+
+    async def test_set_speed(self):
+        async with assert_device_properties_set(
+            self.subject._device, {SPEED_DPS: "mid"}
+        ):
+            await self.subject.async_set_percentage(50)
+
+    async def test_set_speed_snaps(self):
+        async with assert_device_properties_set(
+            self.subject._device, {SPEED_DPS: "high"}
+        ):
+            await self.subject.async_set_percentage(70)
+
+    def test_preset_modes(self):
+        self.assertCountEqual(
+            self.subject.preset_modes,
+            ["Manual", "Auto", "Sleep"],
+        )
+
+    def test_preset_mode(self):
+        self.dps[MODE_DPS] = "manual"
+        self.assertEqual(self.subject.preset_mode, "Manual")
+        self.dps[MODE_DPS] = "auto"
+        self.assertEqual(self.subject.preset_mode, "Auto")
+        self.dps[MODE_DPS] = "sleep"
+        self.assertEqual(self.subject.preset_mode, "Sleep")
+
+    async def test_set_preset_to_manual(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {MODE_DPS: "manual"},
+        ):
+            await self.subject.async_set_preset_mode("Manual")
+
+    async def test_set_preset_to_auto(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {MODE_DPS: "auto"},
+        ):
+            await self.subject.async_set_preset_mode("Auto")
+
+    async def test_set_preset_to_sleep(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {MODE_DPS: "sleep"},
+        ):
+            await self.subject.async_set_preset_mode("Sleep")

+ 2 - 2
tests/devices/test_poolex_silverline_heatpump.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -41,7 +41,7 @@ class TestPoolexSilverlineHeatpump(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_water_flow"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(256, 0),
         )
         self.mark_secondary(["binary_sensor_water_flow"])

+ 2 - 2
tests/devices/test_poolex_vertigo_heatpump.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -41,7 +41,7 @@ class TestPoolexVertigoHeatpump(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_water_flow"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(4, 0),
         )
         self.mark_secondary(["binary_sensor_water_flow"])

+ 2 - 2
tests/devices/test_qoto_03_sprinkler.py

@@ -1,5 +1,5 @@
 """Tests for the Quto 03 Sprinkler."""
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.const import PERCENTAGE, TIME_SECONDS
 
 from ..const import QOTO_SPRINKLER_PAYLOAD
@@ -28,7 +28,7 @@ class TestQotoSprinkler(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.setUpMultiNumber(

+ 2 - 2
tests/devices/test_remora_heatpump.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.climate.const import (
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
@@ -37,7 +37,7 @@ class TestRemoraHeatpump(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_water_flow"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.mark_secondary(["binary_sensor_water_flow"])

+ 2 - 2
tests/devices/test_renpho_rp_ap001s.py

@@ -1,5 +1,5 @@
 from homeassistant.components.fan import SUPPORT_PRESET_MODE
-from homeassistant.const import DEVICE_CLASS_AQI
+from homeassistant.components.sensor import SensorDeviceClass
 
 from ..const import RENPHO_PURIFIER_PAYLOAD
 from ..helpers import assert_device_properties_set
@@ -44,7 +44,7 @@ class TestRenphoPurifier(
                 {
                     "name": "sensor_air_quality",
                     "dps": QUALITY_DPS,
-                    "device_class": DEVICE_CLASS_AQI,
+                    "device_class": SensorDeviceClass.AQI,
                 },
                 {
                     "name": "sensor_prefilter_life",

+ 3 - 2
tests/devices/test_saswell_c16_thermostat.py

@@ -9,7 +9,8 @@ from homeassistant.components.climate.const import (
     SUPPORT_PRESET_MODE,
     SUPPORT_TARGET_TEMPERATURE,
 )
-from homeassistant.const import DEVICE_CLASS_TEMPERATURE, POWER_WATT, TEMP_CELSIUS
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.const import POWER_WATT, TEMP_CELSIUS
 
 from ..const import SASWELL_C16_THERMOSTAT_PAYLOAD
 from ..helpers import assert_device_properties_set
@@ -70,7 +71,7 @@ class TestSaswellC16Thermostat(
         self.setUpBasicSensor(
             FLOORTEMP_DPS,
             self.entities.get("sensor_floor_temperature"),
-            device_class=DEVICE_CLASS_TEMPERATURE,
+            device_class=SensorDeviceClass.TEMPERATURE,
             state_class="measurement",
             unit=TEMP_CELSIUS,
             testdata=(218, 21.8),

+ 2 - 2
tests/devices/test_sd123_hpr01_presence.py

@@ -1,5 +1,5 @@
 """Tests for SD123 Human Presence Radar HPR01"""
-from homeassistant.components.binary_sensor import DEVICE_CLASS_OCCUPANCY
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 
 from ..const import SD123_PRESENCE_PAYLOAD
 from ..mixins.binary_sensor import BasicBinarySensorTests
@@ -41,7 +41,7 @@ class TestSD123HumanPresenceRadar(
         self.setUpBasicBinarySensor(
             PRESENCE_DPS,
             self.entities.get("binary_sensor"),
-            device_class=DEVICE_CLASS_OCCUPANCY,
+            device_class=BinarySensorDeviceClass.OCCUPANCY,
             testdata=("presence", "none"),
         )
         self.setUpBasicLight(

+ 2 - 2
tests/devices/test_simple_blinds.py

@@ -1,6 +1,6 @@
 """Tests for the simple blinds controller."""
 from homeassistant.components.cover import (
-    DEVICE_CLASS_BLIND,
+    CoverDeviceClass,
     SUPPORT_CLOSE,
     SUPPORT_OPEN,
     SUPPORT_SET_POSITION,
@@ -25,7 +25,7 @@ class TestSimpleBlinds(TuyaDeviceTestCase):
         self.subject = self.entities["cover"]
 
     def test_device_class_is_blind(self):
-        self.assertEqual(self.subject.device_class, DEVICE_CLASS_BLIND)
+        self.assertEqual(self.subject.device_class, CoverDeviceClass.BLIND)
 
     def test_supported_features(self):
         self.assertEqual(

+ 2 - 2
tests/devices/test_simple_switch_with_timer.py

@@ -1,5 +1,5 @@
 """Tests for a simple switch with timer"""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import TIME_MINUTES
 
 from ..const import TIMED_SOCKET_PAYLOAD
@@ -28,7 +28,7 @@ class TestTimedSwitch(BasicNumberTests, SwitchableTests, TuyaDeviceTestCase):
         self.mark_secondary(["number_timer"])
 
     def test_device_class_is_outlet(self):
-        self.assertEqual(self.subject.device_class, DEVICE_CLASS_OUTLET)
+        self.assertEqual(self.subject.device_class, SwitchDeviceClass.OUTLET)
 
     def test_extra_state_attributes_set(self):
         self.assertDictEqual(

+ 21 - 29
tests/devices/test_smartmcb_smt006_energymeter.py

@@ -1,19 +1,11 @@
 """Tests for the SmartMCB SMT006 Energy Meter"""
-from homeassistant.components.binary_sensor import (
-    DEVICE_CLASS_BATTERY,
-    DEVICE_CLASS_HEAT,
-    DEVICE_CLASS_PLUG,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_PROBLEM,
-    DEVICE_CLASS_SAFETY,
-    DEVICE_CLASS_SMOKE,
-)
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.sensor import (
+    SensorDeviceClass,
     STATE_CLASS_TOTAL,
     STATE_CLASS_TOTAL_INCREASING,
 )
 from homeassistant.const import (
-    DEVICE_CLASS_ENERGY,
     ENERGY_KILO_WATT_HOUR,
 )
 
@@ -73,7 +65,7 @@ class TestSmartMcbSMT006EnergyMeter(
                 {
                     "name": "sensor_energy",
                     "dps": TOTALENERGY_DPS,
-                    "device_class": DEVICE_CLASS_ENERGY,
+                    "device_class": SensorDeviceClass.ENERGY,
                     "unit": ENERGY_KILO_WATT_HOUR,
                     "state_class": STATE_CLASS_TOTAL_INCREASING,
                     "testdata": (123456, 1234.56),
@@ -81,7 +73,7 @@ class TestSmartMcbSMT006EnergyMeter(
                 {
                     "name": "sensor_balance_energy",
                     "dps": BALANCE_DPS,
-                    "device_class": DEVICE_CLASS_ENERGY,
+                    "device_class": SensorDeviceClass.ENERGY,
                     "unit": ENERGY_KILO_WATT_HOUR,
                     "state_class": STATE_CLASS_TOTAL,
                     "testdata": (123456, 1234.56),
@@ -93,103 +85,103 @@ class TestSmartMcbSMT006EnergyMeter(
                 {
                     "name": "binary_sensor_short_circuit",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (1, 0),
                 },
                 {
                     "name": "binary_sensor_surge",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (2, 0),
                 },
                 {
                     "name": "binary_sensor_overload",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (4, 0),
                 },
                 {
                     "name": "binary_sensor_leakage_current",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_SAFETY,
+                    "device_class": BinarySensorDeviceClass.SAFETY,
                     "testdata": (8, 0),
                 },
                 {
                     "name": "binary_sensor_high_temperature",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_HEAT,
+                    "device_class": BinarySensorDeviceClass.HEAT,
                     "testdata": (16, 0),
                 },
                 {
                     "name": "binary_sensor_fire",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_SMOKE,
+                    "device_class": BinarySensorDeviceClass.SMOKE,
                     "testdata": (32, 0),
                 },
                 {
                     "name": "binary_sensor_high_power",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": BinarySensorDeviceClass.POWER,
                     "testdata": (64, 0),
                 },
                 {
                     "name": "binary_sensor_self_test",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (128, 0),
                 },
                 {
                     "name": "binary_sensor_overcurrent",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (256, 0),
                 },
                 {
                     "name": "binary_sensor_unbalanced",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (512, 0),
                 },
                 {
                     "name": "binary_sensor_overvoltage",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (1024, 0),
                 },
                 {
                     "name": "binary_sensor_undervoltage",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (2048, 0),
                 },
                 {
                     "name": "binary_sensor_phase_fault",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (4096, 0),
                 },
                 {
                     "name": "binary_sensor_outage",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": BinarySensorDeviceClass.POWER,
                     "testdata": (0, 8192),
                 },
                 {
                     "name": "binary_sensor_magnetism",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PROBLEM,
+                    "device_class": BinarySensorDeviceClass.PROBLEM,
                     "testdata": (16384, 0),
                 },
                 {
                     "name": "binary_sensor_low_credit",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_BATTERY,
+                    "device_class": BinarySensorDeviceClass.BATTERY,
                     "testdata": (32768, 0),
                 },
                 {
                     "name": "binary_sensor_credit",
                     "dps": ERROR_DPS,
-                    "device_class": DEVICE_CLASS_PLUG,
+                    "device_class": BinarySensorDeviceClass.PLUG,
                     "testdata": (0, 65536),
                     "unit": ENERGY_KILO_WATT_HOUR,
                 },

+ 6 - 8
tests/devices/test_smartplugv1.py

@@ -1,9 +1,7 @@
 """Tests for the switch entity."""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.switch import SwitchDeviceClass
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_VOLTAGE,
     ELECTRIC_CURRENT_MILLIAMPERE,
     ELECTRIC_POTENTIAL_VOLT,
     POWER_WATT,
@@ -45,7 +43,7 @@ class TestKoganSwitch(
                     "name": "sensor_voltage",
                     "dps": VOLTAGE_DPS,
                     "unit": ELECTRIC_POTENTIAL_VOLT,
-                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "device_class": SensorDeviceClass.VOLTAGE,
                     "state_class": "measurement",
                     "testdata": (2300, 230.0),
                 },
@@ -53,14 +51,14 @@ class TestKoganSwitch(
                     "name": "sensor_current",
                     "dps": CURRENT_DPS,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_power",
                     "dps": POWER_DPS,
                     "unit": POWER_WATT,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": SensorDeviceClass.POWER,
                     "state_class": "measurement",
                     "testdata": (1234, 123.4),
                 },
@@ -76,7 +74,7 @@ class TestKoganSwitch(
         )
 
     def test_device_class_is_outlet(self):
-        self.assertEqual(self.subject.device_class, DEVICE_CLASS_OUTLET)
+        self.assertEqual(self.subject.device_class, SwitchDeviceClass.OUTLET)
 
     def test_current_power_w(self):
         self.dps[POWER_DPS] = 1234

+ 6 - 8
tests/devices/test_smartplugv2.py

@@ -1,9 +1,7 @@
 """Tests for the switch entity."""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_VOLTAGE,
     ELECTRIC_CURRENT_MILLIAMPERE,
     ELECTRIC_POTENTIAL_VOLT,
     POWER_WATT,
@@ -45,7 +43,7 @@ class TestSwitchV2(
                     "name": "sensor_voltage",
                     "dps": VOLTAGE_DPS,
                     "unit": ELECTRIC_POTENTIAL_VOLT,
-                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "device_class": SensorDeviceClass.VOLTAGE,
                     "state_class": "measurement",
                     "testdata": (2300, 230.0),
                 },
@@ -53,14 +51,14 @@ class TestSwitchV2(
                     "name": "sensor_current",
                     "dps": CURRENT_DPS,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_power",
                     "dps": POWER_DPS,
                     "unit": POWER_WATT,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": SensorDeviceClass.POWER,
                     "state_class": "measurement",
                     "testdata": (1234, 123.4),
                 },
@@ -76,7 +74,7 @@ class TestSwitchV2(
         )
 
     def test_device_class_is_outlet(self):
-        self.assertEqual(self.subject.device_class, DEVICE_CLASS_OUTLET)
+        self.assertEqual(self.subject.device_class, SwitchDeviceClass.OUTLET)
 
     def test_current_power_w(self):
         self.dps[POWER_DPS] = 1234

+ 9 - 12
tests/devices/test_smartplugv2_energy.py

@@ -1,11 +1,8 @@
 """Tests for the switch entity."""
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
+from homeassistant.components.sensor import SensorDeviceClass
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_CURRENT,
-    DEVICE_CLASS_ENERGY,
-    DEVICE_CLASS_POWER,
-    DEVICE_CLASS_VOLTAGE,
     ELECTRIC_CURRENT_MILLIAMPERE,
     ELECTRIC_POTENTIAL_VOLT,
     ENERGY_WATT_HOUR,
@@ -56,7 +53,7 @@ class TestSwitchV2Energy(
                 {
                     "name": "switch",
                     "dps": SWITCH_DPS,
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "name": "switch_overcharge_cutoff",
@@ -67,7 +64,7 @@ class TestSwitchV2Energy(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.setUpBasicNumber(
@@ -92,14 +89,14 @@ class TestSwitchV2Energy(
                     "name": "sensor_energy",
                     "dps": ENERGY_DPS,
                     "unit": ENERGY_WATT_HOUR,
-                    "device_class": DEVICE_CLASS_ENERGY,
+                    "device_class": SensorDeviceClass.ENERGY,
                     "state_class": "total_increasing",
                 },
                 {
                     "name": "sensor_voltage",
                     "dps": VOLTAGE_DPS,
                     "unit": ELECTRIC_POTENTIAL_VOLT,
-                    "device_class": DEVICE_CLASS_VOLTAGE,
+                    "device_class": SensorDeviceClass.VOLTAGE,
                     "state_class": "measurement",
                     "testdata": (2300, 230.0),
                 },
@@ -107,14 +104,14 @@ class TestSwitchV2Energy(
                     "name": "sensor_current",
                     "dps": CURRENT_DPS,
                     "unit": ELECTRIC_CURRENT_MILLIAMPERE,
-                    "device_class": DEVICE_CLASS_CURRENT,
+                    "device_class": SensorDeviceClass.CURRENT,
                     "state_class": "measurement",
                 },
                 {
                     "name": "sensor_power",
                     "dps": POWER_DPS,
                     "unit": POWER_WATT,
-                    "device_class": DEVICE_CLASS_POWER,
+                    "device_class": SensorDeviceClass.POWER,
                     "state_class": "measurement",
                     "testdata": (1234, 123.4),
                 },

+ 2 - 2
tests/devices/test_vork_vk6067aw_purifier.py

@@ -1,4 +1,4 @@
-from homeassistant.components.binary_sensor import DEVICE_CLASS_PROBLEM
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 from homeassistant.components.fan import SUPPORT_PRESET_MODE
 from homeassistant.const import (
     PERCENTAGE,
@@ -43,7 +43,7 @@ class TestVorkVK6267AWPurifier(
         self.setUpBasicBinarySensor(
             ERROR_DPS,
             self.entities.get("binary_sensor_error"),
-            device_class=DEVICE_CLASS_PROBLEM,
+            device_class=BinarySensorDeviceClass.PROBLEM,
             testdata=(1, 0),
         )
         self.setUpBasicLight(LIGHT_DPS, self.entities.get("light"))

+ 2 - 2
tests/devices/test_wetair_wawh1210lw_humidifier.py

@@ -5,8 +5,8 @@ from homeassistant.components.humidifier.const import (
     MODE_SLEEP,
     SUPPORT_MODES,
 )
+from homeassistant.components.sensor import SensorDeviceClass
 from homeassistant.const import (
-    DEVICE_CLASS_HUMIDITY,
     PERCENTAGE,
     STATE_UNAVAILABLE,
 )
@@ -54,7 +54,7 @@ class TestWetairWAWH1210LWHumidifier(
                 {
                     "dps": CURRENTHUMID_DPS,
                     "name": "sensor_current_humidity",
-                    "device_class": DEVICE_CLASS_HUMIDITY,
+                    "device_class": SensorDeviceClass.HUMIDITY,
                     "state_class": "measurement",
                     "unit": PERCENTAGE,
                 },

+ 4 - 4
tests/devices/test_woox_r4028_powerstrip.py

@@ -1,5 +1,5 @@
 """Tests for the Woox R4028 powerstrip."""
-from homeassistant.components.switch import DEVICE_CLASS_OUTLET
+from homeassistant.components.switch import SwitchDeviceClass
 from homeassistant.const import TIME_MINUTES
 
 from ..const import WOOX_R4028_SOCKET_PAYLOAD
@@ -31,17 +31,17 @@ class TestWooxR4028Powerstrip(
                 {
                     "dps": SWITCH1_DPS,
                     "name": "switch_outlet_1",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "dps": SWITCH2_DPS,
                     "name": "switch_outlet_2",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {
                     "dps": SWITCH3_DPS,
                     "name": "switch_outlet_3",
-                    "device_class": DEVICE_CLASS_OUTLET,
+                    "device_class": SwitchDeviceClass.OUTLET,
                 },
                 {"dps": SWITCHUSB_DPS, "name": "switch_usb_switch"},
             ]

+ 13 - 2
tests/mixins/binary_sensor.py

@@ -1,4 +1,5 @@
 # Mixins for testing sensor entities
+from homeassistant.components.binary_sensor import BinarySensorDeviceClass
 
 
 class BasicBinarySensorTests:
@@ -11,7 +12,11 @@ class BasicBinarySensorTests:
     ):
         self.basicBSensor = subject
         self.basicBSensorDps = dps
-        self.basicBSensorDeviceClass = device_class
+        try:
+            self.basicBSensorDeviceClass = BinarySensorDeviceClass(device_class)
+        except ValueError:
+            self.basicBSensorDeviceClass = None
+
         self.basicBSensorTestData = testdata
 
     def test_basic_bsensor_device_class(self):
@@ -41,7 +46,13 @@ class MultiBinarySensorTests:
                 raise AttributeError(f"No binary sensor for {name} found.")
             self.multiBSensor[name] = subject
             self.multiBSensorDps[name] = s.get("dps")
-            self.multiBSensorDevClass[name] = s.get("device_class")
+            try:
+                self.multiBSensorDevClass[name] = BinarySensorDeviceClass(
+                    s.get("device_class")
+                )
+            except ValueError:
+                self.multiBSensorDevClass[name] = None
+
             self.multiBSensorTestData[name] = s.get("testdata", (True, False))
 
     def test_multi_bsensor_device_class(self):

+ 13 - 2
tests/mixins/sensor.py

@@ -1,4 +1,5 @@
 # Mixins for testing sensor entities
+from homeassistant.components.sensor import SensorDeviceClass
 
 
 class BasicSensorTests:
@@ -15,7 +16,11 @@ class BasicSensorTests:
         self.basicSensorDps = dps
         self.basicSensorUnit = unit
         self.basicSensorStateClass = state_class
-        self.basicSensorDeviceClass = device_class
+        try:
+            self.basicSensorDeviceClass = SensorDeviceClass(device_class)
+        except ValueError:
+            self.basicSensorDeviceClass = None
+
         self.basicSensorTestData = testdata
 
     def test_basic_sensor_units(self):
@@ -52,7 +57,13 @@ class MultiSensorTests:
             self.multiSensorDps[name] = s.get("dps")
             self.multiSensorUnit[name] = s.get("unit")
             self.multiSensorStateClass[name] = s.get("state_class")
-            self.multiSensorDevClass[name] = s.get("device_class")
+            try:
+                self.multiSensorDevClass[name] = SensorDeviceClass(
+                    s.get("device_class")
+                )
+            except ValueError:
+                self.multiSensorDevClass[name] = None
+
             self.multiSensorTestData[name] = s.get("testdata", (30, 30))
 
     def test_multi_sensor_units(self):

+ 14 - 4
tests/mixins/switch.py

@@ -1,5 +1,5 @@
 # Mixins for testing switches
-from homeassistant.components.switch import DEVICE_CLASS_SWITCH
+from homeassistant.components.switch import SwitchDeviceClass
 
 from ..helpers import assert_device_properties_set
 
@@ -50,14 +50,18 @@ class BasicSwitchTests:
         self,
         dps,
         subject,
-        device_class=DEVICE_CLASS_SWITCH,
+        device_class="switch",
         power_dps=None,
         power_scale=1,
         testdata=(True, False),
     ):
         self.basicSwitch = subject
         self.basicSwitchDps = dps
-        self.basicSwitchDevClass = device_class
+        try:
+            self.basicSwitchDevClass = SwitchDeviceClass(device_class)
+        except ValueError:
+            self.basicSwitchDevClass = None
+
         self.basicSwitchPowerDps = power_dps
         self.basicSwitchPowerScale = power_scale
         self.basicSwitchOn = testdata[0]
@@ -135,7 +139,13 @@ class MultiSwitchTests:
                 raise AttributeError(f"No switch for {name} found.")
             self.multiSwitch[name] = subject
             self.multiSwitchDps[name] = s.get("dps")
-            self.multiSwitchDevClass[name] = s.get("device_class", DEVICE_CLASS_SWITCH)
+            try:
+                self.multiSwitchDevClass[name] = SwitchDeviceClass(
+                    s.get("device_class", "switch")
+                )
+            except ValueError:
+                self.multiSwitchDevClass[name] = None
+
             self.multiSwitchPowerDps[name] = s.get("power_dps")
             self.multiSwitchPowerScale[name] = s.get("power_scale", 1)