Przeglądaj źródła

Implement tests for hellnar_heatpump.yaml.

Fixed some issues that came out
- range conditions were at wrong level, so default 7-35 was being used
  instead of 17-30 or 0-30 depending on mode as per info from Tuya web.
- ranges were not scaled
- some dps were missing (acceptable, but warnings will result).

Based on futher info from jorgenDK, some names changed.
Jason Rumney 4 lat temu
rodzic
commit
8d53881dff

+ 3 - 1
README.md

@@ -239,6 +239,8 @@ Further device support has been made with the assistance of users.  Please consi
  - [Lapy](https://github.com/Lapy) for contributing support for Electriq dehumidifiers.
  - [thomas-fr](https://github.com/thomas-fr) for contributing support for Poolex Silverline heatpumps.
  - [lperez31](https://github.com/lperez31) for contributing support for Poolex Vertigo heatpumps.
- - [b3nnyk22](https://github.com/b3nnyk22) for assistance in supporting Kogan Dehumidifiers. 
+ - [b3nnyk22](https://github.com/b3nnyk22) for assistance in supporting Kogan Dehumidifiers.
+ - [rodrigoGA](https://github.com/rodrigoGA) for assistance in supporting Greenwind dehumidifiers.
+ - [jorgenDK](https://github.com/jorgenDK) for assistance in supporting TroniTechnik Air Conditioner, and thanks for the coffee!
  
 [![BuyMeCoffee](https://www.buymeacoffee.com/assets/img/custom_images/orange_img.png)](https://www.buymeacoffee.com/jasonrumney)

+ 30 - 21
custom_components/tuya_local/devices/hellnar_heatpump.yaml

@@ -16,24 +16,24 @@ primary_entity:
       type: integer
       mapping:
         - scale: 10
-      constraint: hvac_mode
-      conditions:
-        - dps_val: cold
-          range:
-            min: 17
-            max: 30
-        - dps_val: auto
-          range:
-            min: 17
-            max: 30
-        - dps_val: hot
-          range:
-            min: 0
-            max: 30
-        - dps_val: wet
-          invalid: true
-        - dps_val: wind
-          invalid: true
+          constraint: hvac_mode
+          conditions:
+            - dps_val: cold
+              range:
+                min: 170
+                max: 300
+            - dps_val: auto
+              range:
+                min: 170
+                max: 300
+            - dps_val: hot
+              range:
+                min: 0
+                max: 300
+            - dps_val: wet
+              invalid: true
+            - dps_val: wind
+              invalid: true
     - id: 3
       name: current_temperature
       type: integer
@@ -97,7 +97,7 @@ primary_entity:
       name: unknown_20
       type: integer
     - id: 105
-      name: maybe_swing_h_or_v
+      name: unknown_105
       type: string
     - id: 110
       name: unknown_110
@@ -112,14 +112,23 @@ primary_entity:
       name: unknown_119
       type: string
     - id: 120
-      name: maybe_swing_v_or_h
+      name: unknown_120
       type: string
     - id: 123
-      name: unknown_123
+      name: swing_mode
       type: string
     - id: 126
       name: unknown_126
       type: string
+    - id: 127
+      name: unknown_127
+      type: string
+    - id: 128
+      name: unknown_128
+      type: string
+    - id: 129
+      name: unknown_129
+      type: string
     - id: 130
       name: maybe_eco_temp
       type: integer

+ 26 - 0
tests/const.py

@@ -235,3 +235,29 @@ KOGAN_DEHUMIDIFIER_PAYLOAD = {
     "13": 0,
     "101": 50,
 }
+
+HELLNAR_HEATPUMP_PAYLOAD = {
+    "1": False,
+    "2": 260,
+    "3": 26,
+    "4": "wet",
+    "5": "low",
+    "18": 0,
+    "20": 0,
+    "105": "off",
+    "110": 131644,
+    "113": "0",
+    "114": "0",
+    "119": "0",
+    "120": "off",
+    "123": "0010",
+    "126": "0",
+    "127": "0",
+    "128": "0",
+    "129": "1",
+    "130": 26,
+    "131": False,
+    "132": False,
+    "133": "0",
+    "134": '{"t":1624086077,"s":false,"clr"true}',
+}

+ 204 - 0
tests/devices/test_hellnar_heatpump.py

@@ -0,0 +1,204 @@
+from homeassistant.components.climate.const import (
+    HVAC_MODE_AUTO,
+    HVAC_MODE_COOL,
+    HVAC_MODE_DRY,
+    HVAC_MODE_FAN_ONLY,
+    HVAC_MODE_HEAT,
+    HVAC_MODE_OFF,
+    SUPPORT_SWING_MODE,
+    SUPPORT_TARGET_TEMPERATURE,
+)
+from homeassistant.const import STATE_UNAVAILABLE
+
+from ..const import HELLNAR_HEATPUMP_PAYLOAD
+from ..helpers import assert_device_properties_set
+from .base_device_tests import TuyaDeviceTestCase
+
+POWER_DPS = "1"
+TEMPERATURE_DPS = "2"
+CURRENTTEMP_DPS = "3"
+HVACMODE_DPS = "4"
+
+
+class TestHellnarHeatpump(TuyaDeviceTestCase):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig("hellnar_heatpump.yaml", HELLNAR_HEATPUMP_PAYLOAD)
+        self.subject = self.entities.get("climate")
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            SUPPORT_SWING_MODE | SUPPORT_TARGET_TEMPERATURE,
+        )
+
+    def test_icon(self):
+        self.dps[POWER_DPS] = True
+        self.dps[HVACMODE_DPS] = "auto"
+        self.assertEqual(self.subject.icon, "mdi:hvac")
+        self.dps[HVACMODE_DPS] = "cold"
+        self.assertEqual(self.subject.icon, "mdi:snowflake")
+        self.dps[HVACMODE_DPS] = "hot"
+        self.assertEqual(self.subject.icon, "mdi:fire")
+        self.dps[HVACMODE_DPS] = "wet"
+        self.assertEqual(self.subject.icon, "mdi:water")
+        self.dps[HVACMODE_DPS] = "wind"
+        self.assertEqual(self.subject.icon, "mdi:fan")
+        self.dps[POWER_DPS] = False
+        self.assertEqual(self.subject.icon, "mdi:hvac-off")
+
+    def test_temperature_unit_returns_device_temperature_unit(self):
+        self.assertEqual(
+            self.subject.temperature_unit, self.subject._device.temperature_unit
+        )
+
+    def test_target_temperature(self):
+        self.dps[HVACMODE_DPS] = "auto"
+        self.dps[TEMPERATURE_DPS] = 250
+        self.assertEqual(self.subject.target_temperature, 25)
+
+    def test_target_temperature_step(self):
+        self.assertEqual(self.subject.target_temperature_step, 0.1)
+
+    def test_minimum_target_temperature(self):
+        self.dps[HVACMODE_DPS] = "cold"
+        self.assertEqual(self.subject.min_temp, 170)
+        self.dps[HVACMODE_DPS] = "hot"
+        self.assertEqual(self.subject.min_temp, 0)
+
+    def test_maximum_target_temperature(self):
+        self.dps[HVACMODE_DPS] = "cold"
+        self.assertEqual(self.subject.max_temp, 300)
+        self.dps[HVACMODE_DPS] = "hot"
+        self.assertEqual(self.subject.max_temp, 300)
+
+    async def test_legacy_set_temperature_with_temperature(self):
+        self.dps[HVACMODE_DPS] = "auto"
+        async with assert_device_properties_set(
+            self.subject._device, {TEMPERATURE_DPS: 240}
+        ):
+            await self.subject.async_set_temperature(temperature=24)
+
+    async def test_legacy_set_temperature_with_no_valid_properties(self):
+        self.dps[HVACMODE_DPS] = "auto"
+        await self.subject.async_set_temperature(something="else")
+        self.subject._device.async_set_property.assert_not_called
+
+    async def test_set_target_temperature_succeeds_within_valid_range(self):
+        self.dps[HVACMODE_DPS] = "auto"
+        async with assert_device_properties_set(
+            self.subject._device,
+            {TEMPERATURE_DPS: 250},
+        ):
+            await self.subject.async_set_target_temperature(25)
+
+    async def test_set_target_temperature_fails_outside_valid_range(self):
+        self.dps[HVACMODE_DPS] = "cold"
+        with self.assertRaisesRegex(
+            ValueError, "temperature \\(150\\) must be between 170 and 300"
+        ):
+            await self.subject.async_set_target_temperature(15)
+
+        self.dps[HVACMODE_DPS] = "hot"
+        with self.assertRaisesRegex(
+            ValueError, "temperature \\(330\\) must be between 0 and 300"
+        ):
+            await self.subject.async_set_target_temperature(33)
+
+    def test_current_temperature(self):
+        self.dps[CURRENTTEMP_DPS] = 25
+        self.assertEqual(self.subject.current_temperature, 25)
+
+    def test_hvac_mode(self):
+        self.dps[POWER_DPS] = True
+        self.dps[HVACMODE_DPS] = "hot"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
+
+        self.dps[HVACMODE_DPS] = "cold"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_COOL)
+
+        self.dps[HVACMODE_DPS] = "wet"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_DRY)
+
+        self.dps[HVACMODE_DPS] = "wind"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_FAN_ONLY)
+
+        self.dps[HVACMODE_DPS] = "auto"
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_AUTO)
+
+        self.dps[HVACMODE_DPS] = None
+        self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
+
+        self.dps[HVACMODE_DPS] = "auto"
+        self.dps[POWER_DPS] = False
+        self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(
+            self.subject.hvac_modes,
+            [
+                HVAC_MODE_OFF,
+                HVAC_MODE_HEAT,
+                HVAC_MODE_AUTO,
+                HVAC_MODE_COOL,
+                HVAC_MODE_DRY,
+                HVAC_MODE_FAN_ONLY,
+            ],
+        )
+
+    async def test_turn_on(self):
+        async with assert_device_properties_set(
+            self.subject._device, {POWER_DPS: True, HVACMODE_DPS: "hot"}
+        ):
+            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, {POWER_DPS: False}
+        ):
+            await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
+
+    def test_device_state_attributes(self):
+        self.dps["5"] = "fan?"
+        self.dps["18"] = 18
+        self.dps["20"] = 20
+        self.dps["105"] = "unknown105"
+        self.dps["110"] = 110
+        self.dps["113"] = "unknown113"
+        self.dps["114"] = "unknown114"
+        self.dps["119"] = "unknown119"
+        self.dps["120"] = "unknown120"
+        self.dps["126"] = "unknown126"
+        self.dps["127"] = "unknown127"
+        self.dps["128"] = "unknown128"
+        self.dps["129"] = "unknown129"
+        self.dps["130"] = 130
+        self.dps["131"] = True
+        self.dps["132"] = False
+        self.dps["133"] = "unknown133"
+        self.dps["134"] = "unknown134"
+
+        self.assertCountEqual(
+            self.subject.device_state_attributes,
+            {
+                "maybe_fan_mode": "fan?",
+                "unknown_18": 18,
+                "unknown_20": 20,
+                "unknown_105": "unknown105",
+                "unknown_110": 110,
+                "unknown_113": "unknown113",
+                "unknown_114": "unknown114",
+                "unknown_119": "unknown119",
+                "unknown_120": "unknown120",
+                "unknown_126": "unknown126",
+                "unknown_127": "unknown127",
+                "unknown_128": "unknown128",
+                "unknown_129": "unknown129",
+                "maybe_eco_temp": 130,
+                "unknown_131": True,
+                "unknown_132": False,
+                "unknown_133": "unknown133",
+                "unknown_134": "unknown134",
+            },
+        )