Przeglądaj źródła

Add support for ElectriQ Airflex W15 heatpump

Issue #175
Jason Rumney 3 lat temu
rodzic
commit
0efc008193

+ 1 - 0
ACKNOWLEDGEMENTS.md

@@ -101,3 +101,4 @@ Further device support has been made with the assistance of users.  Please consi
 - [poolMiniDomo](https://github.com/poolMiniDomo) for assistance supporting Moes Temperature and Humidity switches.
 - [pretoriano80](https://github.com/pretoriano80) for assistance supporting AlecoAir dehumidifiers.
 - [JanekSMC](https://github.com/JanekSMC) for assistance supporting Orion Smart Locks.
+- [RichardMawdsley](https://github.com/RichardMawdsley) for assistance supporting ElectriQ Airflex 15W heatpumps.

+ 1 - 0
README.md

@@ -51,6 +51,7 @@ the device will not work despite being listed below.
 ### Air Conditioners / Heatpumps
 
 - ElectriQ 12WMINV
+- ElectriQ Airflex 15W
 - Tadiran Wind 65/3P
 - Fersk Vind 2
 - Carson CB PA280

+ 118 - 0
custom_components/tuya_local/devices/electriq_airflex15w_heatpump.yaml

@@ -0,0 +1,118 @@
+name: ElectriQ Airflex 15W Heatpump
+product:
+  - id: 4RUISW6Lmtz2u1l8
+primary_entity:
+  entity: climate
+  dps:
+    - id: 1
+      name: hvac_mode
+      type: boolean
+      mapping:
+        - dps_val: false
+          value: "off"
+          icon: "mdi:hvac-off"
+        - dps_val: true
+          constraint: preset_mode
+          conditions:
+            - dps_val: auto
+              value: heat_cool
+              icon: "mdi:hvac"
+            - dps_val: cold
+              value: cool
+              icon: "mdi:snowflake"
+            - dps_val: hot
+              value: heat
+              icon: "mdi:fire"
+            - dps_val: wet
+              value: dry
+              icon: "mdi:water"
+            - dps_val: wind
+              value: fan_only
+              icon: "mdi:fan"
+            - dps_val: eco
+              value: heat_cool
+              icon: "mdi:leaf"
+    - id: 2
+      type: integer
+      name: temperature
+      range:
+        min: 16
+        max: 31
+      mapping:
+        - constraint: temperature_unit
+          conditions:
+            - dps_val: F
+              value_redirect: temp_set_f
+              range:
+                min: 62
+                max: 90
+    - id: 3
+      type: integer
+      name: current_temperature
+      mapping:
+        - constraint: temperature_unit
+          conditions:
+            - dps_val: F
+              value_redirect: temp_current_f
+    - id: 17
+      type: integer
+      name: humidity
+      range:
+        min: 0
+        max: 100
+    - id: 101
+      type: string
+      name: preset_mode
+      mapping:
+        - dps_val: auto
+          value: Auto
+        - dps_val: cold
+          value: Cool
+        - dps_val: hot
+          value: Heat
+        - dps_val: wet
+          value: Dry
+        - dps_val: wind
+          value: Fan
+        - dps_val: eco
+          value: eco
+    - id: 104
+      type: string
+      name: fan_mode
+      mapping:
+        - dps_val: "1"
+          value: low
+        - dps_val: "2"
+          value: medium
+        - dps_val: "3"
+          value: high
+    - id: 109
+      type: string
+      name: temperature_unit
+    - id: 110
+      type: integer
+      name: temp_set_f
+      range:
+        min: 62
+        max: 90
+      hidden: true
+    - id: 111
+      type: integer
+      name: temp_current_f
+      hidden: true
+    - id: 112
+      type: integer
+      name: current_humidity
+secondary_entities:
+  - entity: select
+    name: Temperature Unit
+    category: config
+    dps:
+      - id: 109
+        type: string
+        name: option
+        mapping:
+          - dps_val: C
+            value: Celsius
+          - dps_val: F
+            value: Fahrenheit

+ 13 - 0
tests/const.py

@@ -1340,3 +1340,16 @@ ORION_SMARTLOCK_PAYLOAD = {
     "15": 0,
     "16": False,
 }
+
+ELECTRIQ_AIRFLEX15W_PAYLOAD = {
+    "1": True,
+    "2": 22,
+    "3": 27,
+    "17": 50,
+    "101": "cold",
+    "104": "2",
+    "109": "C",
+    "110": 72,
+    "111": 80,
+    "112": 68,
+}

+ 205 - 0
tests/devices/test_electriq_airflex15w_heatpump.py

@@ -0,0 +1,205 @@
+from homeassistant.components.climate.const import (
+    ClimateEntityFeature,
+    HVACMode,
+)
+from homeassistant.const import PERCENTAGE, TEMP_CELSIUS, TEMP_FAHRENHEIT
+
+from ..const import ELECTRIQ_AIRFLEX15W_PAYLOAD
+from ..helpers import assert_device_properties_set
+from ..mixins.climate import TargetTemperatureTests
+from ..mixins.select import BasicSelectTests
+from .base_device_tests import TuyaDeviceTestCase
+
+POWER_DPS = "1"
+TEMPERATURE_DPS = "2"
+CURRENTTEMP_DPS = "3"
+HUMIDITY_DPS = "17"
+HVACMODE_DPS = "101"
+FAN_DPS = "104"
+UNIT_DPS = "109"
+TEMPF_DPS = "110"
+CURTEMPF_DPS = "111"
+CURHUMID_DPS = "112"
+
+
+class TestElectriqAirflex15WHeatpump(
+    BasicSelectTests,
+    TargetTemperatureTests,
+    TuyaDeviceTestCase,
+):
+    __test__ = True
+
+    def setUp(self):
+        self.setUpForConfig(
+            "electriq_airflex15w_heatpump.yaml", ELECTRIQ_AIRFLEX15W_PAYLOAD
+        )
+        self.subject = self.entities.get("climate")
+
+        self.setUpTargetTemperature(
+            TEMPERATURE_DPS,
+            self.subject,
+            min=16,
+            max=31,
+        )
+        self.setUpBasicSelect(
+            UNIT_DPS,
+            self.entities.get("select_temperature_unit"),
+            {
+                "C": "Celsius",
+                "F": "Fahrenheit",
+            },
+        )
+        self.mark_secondary(["select_temperature_unit"])
+
+    def test_supported_features(self):
+        self.assertEqual(
+            self.subject.supported_features,
+            (
+                ClimateEntityFeature.TARGET_TEMPERATURE
+                | ClimateEntityFeature.TARGET_HUMIDITY
+                | ClimateEntityFeature.FAN_MODE
+                | ClimateEntityFeature.PRESET_MODE
+            ),
+        )
+
+    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[HVACMODE_DPS] = "eco"
+        self.assertEqual(self.subject.icon, "mdi:leaf")
+        self.dps[POWER_DPS] = False
+        self.assertEqual(self.subject.icon, "mdi:hvac-off")
+
+    def test_temperature_unit(self):
+        self.dps[UNIT_DPS] = "C"
+        self.assertEqual(self.subject.temperature_unit, TEMP_CELSIUS)
+        self.dps[UNIT_DPS] = "F"
+        self.assertEqual(self.subject.temperature_unit, TEMP_FAHRENHEIT)
+
+    def test_current_temperature(self):
+        self.dps[UNIT_DPS] = "C"
+        self.dps[CURRENTTEMP_DPS] = 25
+        self.assertEqual(self.subject.current_temperature, 25)
+        self.dps[UNIT_DPS] = "F"
+        self.dps[CURTEMPF_DPS] = 78
+        self.assertEqual(self.subject.current_temperature, 78)
+
+    def test_temperature_f(self):
+        self.dps[UNIT_DPS] = "F"
+        self.dps[TEMPF_DPS] = 90
+        self.assertEqual(self.subject.target_temperature, 90)
+
+    async def test_set_temperature_f(self):
+        self.dps[UNIT_DPS] = "F"
+        async with assert_device_properties_set(
+            self.subject._device,
+            {TEMPF_DPS: 85},
+        ):
+            await self.subject.async_set_temperature(temperature=85)
+
+    def test_hvac_mode(self):
+        self.dps[POWER_DPS] = True
+        self.dps[HVACMODE_DPS] = "hot"
+        self.assertEqual(self.subject.hvac_mode, HVACMode.HEAT)
+        self.dps[HVACMODE_DPS] = "cold"
+        self.assertEqual(self.subject.hvac_mode, HVACMode.COOL)
+        self.dps[HVACMODE_DPS] = "wet"
+        self.assertEqual(self.subject.hvac_mode, HVACMode.DRY)
+        self.dps[HVACMODE_DPS] = "wind"
+        self.assertEqual(self.subject.hvac_mode, HVACMode.FAN_ONLY)
+        self.dps[HVACMODE_DPS] = "auto"
+        self.assertEqual(self.subject.hvac_mode, HVACMode.HEAT_COOL)
+        self.dps[HVACMODE_DPS] = "eco"
+        self.assertEqual(self.subject.hvac_mode, HVACMode.HEAT_COOL)
+        self.dps[POWER_DPS] = False
+        self.assertEqual(self.subject.hvac_mode, HVACMode.OFF)
+
+    def test_hvac_modes(self):
+        self.assertCountEqual(
+            self.subject.hvac_modes,
+            [
+                HVACMode.OFF,
+                HVACMode.HEAT,
+                HVACMode.HEAT_COOL,
+                HVACMode.COOL,
+                HVACMode.DRY,
+                HVACMode.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(HVACMode.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(HVACMode.OFF)
+
+    def test_fan_mode(self):
+        self.dps[FAN_DPS] = "1"
+        self.assertEqual(self.subject.fan_mode, "low")
+        self.dps[FAN_DPS] = "2"
+        self.assertEqual(self.subject.fan_mode, "medium")
+        self.dps[FAN_DPS] = "3"
+        self.assertEqual(self.subject.fan_mode, "high")
+
+    def test_fan_modes(self):
+        self.assertCountEqual(
+            self.subject.fan_modes,
+            [
+                "low",
+                "medium",
+                "high",
+            ],
+        )
+
+    async def test_set_fan_mode_to_low(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {FAN_DPS: "1"},
+        ):
+            await self.subject.async_set_fan_mode("low")
+
+    async def test_set_fan_mode_to_medium(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {FAN_DPS: "2"},
+        ):
+            await self.subject.async_set_fan_mode("medium")
+
+    async def test_set_fan_mode_to_high(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {FAN_DPS: "3"},
+        ):
+            await self.subject.async_set_fan_mode("high")
+
+    def test_humidity(self):
+        self.dps[HUMIDITY_DPS] = 74
+        self.assertEqual(self.subject.target_humidity, 74)
+
+    async def test_set_humidity(self):
+        async with assert_device_properties_set(
+            self.subject._device,
+            {HUMIDITY_DPS: 40},
+        ):
+            await self.subject.async_set_humidity(40)
+
+    def test_extra_state_attribures(self):
+        self.assertEqual(
+            self.subject.extra_state_attributes,
+            {},
+        )