Przeglądaj źródła

climate: overide turn_off and turn_on

Override the turn_off and turn_on functions for climate platform.
When the hvac_mode attribute is boolean, toggle it without considering
the mappings so that the previous mode is not lost when turning off
and back on again.

Caveat: a hypothetical Tuya device that uses True for off and False
for on will not work correctly since the mappings are bypassed.  Such
a device has never been encountered, and is unlikely to exist.

Modify old climate device configs which had coupled "power" and
"hvac_mode" dps to use "hvac_mode" and "mode" instead.  Newer configs
have done it this way, since the resulting config file is simpler, but
some older ones had the logic reversed due to old bugs that have since
been fixed.

This is quite a big change, with high risk of a typo messing up one or
more devices. Unit tests are passing, so any devices with tests should
be OK.  Mostly it is the newer devices that don't have tests, which
mostly did not need modifying, unless someone copied from an older
config in one of the PRs.

Issue #302
Jason Rumney 3 lat temu
rodzic
commit
370ddcfcb6
22 zmienionych plików z 345 dodań i 714 usunięć
  1. 12 28
      custom_components/tuya_local/devices/beca_bac002_thermostat_c.yaml
  2. 10 19
      custom_components/tuya_local/devices/beca_bht002_thermostat_c.yaml
  3. 10 19
      custom_components/tuya_local/devices/beca_bht6000_thermostat_c.yaml
  4. 9 18
      custom_components/tuya_local/devices/beok_tr9b_thermostat.yaml
  5. 18 42
      custom_components/tuya_local/devices/carson_cb.yaml
  6. 18 42
      custom_components/tuya_local/devices/eberg_cooly_c35hd.yaml
  7. 16 34
      custom_components/tuya_local/devices/eberg_qubo_q40hd_heatpump.yaml
  8. 26 56
      custom_components/tuya_local/devices/electriq_12wminv_heatpump.yaml
  9. 21 45
      custom_components/tuya_local/devices/electriq_desd9lw_dehumidifier.yaml
  10. 26 61
      custom_components/tuya_local/devices/electriq_ecosilent14hpw_aircon.yaml
  11. 18 42
      custom_components/tuya_local/devices/fersk_vind_2_climate.yaml
  12. 22 52
      custom_components/tuya_local/devices/hellnar_heatpump.yaml
  13. 17 33
      custom_components/tuya_local/devices/jiahong_et72w_thermostat.yaml
  14. 15 33
      custom_components/tuya_local/devices/kogan_kawfpac09ya_airconditioner.yaml
  15. 13 31
      custom_components/tuya_local/devices/madimack_elite_v3_heatpump.yaml
  16. 10 19
      custom_components/tuya_local/devices/moes_bht002_thermostat_c.yaml
  17. 9 18
      custom_components/tuya_local/devices/nashone_mts700wb_thermostat.yaml
  18. 22 52
      custom_components/tuya_local/devices/starlight_heatpump.yaml
  19. 21 51
      custom_components/tuya_local/devices/tadiran_wind_heatpump.yaml
  20. 10 19
      custom_components/tuya_local/devices/weau_pool_heatpump_v2.yaml
  21. 18 0
      custom_components/tuya_local/generic/climate.py
  22. 4 0
      tests/test_device_config.py

+ 12 - 28
custom_components/tuya_local/devices/beca_bac002_thermostat_c.yaml

@@ -4,11 +4,19 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: "0"
+              value: cool
+            - dps_val: "1"
+              value: heat
+            - dps_val: "2"
+              value: fan_only
     - id: 2
       type: integer
       name: temperature
@@ -33,32 +41,8 @@ primary_entity:
           value: comfort
     - id: 102
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: "0"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: cool
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: "1"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: heat
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: "2"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: fan_only
-            - dps_val: false
-              value_redirect: power
-              value: "off"
+      name: mode
+      hidden: true
     - id: 103
       type: string
       name: fan_mode

+ 10 - 19
custom_components/tuya_local/devices/beca_bht002_thermostat_c.yaml

@@ -4,11 +4,17 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: "0"
+              value: auto
+            - dps_val: "1"
+              value: heat
     - id: 2
       type: integer
       name: temperature
@@ -24,23 +30,8 @@ primary_entity:
         - scale: 2
     - id: 4
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: "0"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: auto
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: "1"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: heat
-            - dps_val: false
-              value_redirect: power
+      name: mode
+      hidden: true
     - id: 5
       type: boolean
       name: preset_mode

+ 10 - 19
custom_components/tuya_local/devices/beca_bht6000_thermostat_c.yaml

@@ -4,11 +4,17 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: "0"
+              value: auto
+            - dps_val: "1"
+              value: heat
     - id: 2
       type: integer
       name: temperature
@@ -24,23 +30,8 @@ primary_entity:
         - scale: 2
     - id: 4
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: "0"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: auto
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: "1"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: heat
-            - dps_val: false
-              value_redirect: power
+      name: mode
+      hidden: true
     - id: 5
       type: boolean
       name: preset_mode

+ 9 - 18
custom_components/tuya_local/devices/beok_tr9b_thermostat.yaml

@@ -4,30 +4,21 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
-      hidden: true
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
-    - id: 2
-      type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: "auto"
-          constraint: power
+        - dps_val: true
+          constraint: mode
           conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
+            - dps_val: auto
               value: auto
-        - dps_val: manual
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
+            - dps_val: manual
               value: heat
+    - id: 2
+      type: string
+      name: mode
+      hidden: true
     - id: 16
       type: integer
       name: temperature

+ 18 - 42
custom_components/tuya_local/devices/carson_cb.yaml

@@ -3,14 +3,27 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: COOL
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: FAN
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: DRY
+              icon: "mdi:water"
+              value: dry
+            - dps_val: HEAT
+              icon: "mdi:fire"
+              value: heat   
     - id: 2
       name: temperature
       type: integer
@@ -28,46 +41,9 @@ primary_entity:
       name: current_temperature
       type: integer
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: COOL
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - dps_val: FAN
-          icon: "mdi:fan"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: fan_only
-        - dps_val: DRY
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
-        - dps_val: HEAT
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
+      hidden: true
     - id: 5
       name: fan_mode
       type: integer

+ 18 - 42
custom_components/tuya_local/devices/eberg_cooly_c35hd.yaml

@@ -3,58 +3,34 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
-    - id: 4
-      name: unknown_4
-      type: integer
-    - id: 5
-      name: hvac_mode
-      type: string
-      mapping:
-        - dps_val: 1
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
+        - dps_val: true
+          constraint: mode
           conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
+            - dps_val: "1"
+              icon: "mdi:fire"
               value: heat
-        - dps_val: 2
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
+            - dps_val: "2"
+              icon: "mdi:water"
               value: dry
-        - dps_val: 3
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
+            - dps_val: "3"
+              icon: "mdi:snowflake"
               value: cool
-        - dps_val: 4
-          icon: "mdi:fan"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
+            - dps_val: "4"
+              icon: "mdi:fan"
               value: fan_only
+    - id: 4
+      name: unknown_4
+      type: integer
+    - id: 5
+      name: mode
+      type: string
+      hidden: true
     - id: 6
       name: temperature
       type: integer

+ 16 - 34
custom_components/tuya_local/devices/eberg_qubo_q40hd_heatpump.yaml

@@ -3,14 +3,24 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: cold
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: hot
+              icon: "mdi:fire"
+              value: heat
+            - dps_val: dehumidify
+              icon: "mdi:water-percent"
+              value: dry              
     - id: 2
       name: temperature
       type: integer
@@ -28,37 +38,9 @@ primary_entity:
       name: current_temperature
       type: integer
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: cold
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: cool
-        - dps_val: hot
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
-        - dps_val: dehumidify
-          icon: "mdi:water-percent"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry              
+      hidden: true
     - id: 5
       name: fan_mode
       type: string
@@ -126,7 +108,7 @@ primary_entity:
         - dps_val: eco
           value: idle
         - dps_val: "off"
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: False
               value: "off"

+ 26 - 56
custom_components/tuya_local/devices/electriq_12wminv_heatpump.yaml

@@ -3,14 +3,30 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: cold
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: wind
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: wet
+              icon: "mdi:water"
+              value: dry
+            - dps_val: hot
+              icon: "mdi:fire"
+              value: heat
+            - dps_val: auto
+              icon: "mdi:hvac"
+              value: heat_cool
     - id: 2
       name: temperature
       type: integer
@@ -21,86 +37,40 @@ primary_entity:
       name: current_temperature
       type: integer
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: cold
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - 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
-        - 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: hot
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
-        - dps_val: auto
-          icon: "mdi:hvac"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat_cool
+      hidden: true
     - id: 5
       name: fan_mode
       type: integer
       mapping:
         - dps_val: 1
           value: auto
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: wet
               invalid: true
         - dps_val: 2
           value: Turbo
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: wet
               invalid: true
         - dps_val: 3
           value: low
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: wet
               invalid: true
         - dps_val: 4
           value: medium
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: wet
               invalid: true
         - dps_val: 5
           value: high
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: wet
               invalid: true

+ 21 - 45
custom_components/tuya_local/devices/electriq_desd9lw_dehumidifier.yaml

@@ -3,14 +3,27 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
-      hidden: true
       mapping:
         - dps_val: false
           icon: "mdi:air-humidifier-off"
-          icon_priority: 1
           value: "off"
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: "Auto"
+              value: "auto"
+              icon: "mdi:air-humidifier"
+            - dps_val: "Heater"
+              value: "heat"
+              icon: "mdi:fire"
+            - dps_val: "Dehumidity"
+              value: "dry"
+              icon: "mdi:water"
+            - dps_val: "Fan"
+              value: "fan_only"
+              icon: "mdi:fan"
     - id: 2
       type: integer
       name: humidity
@@ -24,64 +37,27 @@ primary_entity:
       name: fan_mode
       mapping:
         - dps_val: "Low"
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: "Auto"
               invalid: true
           value: "Low"
         - dps_val: "Medium"
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: "Auto"
               invalid: true
           value: "Medium"
         - dps_val: "High"
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: "Auto"
               invalid: true
           value: "High"
     - id: 5
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: "Auto"
-          constraint: power
-          conditions:
-          - dps_val: false
-            value_redirect: power
-          - dps_val: true
-            value: "auto"
-            icon: "mdi:air-humidifier"
-            icon-priority: 2
-        - dps_val: "Heater"
-          constraint: power
-          conditions:
-          - dps_val: false
-            value_redirect: power
-          - dps_val: true
-            value: "heat"
-            icon: "mdi:fire"
-            icon-priority: 2
-        - dps_val: "Dehumidity"
-          constraint: power
-          conditions:
-          - dps_val: false
-            value_redirect: power
-          - dps_val: true
-            value: "dry"
-            icon: "mdi:water"
-            icon-priority: 2
-        - dps_val: "Fan"
-          constraint: power
-          conditions:
-          - dps_val: false
-            value_redirect: power
-            value: "off"
-          - dps_val: true
-            value: "fan_only"
-            icon: "mdi:fan"
-            icon_priority: 2
+      hidden: true
     - id: 6
       type: integer
       name: current_humidity

+ 26 - 61
custom_components/tuya_local/devices/electriq_ecosilent14hpw_aircon.yaml

@@ -3,15 +3,30 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: true
-          value: "on"
+          constraint: mode
+          conditions:
+            - dps_val: "cool"
+              value: cool
+              icon: "mdi:snowflake"
+            - dps_val: "fan"
+              value: fan_only
+              icon: "mdi:fan"
+            - dps_val: "heat"
+              value: heat
+              icon: "mdi:fire"
+            - dps_val: "smart_cool"
+              value: auto
+              icon: "mdi:hvac"
+            - dps_val: "dry"
+              value: dry
+              icon: "mdi:water"
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
     - id: 2
       name: temperature
       type: integer
@@ -34,93 +49,43 @@ primary_entity:
             - dps_val: f
               value_redirect: current_temperature_f
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: "cool"
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: cool
-          icon: "mdi:snowflake"
-          icon_priority: 2
-        - dps_val: "fan"
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: fan_only
-          icon: "mdi:fan"
-          icon_priority: 2
-        - dps_val: "heat"
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: heat
-          icon: "mdi:fire"
-          icon_priority: 2
-        - dps_val: "smart_cool"
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: auto
-          icon: "mdi:hvac"
-          icon_priority: 2
-        - dps_val: "dry"
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: dry
-          icon: "mdi:water"
-          icon_priority: 2
+      hidden: true
     - id: 5
       name: fan_mode
       type: string
       mapping:
         - dps_val: "f1"
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: false
               value: "off"
             - dps_val: true
               value: low
         - dps_val: "f2"
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: false
               value: "off"
             - dps_val: true
               value: diffuse
         - dps_val: "f3"
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: false
               value: "off"
             - dps_val: true
               value: medium
         - dps_val: "f4"
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: false
               value: "off"
             - dps_val: true
               value: high
         - dps_val: "f5"
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: false
               value: "off"
@@ -150,7 +115,7 @@ primary_entity:
       type: boolean
       mapping:
         - dps_val: false
-          constraint: power
+          constraint: hvac_mode
           value: "off"
         - dps_val: true
           value: vertical

+ 18 - 42
custom_components/tuya_local/devices/fersk_vind_2_climate.yaml

@@ -3,14 +3,27 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: COOL
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: FAN
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: DRY
+              icon: "mdi:water"
+              value: dry
+            - dps_val: HEAT
+              icon: "mdi:fire"
+              value: heat
     - id: 2
       name: temperature
       type: integer
@@ -29,46 +42,9 @@ primary_entity:
       name: current_temperature
       type: integer
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: COOL
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - dps_val: FAN
-          icon: "mdi:fan"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: fan_only
-        - dps_val: DRY
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
-        - dps_val: HEAT
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
+      hidden: true
     - id: 5
       name: fan_mode
       type: integer

+ 22 - 52
custom_components/tuya_local/devices/hellnar_heatpump.yaml

@@ -3,20 +3,36 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: auto
+              icon: "mdi:hvac"
+              value: heat_cool
+            - dps_val: cold
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: hot
+              icon: "mdi:fire"
+              value: heat
+            - dps_val: wind
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: wet
+              icon: "mdi:water"
+              value: dry
     - id: 2
       name: temperature
       type: integer
       mapping:
         - scale: 10
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: cold
               range:
@@ -38,55 +54,9 @@ primary_entity:
       name: current_temperature
       type: integer
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: auto
-          icon: "mdi:hvac"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat_cool
-        - dps_val: cold
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - dps_val: hot
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
-        - 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
-        - dps_val: wet
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
+      hidden: true
     - id: 5
       name: maybe_fan_mode
       type: string

+ 17 - 33
custom_components/tuya_local/devices/jiahong_et72w_thermostat.yaml

@@ -4,11 +4,22 @@ primary_entity:
   dps:
     - id: 101
       type: boolean
-      name: power
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: "Smart"
+              icon: "mdi:calendar-sync"
+              value: auto
+            - dps_val: "Manual"
+              icon: "mdi:fire"
+              value: heat
+            - dps_val: "Anti_frozen"
+              icon: "mdi:snowflake"
+              value: cool
     - id: 102
       type: integer
       name: temperature
@@ -27,33 +38,8 @@ primary_entity:
                 max: 750
     - id: 103
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: "Smart"
-          icon: "mdi:calendar-sync"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: auto
-            - dps_val: false
-              value_redirect: power
-        - dps_val: "Manual"
-          icon: "mdi:fire"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: heat
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: "Anti_frozen"
-          icon: "mdi:snowflake"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: cool
-            - dps_val: false
-              value_redirect: power
+      name: mode
+      hidden: true
     - id: 105
       type: integer
       name: current_temperature
@@ -91,20 +77,18 @@ primary_entity:
       readonly: true
       mapping:
         - dps_val: true
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: true
               value: heating
             - dps_val: false
-              value_redirect: power
               value: "off"
         - dps_val: false
-          constraint: power
+          constraint: hvac_mode
           conditions:
             - dps_val: true
               value: idle
             - dps_val: false
-              value_redirect: power
               value: "off"
     - id: 104
       type: integer

+ 15 - 33
custom_components/tuya_local/devices/kogan_kawfpac09ya_airconditioner.yaml

@@ -6,13 +6,23 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: COOL
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: FAN
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: DRY
+              icon: "mdi:water"
+              value: dry
     - id: 2
       type: integer
       name: temperature
@@ -31,36 +41,8 @@ primary_entity:
       name: current_temperature
     - id: 4
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: COOL
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - dps_val: FAN
-          icon: "mdi:fan"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: fan_only
-        - dps_val: DRY
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
+      name: mode
+      hidden: true
     - id: 5
       type: string
       name: fan_mode

+ 13 - 31
custom_components/tuya_local/devices/madimack_elite_v3_heatpump.yaml

@@ -3,46 +3,28 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
-    - id: 2
-      name: hvac_mode
-      type: string
-      mapping:
-        - dps_val: auto
-          icon: "mdi:refresh-auto"
-          icon_priority: 1
-          constraint: power
+        - dps_val: true
+          constraint: mode
           conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
+            - dps_val: auto
+              icon: "mdi:refresh-auto"
               value: heat_cool
-        - dps_val: cold
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
+            - dps_val: cold
+              icon: "mdi:snowflake"
               value: cool
-        - dps_val: heating
-          icon: "mdi:hot-tub"
-          icon_priority: 3
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
+            - dps_val: heating
+              icon: "mdi:hot-tub"
               value: heat
+    - id: 2
+      name: mode
+      type: string
+      hidden: true
     - id: 4
       name: temperature
       type: integer

+ 10 - 19
custom_components/tuya_local/devices/moes_bht002_thermostat_c.yaml

@@ -4,11 +4,17 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: "0"
+              value: auto
+            - dps_val: "1"
+              value: heat
     - id: 2
       type: integer
       name: temperature
@@ -24,23 +30,8 @@ primary_entity:
         - scale: 2
     - id: 4
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: "0"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: auto
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: "1"
-          constraint: power
-          conditions:
-            - dps_val: true
-              value: heat
-            - dps_val: false
-              value_redirect: power
+      name: mode
+      hidden: true
     - id: 5
       type: boolean
       name: preset_mode

+ 9 - 18
custom_components/tuya_local/devices/nashone_mts700wb_thermostat.yaml

@@ -4,30 +4,21 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
-      hidden: true
+      name: hvac_mode
       mapping:
         - dps_val: False
           value: "off"
-    - id: 2
-      type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: cold
-          constraint: power
+        - dps_val: true
+          constraint: mode
           conditions:
-            - dps_val: true
+            - dps_val: cold
               value: cool
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-        - dps_val: hot
-          constraint: power
-          conditions:
-            - dps_val: true
+            - dps_val: hot
               value: heat
-            - dps_val: false
-              value_redirect: power
+    - id: 2
+      type: string
+      name: mode
+      hidden: true
     - id: 3
       type: string
       name: work_state

+ 22 - 52
custom_components/tuya_local/devices/starlight_heatpump.yaml

@@ -3,14 +3,30 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: auto
+              icon: "mdi:hvac"
+              value: heat_cool
+            - dps_val: cold
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: hot
+              icon: "mdi:fire"
+              value: heat
+            - dps_val: wind
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: wet
+              icon: "mdi:water"
+              value: dry            
     - id: 2
       name: temperature
       type: integer
@@ -20,7 +36,7 @@ primary_entity:
       mapping:
         - scale: 10
           step: 5
-          constraint: hvac_mode
+          constraint: mode
           conditions:
             - dps_val: wet
               invalid: true
@@ -30,55 +46,9 @@ primary_entity:
       name: current_temperature
       type: integer
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: auto
-          icon: "mdi:hvac"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat_cool
-        - dps_val: cold
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - dps_val: hot
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
-        - 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
-        - dps_val: wet
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
+      hidden: true
     - id: 5
       name: fan_mode
       type: string

+ 21 - 51
custom_components/tuya_local/devices/tadiran_wind_heatpump.yaml

@@ -4,14 +4,30 @@ primary_entity:
   entity: climate
   dps:
     - id: 1
-      name: power
+      name: hvac_mode
       type: boolean
       mapping:
         - dps_val: false
           value: "off"
           icon: "mdi:hvac-off"
-          icon_priority: 1
-      hidden: true
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: auto
+              icon: "mdi:hvac"
+              value: heat_cool
+            - dps_val: cooling
+              icon: "mdi:snowflake"
+              value: cool
+            - dps_val: heating
+              icon: "mdi:fire"
+              value: heat
+            - dps_val: fan
+              icon: "mdi:fan"
+              value: fan_only
+            - dps_val: dehum
+              icon: "mdi:water"
+              value: dry
     - id: 2
       name: temperature
       type: integer
@@ -24,55 +40,9 @@ primary_entity:
       mapping:
         - scale: 10
     - id: 4
-      name: hvac_mode
+      name: mode
       type: string
-      mapping:
-        - dps_val: auto
-          icon: "mdi:hvac"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat_cool
-        - dps_val: cooling
-          icon: "mdi:snowflake"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
-        - dps_val: heating
-          icon: "mdi:fire"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: heat
-        - dps_val: fan
-          icon: "mdi:fan"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: fan_only
-        - dps_val: dehum
-          icon: "mdi:water"
-          icon_priority: 2
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: dry
+      hidden: true
     - id: 5
       name: fan_mode
       type: string

+ 10 - 19
custom_components/tuya_local/devices/weau_pool_heatpump_v2.yaml

@@ -6,11 +6,17 @@ primary_entity:
   dps:
     - id: 1
       type: boolean
-      name: power
-      hidden: true
+      name: hvac_mode
       mapping:
         - dps_val: false
           value: "off"
+        - dps_val: true
+          constraint: mode
+          conditions:
+            - dps_val: eheat
+              value: heat
+            - dps_val: ecool
+              value: cool
     - id: 9
       type: integer
       name: temperature
@@ -24,23 +30,8 @@ primary_entity:
         - scale: 10
     - id: 2
       type: string
-      name: hvac_mode
-      mapping:
-        - dps_val: eheat
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-              value: "off"
-            - dps_val: true
-              value: heat
-        - dps_val: ecool
-          constraint: power
-          conditions:
-            - dps_val: false
-              value_redirect: power
-            - dps_val: true
-              value: cool
+      name: mode
+      hidden: true
     - id: 20
       type: bitfield
       name: fault

+ 18 - 0
custom_components/tuya_local/generic/climate.py

@@ -286,6 +286,24 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
             raise NotImplementedError()
         await self._hvac_mode_dps.async_set_value(self._device, hvac_mode)
 
+    async def async_turn_on(self):
+        """Turn on the climate device."""
+        # Bypass the usual dps mapping to switch the power dp directly
+        # this way the hvac_mode will be kept when toggling off and on.
+        if self._hvac_mode_dps and self._hvac_mode_dps.type is bool:
+            await self.device.async_set_property(self._hvac_mode_dps, True)
+        else:
+            await super.async_turn_on()
+
+    async def async_turn_off(self):
+        """Turn off the climate device."""
+        # Bypass the usual dps mapping to switch the power dp directly
+        # this way the hvac_mode will be kept when toggling off and on.
+        if self._hvac_mode_dps and self._hvac_mode_dps.type is bool:
+            await self.device.async_set_property(self._hvac_mode_dps, False)
+        else:
+            await super.async_turn_off()
+
     @property
     def is_aux_heat(self):
         """Return state of aux heater"""

+ 4 - 0
tests/test_device_config.py

@@ -54,6 +54,10 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
         """
         for cfg in available_configs():
             parsed = TuyaDeviceConfig(cfg)
+            # Check for error messages or unparsed config
+            if isinstance(parsed, str) or isinstance(parsed._config, str):
+                self.fail(f"unparsable yaml in {cfg}")
+
             self.assertIsNotNone(parsed._config.get("name"), f"name missing from {cfg}")
             self.assertIsNotNone(
                 parsed._config.get("primary_entity"),