Ver Fonte

Adjustments to Eberg Qubo Q40HD based on further info

Issue #35
Jason Rumney há 4 anos atrás
pai
commit
d0d86442af

+ 47 - 49
custom_components/tuya_local/devices/eberg_qubo_q40hd_heatpump.yaml

@@ -15,14 +15,14 @@ primary_entity:
       name: temperature
       type: integer
       range:
-        min: 15
+        min: 17
         max: 30
       mapping:
         - constraint: temperature_unit
           conditions:
             - dps_val: f
               range:
-                min: 60
+                min: 63
                 max: 86
     - id: 3
       name: current_temperature
@@ -38,6 +38,7 @@ primary_entity:
           conditions:
             - dps_val: false
               value_redirect: power
+              value: "off"
             - dps_val: true
               value: cool
         - dps_val: hot
@@ -49,59 +50,18 @@ primary_entity:
               value_redirect: power
             - dps_val: true
               value: heat
-        - dps_val: wet
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
-        - dps_val: wind
-          icon: "mdi:fan"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: fan_only
     - id: 5
       name: fan_mode
       type: string
       mapping:
         - dps_val: auto
           value: auto
-          constraint: hvac_mode
-          conditions:
-            - dps_val: wet
-              invalid: true
-            - dps_val: hot
-              invalid: true
-            - dps_val: wind
-              invalid: true
         - dps_val: low
           value: low
-          constraint: hvac_mode
-          conditions:
-            - dps_val: hot
-              invalid: true
         - dps_val: middle
           value: medium
-          constraint: hvac_mode
-          conditions:
-            - dps_val: wet
-              invalid: true
-            - dps_val: hot
-              invalid: true
         - dps_val: high
           value: high
-          constraint: hvac_mode
-          conditions:
-            - dps_val: wet
-              invalid: true
     - id: 19
       name: temperature_unit
       type: string
@@ -115,13 +75,51 @@ primary_entity:
       name: timer
     - id: 25
       type: boolean
-      name: unknown_25
+      name: preset_mode
+      mapping:
+        - dps_val: true
+          value: sleep
+        - dps_val: false
+          value: comfort
     - id: 30
       type: boolean
-      name: boolean
-      name: unknown_30
-      # Suspect one of 25 or 30 is Sleep (can model as preset or switch)
+      name: swing_mode
+      mapping:
+        - dps_val: true
+          value: vertical
+        - dps_val: false
+          value: "off"
     - id: 101
-      name: unknown_101
+      name: hvac_action
       type: string
-#     suspect hvac_action, but mapping unknown. Observed value "heat_s"
+      # mappings based on dev portal info and observed values
+      mapping:
+        - dps_val: heat_s
+          value: heating
+        - dps_val: cool_s
+          value: cooling
+        - dps_val: ventilation
+          value: fan
+        - dps_val: auto
+          value: idle
+        - dps_val: anti-clockwise
+          value: fan
+        - dps_val: hot
+          value: heating
+        - dps_val: appointment
+          value: idle
+        - dps_val: wet
+          value: drying
+        - dps_val: auto_clean
+          value: idle
+        - dps_val: wind
+          value: fan
+        - dps_val: eco
+          value: idle
+        - dps_val: "off"
+          constraint: power
+          conditions:
+            - dps_val: False
+              value: "off"
+            - dps_val: True
+              value: idle

+ 132 - 67
tests/devices/test_eberg_qubo_q40hd_heatpump.py

@@ -1,11 +1,21 @@
 from homeassistant.components.climate.const import (
+    CURRENT_HVAC_COOL,
+    CURRENT_HVAC_DRY,
+    CURRENT_HVAC_FAN,
+    CURRENT_HVAC_HEAT,
+    CURRENT_HVAC_IDLE,
+    CURRENT_HVAC_OFF,
     HVAC_MODE_COOL,
-    HVAC_MODE_DRY,
-    HVAC_MODE_FAN_ONLY,
     HVAC_MODE_HEAT,
     HVAC_MODE_OFF,
+    PRESET_SLEEP,
+    PRESET_COMFORT,
     SUPPORT_FAN_MODE,
+    SUPPORT_PRESET_MODE,
+    SUPPORT_SWING_MODE,
     SUPPORT_TARGET_TEMPERATURE,
+    SWING_OFF,
+    SWING_VERTICAL,
 )
 from homeassistant.const import STATE_UNAVAILABLE, TEMP_CELSIUS, TEMP_FAHRENHEIT
 
@@ -20,9 +30,9 @@ HVACMODE_DPS = "4"
 FAN_DPS = "5"
 UNIT_DPS = "19"
 TIMER_DPS = "22"
-UNKNOWN25_DPS = "25"
-UNKNOWN30_DPS = "30"
-UNKNOWN101_DPS = "101"
+PRESET_DPS = "25"
+SWING_DPS = "30"
+HVACACTION_DPS = "101"
 
 
 class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
@@ -38,7 +48,12 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
     def test_supported_features(self):
         self.assertEqual(
             self.subject.supported_features,
-            SUPPORT_TARGET_TEMPERATURE | SUPPORT_FAN_MODE,
+            (
+                SUPPORT_TARGET_TEMPERATURE
+                | SUPPORT_FAN_MODE
+                | SUPPORT_PRESET_MODE
+                | SUPPORT_SWING_MODE
+            ),
         )
 
     def test_icon(self):
@@ -47,10 +62,6 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
         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")
 
@@ -69,9 +80,9 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
 
     def test_minimum_target_temperature(self):
         self.dps[UNIT_DPS] = "c"
-        self.assertEqual(self.subject.min_temp, 15)
+        self.assertEqual(self.subject.min_temp, 17)
         self.dps[UNIT_DPS] = "f"
-        self.assertEqual(self.subject.min_temp, 60)
+        self.assertEqual(self.subject.min_temp, 63)
 
     def test_maximum_target_temperature(self):
         self.dps[UNIT_DPS] = "c"
@@ -111,23 +122,23 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
-            ValueError, "temperature \\(14\\) must be between 15 and 30"
+            ValueError, "temperature \\(16\\) must be between 17 and 30"
         ):
-            await self.subject.async_set_target_temperature(14)
+            await self.subject.async_set_target_temperature(16)
 
         with self.assertRaisesRegex(
-            ValueError, "temperature \\(31\\) must be between 15 and 30"
+            ValueError, "temperature \\(31\\) must be between 17 and 30"
         ):
             await self.subject.async_set_target_temperature(31)
 
         self.dps[UNIT_DPS] = "f"
         with self.assertRaisesRegex(
-            ValueError, "temperature \\(59\\) must be between 60 and 86"
+            ValueError, "temperature \\(62\\) must be between 63 and 86"
         ):
-            await self.subject.async_set_target_temperature(59)
+            await self.subject.async_set_target_temperature(62)
 
         with self.assertRaisesRegex(
-            ValueError, "temperature \\(87\\) must be between 60 and 86"
+            ValueError, "temperature \\(87\\) must be between 63 and 86"
         ):
             await self.subject.async_set_target_temperature(87)
 
@@ -143,16 +154,10 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
         self.dps[HVACMODE_DPS] = "hot"
         self.assertEqual(self.subject.hvac_mode, HVAC_MODE_HEAT)
 
-        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] = None
         self.assertEqual(self.subject.hvac_mode, STATE_UNAVAILABLE)
 
-        self.dps[HVACMODE_DPS] = "wind"
+        self.dps[HVACMODE_DPS] = "cold"
         self.dps[POWER_DPS] = False
         self.assertEqual(self.subject.hvac_mode, HVAC_MODE_OFF)
 
@@ -162,8 +167,6 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
             [
                 HVAC_MODE_OFF,
                 HVAC_MODE_COOL,
-                HVAC_MODE_DRY,
-                HVAC_MODE_FAN_ONLY,
                 HVAC_MODE_HEAT,
             ],
         )
@@ -181,7 +184,6 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
             await self.subject.async_set_hvac_mode(HVAC_MODE_OFF)
 
     def test_fan_mode(self):
-        self.dps[HVACMODE_DPS] = "cold"
         self.dps[FAN_DPS] = "low"
         self.assertEqual(self.subject.fan_mode, "low")
         self.dps[FAN_DPS] = "middle"
@@ -203,80 +205,143 @@ class TestEbergQuboQ40HDHeatpump(TuyaDeviceTestCase):
         )
 
     async def test_set_fan_mode_to_low(self):
-        self.dps[HVACMODE_DPS] = "cold"
         async with assert_device_properties_set(
             self.subject._device,
             {FAN_DPS: "low"},
         ):
             await self.subject.async_set_fan_mode("low")
 
-    async def test_set_fan_mode_to_low_fails_when_heating(self):
-        self.dps[HVACMODE_DPS] = "hot"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("low")
-
     async def test_set_fan_mode_to_medium(self):
-        self.dps[HVACMODE_DPS] = "cold"
         async with assert_device_properties_set(
             self.subject._device,
             {FAN_DPS: "middle"},
         ):
             await self.subject.async_set_fan_mode("medium")
 
-    async def test_set_fan_mode_to_medium_fails_when_heating_or_drying(self):
-        self.dps[HVACMODE_DPS] = "hot"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("medium")
-
-        self.dps[HVACMODE_DPS] = "wet"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("medium")
-
     async def test_set_fan_mode_to_high(self):
-        self.dps[HVACMODE_DPS] = "cold"
         async with assert_device_properties_set(
             self.subject._device,
             {FAN_DPS: "high"},
         ):
             await self.subject.async_set_fan_mode("high")
 
-    async def test_set_fan_mode_to_high_fails_when_drying(self):
-        self.dps[HVACMODE_DPS] = "wet"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("high")
-
     async def test_set_fan_mode_to_auto(self):
-        self.dps[HVACMODE_DPS] = "cold"
         async with assert_device_properties_set(
             self.subject._device,
             {FAN_DPS: "auto"},
         ):
             await self.subject.async_set_fan_mode("auto")
 
-    async def test_set_fan_mode_to_auto_fails_unless_cooling(self):
-        self.dps[HVACMODE_DPS] = "hot"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("auto")
+    def test_swing_mode(self):
+        self.dps[SWING_DPS] = True
+        self.assertEqual(self.subject.swing_mode, SWING_VERTICAL)
+        self.dps[SWING_DPS] = False
+        self.assertEqual(self.subject.swing_mode, SWING_OFF)
 
-        self.dps[HVACMODE_DPS] = "wet"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("auto")
+    def test_swing_modes(self):
+        self.assertCountEqual(
+            self.subject.swing_modes,
+            [
+                SWING_VERTICAL,
+                SWING_OFF,
+            ],
+        )
 
-        self.dps[HVACMODE_DPS] = "wind"
-        with self.assertRaises(AttributeError):
-            await self.subject.async_set_fan_mode("auto")
+    async def test_set_swing_mode_to_vertical(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {SWING_DPS: True},
+        ):
+            await self.subject.async_set_swing_mode(SWING_VERTICAL)
+
+    async def test_set_swing_mode_to_off(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {SWING_DPS: False},
+        ):
+            await self.subject.async_set_swing_mode(SWING_OFF)
+
+    def test_preset_mode(self):
+        self.dps[PRESET_DPS] = True
+        self.assertEqual(self.subject.preset_mode, PRESET_SLEEP)
+        self.dps[PRESET_DPS] = False
+        self.assertEqual(self.subject.preset_mode, PRESET_COMFORT)
+
+    def test_preset_modes(self):
+        self.assertCountEqual(
+            self.subject.preset_modes,
+            [
+                PRESET_COMFORT,
+                PRESET_SLEEP,
+            ],
+        )
+
+    async def test_set_preset_mode_to_sleep(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: True},
+        ):
+            await self.subject.async_set_preset_mode(PRESET_SLEEP)
+
+    async def test_set_preset_mode_to_normal(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {PRESET_DPS: False},
+        ):
+            await self.subject.async_set_preset_mode(PRESET_COMFORT)
+
+    def test_hvac_action(self):
+        self.dps[POWER_DPS] = True
+        self.dps[HVACACTION_DPS] = "heat_s"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
+
+        self.dps[HVACACTION_DPS] = "hot"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
+
+        self.dps[HVACACTION_DPS] = "heating"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_HEAT)
+
+        self.dps[HVACACTION_DPS] = "cool_s"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_COOL)
+
+        self.dps[HVACACTION_DPS] = "cooling"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_COOL)
+
+        self.dps[HVACACTION_DPS] = "anti-clockwise"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_FAN)
+
+        self.dps[HVACACTION_DPS] = "ventilation"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_FAN)
+
+        self.dps[HVACACTION_DPS] = "wind"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_FAN)
+
+        self.dps[HVACACTION_DPS] = "appointment"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+
+        self.dps[HVACACTION_DPS] = "auto"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+
+        self.dps[HVACACTION_DPS] = "auto_clean"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+
+        self.dps[HVACACTION_DPS] = "eco"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+
+        self.dps[HVACACTION_DPS] = "wet"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_DRY)
+
+        self.dps[HVACACTION_DPS] = "off"
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_IDLE)
+
+        self.dps[POWER_DPS] = False
+        self.assertEqual(self.subject.hvac_action, CURRENT_HVAC_OFF)
 
     def test_device_state_attribures(self):
         self.dps[TIMER_DPS] = 22
-        self.dps[UNKNOWN25_DPS] = True
-        self.dps[UNKNOWN30_DPS] = False
-        self.dps[UNKNOWN101_DPS] = "101"
         self.assertDictEqual(
             self.subject.device_state_attributes,
             {
                 "timer": 22,
-                "unknown_25": True,
-                "unknown_30": False,
-                "unknown_101": "101",
             },
         )