Explorar o código

Add tests for Jiahong Thermostat and correct issues found.

PR #181
Jason Rumney %!s(int64=3) %!d(string=hai) anos
pai
achega
d665a822a6

+ 10 - 7
custom_components/tuya_local/devices/jiahong_et72w_thermostat.yaml

@@ -76,7 +76,6 @@ primary_entity:
     - id: 107
       name: temperature_unit
       type: boolean
-      hidden: true
       mapping:
         - dps_val: false
           value: C
@@ -151,11 +150,10 @@ secondary_entities:
       - id: 107
         name: unit
         type: boolean
-        hidden: true
         mapping:
           - dps_val: false
             value: C
-            dps_val: true
+          - dps_val: true
             value: F
   - entity: sensor
     name: Floor Temperature
@@ -172,11 +170,10 @@ secondary_entities:
       - id: 107
         name: unit
         type: boolean
-        hidden: true
         mapping:
           - dps_val: false
             value: C
-            dps_val: true
+          - dps_val: true
             value: F
   - entity: sensor
     name: Energy
@@ -222,14 +219,20 @@ secondary_entities:
         mapping:
           - scale: 10
             step: 5
+            constraint: unit
+            conditions:
+              - dps_val: true
+                step: 30
+                range:
+                  min: 120
+                  max: 750
       - id: 107
         name: unit
         type: boolean
-        hidden: true
         mapping:
           - dps_val: false
             value: C
-            dps_val: true
+          - dps_val: true
             value: F
   - entity: select
     category: config

+ 29 - 0
tests/const.py

@@ -1230,3 +1230,32 @@ M027_CURTAIN_PAYLOAD = {
     "9": 0,
     "10": 20000,
 }
+
+JIAHONG_ET72W_PAYLOAD = {
+    "101": True,
+    "102": 220,
+    "103": "Manual",
+    "104": 0,
+    "105": 205,
+    "106": 240,
+    "107": False,
+    "108": False,
+    "109": False,
+    "110": 2,
+    "111": "0",
+    "112": 0,
+    "113": 0,
+    "116": 500,
+    "117": 1234,
+    "118": True,
+    "121": 300,
+}
+
+BETTERLIFE_BL1500_PAYLOAD = {
+    "1": True,
+    "2": 20,
+    "4": "comfort",
+    "7": False,
+    "11": "0",
+    "12": 0,
+}

+ 246 - 0
tests/devices/test_jiahong_et72w_thermostat.py

@@ -0,0 +1,246 @@
+from homeassistant.components.climate.const import (
+    HVAC_MODE_AUTO,
+    HVAC_MODE_COOL,
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.components.sensor import (
+    STATE_CLASS_MEASUREMENT,
+    STATE_CLASS_TOTAL_INCREASING,
+)
+from homeassistant.const import (
+    DEVICE_CLASS_ENERGY,
+    DEVICE_CLASS_TEMPERATURE,
+    ENERGY_KILO_WATT_HOUR,
+    STATE_UNAVAILABLE,
+    TEMP_CELSIUS,
+    TEMP_FAHRENHEIT,
+)
+from ..const import JIAHONG_ET72W_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.lock import BasicLockTests
+from ..mixins.number import BasicNumberTests
+from ..mixins.select import MultiSelectTests
+from ..mixins.sensor import MultiSensorTests
+from .base_device_tests import TuyaDeviceTestCase
+
+POWER_DPS = "101"
+TEMPERATURE_DPS = "102"
+HVACMODE_DPS = "103"
+UNKNOWN104_DPS = "104"
+CURRENTTEMP_DPS = "105"
+FLOORTEMP_DPS = "106"
+UNIT_DPS = "107"
+LOCK_DPS = "108"
+UNKNOWN109_DPS = "109"
+SCHED_DPS = "110"
+SENSOR_DPS = "111"
+UNKNOWN112_DPS = "112"
+UNKNOWN113_DPS = "113"
+CALIB_DPS = "116"
+ENERGY_DPS = "117"
+HVACACTION_DPS = "118"
+TEMPLIMIT_DPS = "121"
+
+
+class TestJiahongEt72wThermostat(
+    BasicLockTests,
+    BasicNumberTests,
+    MultiSelectTests,
+    MultiSensorTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig(
+            "jiahong_et72w_thermostat.yaml",
+            JIAHONG_ET72W_PAYLOAD,
+        )
+        self.subject = self.entities.get("climate")
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=5.0,
+            max=40.0,
+            scale=10,
+            step=5,
+        )
+        self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_screen_lock"))
+        self.setUpMultiSelect(
+            [
+                {
+                    "dps": SCHED_DPS,
+                    "name": "select_auto_schedule",
+                    "options": {
+                        0: "7",
+                        1: "5+1+1",
+                        2: "7 (Adaptive)",
+                        3: "5+1+1 (Adaptive)",
+                    },
+                },
+                {
+                    "dps": UNIT_DPS,
+                    "name": "select_temperature_unit",
+                    "options": {
+                        False: "Celsius",
+                        True: "Fahrenheit",
+                    },
+                },
+                {
+                    "dps": SENSOR_DPS,
+                    "name": "select_temperature_sensor",
+                    "options": {
+                        "0": "Room",
+                        "1": "Floor",
+                        "2": "Both",
+                    },
+                },
+            ],
+        )
+        self.setUpBasicNumber(
+            TEMPLIMIT_DPS,
+            self.entities.get("number_room_temperature_limit"),
+            min=10.0,
+            max=40.0,
+            step=0.5,
+            scale=10,
+            unit=TEMP_CELSIUS,
+        )
+        self.setUpMultiSensors(
+            [
+                {
+                    "dps": CURRENTTEMP_DPS,
+                    "name": "sensor_room_temperature",
+                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "state_class": STATE_CLASS_MEASUREMENT,
+                    "unit": TEMP_CELSIUS,
+                    "testdata": (195, 19.5),
+                },
+                {
+                    "dps": FLOORTEMP_DPS,
+                    "name": "sensor_floor_temperature",
+                    "device_class": DEVICE_CLASS_TEMPERATURE,
+                    "state_class": STATE_CLASS_MEASUREMENT,
+                    "unit": TEMP_CELSIUS,
+                    "testdata": (214, 21.4),
+                },
+                {
+                    "dps": ENERGY_DPS,
+                    "name": "sensor_energy",
+                    "device_class": DEVICE_CLASS_ENERGY,
+                    "state_class": STATE_CLASS_TOTAL_INCREASING,
+                    "unit": ENERGY_KILO_WATT_HOUR,
+                    "testdata": (1234, 123.4),
+                },
+            ]
+        )
+        self.mark_secondary(
+            [
+                "lock_screen_lock",
+                "number_room_temperature_limit",
+                "select_auto_schedule",
+                "select_temperature_sensor",
+                "select_temperature_unit",
+            ],
+        )
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_TARGET_TEMPERATURE,
+        )
+
+    def test_temperature_unit(self):
+        self.dps[UNIT_DPS] = False
+        self.assertEqual(
+            self.subject.temperature_unit,
+            TEMP_CELSIUS,
+        )
+        self.assertEqual(self.subject.target_temperature_step, 0.5)
+
+        self.dps[UNIT_DPS] = True
+        self.assertEqual(
+            self.subject.temperature_unit,
+            TEMP_FAHRENHEIT,
+        )
+        self.assertEqual(self.subject.target_temperature_step, 3.0)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 385
+        self.assertEqual(self.subject.current_temperature, 38.5)
+
+    def test_hvac_mode(self):
+        self.dps[POWER_DPS] = False
+        self.dps[HVACMODE_DPS] = "Smart"
+        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] = "Anti_frozen"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_COOL)
+
+        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_AUTO,
+                HVAC_MODE_COOL,
+                HVAC_MODE_HEAT,
+                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 40.0",
+        ):
+            await self.subject.async_set_target_temperature(4.5)
+        with self.assertRaisesRegex(
+            ValueError,
+            f"temperature \\(41\\) must be between 5.0 and 40.0",
+        ):
+            await self.subject.async_set_target_temperature(41)
+
+    def test_extra_state_attributes(self):
+        self.dps[UNKNOWN104_DPS] = 104
+        self.dps[UNKNOWN109_DPS] = True
+        self.dps[UNKNOWN112_DPS] = 112
+        self.dps[UNKNOWN113_DPS] = 113
+        self.assertDictEqual(
+            self.subject.extra_state_attributes,
+            {
+                "unknown_104": 104,
+                "unknown_109": True,
+                "unknown_112": 112,
+                "unknown_113": 113,
+            },
+        )
+
+    def test_multi_sensor_extra_state_attributes(self):
+        self.dps[CALIB_DPS] = 321
+        self.assertEqual(
+            self.multiSensor["sensor_energy"].extra_state_attributes,
+            {"energy_calibration": 321},
+        )
+
+    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")