Просмотр исходного кода

Tests: Add a schema check to device config tests

Schema check detects typos, wrong indentation, misplaced attributes,
and use of imaginary attributes that contributers made up on the spot.

Many errors detected by this.
Jason Rumney 1 год назад
Родитель
Сommit
a52aeca788
62 измененных файлов с 256 добавлено и 180 удалено
  1. 1 1
      custom_components/tuya_local/devices/CT20W_pir_motion_detector.yaml
  2. 1 2
      custom_components/tuya_local/devices/README.md
  3. 2 2
      custom_components/tuya_local/devices/agl_ultramagic_lock.yaml
  4. 1 1
      custom_components/tuya_local/devices/asip_0622_planter.yaml
  5. 0 1
      custom_components/tuya_local/devices/aspen_asp200_fan.yaml
  6. 0 1
      custom_components/tuya_local/devices/atorch_s1wp.yaml
  7. 1 2
      custom_components/tuya_local/devices/aubess_rainpoint_irrigation_system.yaml
  8. 1 1
      custom_components/tuya_local/devices/beca_zht002_thermostat_c.yaml
  9. 0 2
      custom_components/tuya_local/devices/beok_tr9b_thermostat.yaml
  10. 3 3
      custom_components/tuya_local/devices/ble_hu06_lock.yaml
  11. 1 1
      custom_components/tuya_local/devices/ble_water_valve.yaml
  12. 2 2
      custom_components/tuya_local/devices/bresser_weather_station.yaml
  13. 2 2
      custom_components/tuya_local/devices/breville_lad208_dehumidifier.yaml
  14. 1 1
      custom_components/tuya_local/devices/breville_smartairconnect_purifier.yaml
  15. 0 1
      custom_components/tuya_local/devices/catit_pet_feeder.yaml
  16. 2 1
      custom_components/tuya_local/devices/cleanair_605b_humidifier.yaml
  17. 13 8
      custom_components/tuya_local/devices/cooper_hunter_air_conditioner.yaml
  18. 1 2
      custom_components/tuya_local/devices/diivoo_wt05.yaml
  19. 2 3
      custom_components/tuya_local/devices/dongguan_garage_door_opener.yaml
  20. 2 1
      custom_components/tuya_local/devices/dts238_7_energy_meter.yaml
  21. 0 3
      custom_components/tuya_local/devices/earu_smart_wifi_circuit_breaker_with_energy_monitor.yaml
  22. 1 1
      custom_components/tuya_local/devices/etop_ht_thermostat.yaml
  23. 1 2
      custom_components/tuya_local/devices/garza_irrigation_system.yaml
  24. 0 1
      custom_components/tuya_local/devices/goodcell_ev_charger.yaml
  25. 1 2
      custom_components/tuya_local/devices/holman_wx1_taptimer.yaml
  26. 1 2
      custom_components/tuya_local/devices/holman_wx2_taptimer.yaml
  27. 1 2
      custom_components/tuya_local/devices/holman_wx8_irrigation_controller.yaml
  28. 28 24
      custom_components/tuya_local/devices/hysen_hy08we2_thermostat.yaml
  29. 0 3
      custom_components/tuya_local/devices/immax_neo_light_vento.yaml
  30. 1 1
      custom_components/tuya_local/devices/inkbird_bbq4t_thermometer.yaml
  31. 1 1
      custom_components/tuya_local/devices/inkbird_bbq4t_thermometerv2.yaml
  32. 0 12
      custom_components/tuya_local/devices/inkbird_ibs_m1s.yaml
  33. 3 3
      custom_components/tuya_local/devices/inkbird_itc308_thermostat.yaml
  34. 0 1
      custom_components/tuya_local/devices/ironzon_fingerprint_lock.yaml
  35. 0 8
      custom_components/tuya_local/devices/its_45hd_heatpump.yaml
  36. 1 1
      custom_components/tuya_local/devices/kabum_smart500_vacuum.yaml
  37. 0 18
      custom_components/tuya_local/devices/ledlux_thermostat.yaml
  38. 1 1
      custom_components/tuya_local/devices/lenovo_e1_vacuum.yaml
  39. 0 1
      custom_components/tuya_local/devices/leos_loo_too.yaml
  40. 0 7
      custom_components/tuya_local/devices/lytmi_hdmisync_backlight.yaml
  41. 8 7
      custom_components/tuya_local/devices/minco_mh1823d_thermostat.yaml
  42. 4 2
      custom_components/tuya_local/devices/mrc_magnum_floorheater.yaml
  43. 1 1
      custom_components/tuya_local/devices/nx_100ap_air_purifier.yaml
  44. 2 2
      custom_components/tuya_local/devices/orion_outdoor_siren.yaml
  45. 2 2
      custom_components/tuya_local/devices/probreeze_pb20.yaml
  46. 0 1
      custom_components/tuya_local/devices/proscenic_m9_vacuum.yaml
  47. 1 1
      custom_components/tuya_local/devices/rgb_light_bar.yaml
  48. 1 1
      custom_components/tuya_local/devices/rotenso_ronir35wi_heatpump.yaml
  49. 0 1
      custom_components/tuya_local/devices/rotenso_ronix_heatpump.yaml
  50. 1 2
      custom_components/tuya_local/devices/sencor_air_conditioner.yaml
  51. 1 1
      custom_components/tuya_local/devices/smart_led_strip.yaml
  52. 0 1
      custom_components/tuya_local/devices/smart_siren_alarm.yaml
  53. 0 6
      custom_components/tuya_local/devices/suntec_coolfix_airconditioner.yaml
  54. 1 1
      custom_components/tuya_local/devices/tonepie_t1pro_catlitterbox.yaml
  55. 8 5
      custom_components/tuya_local/devices/tv_backlights.yaml
  56. 1 1
      custom_components/tuya_local/devices/ultenic_t10_vacuum.yaml
  57. 1 2
      custom_components/tuya_local/devices/vivosun_de0003_dehumidifier.yaml
  58. 0 1
      custom_components/tuya_local/devices/yp_petfeeeder.yaml
  59. 2 2
      custom_components/tuya_local/devices/yx316wifi_aroma_diffuser.yaml
  60. 3 4
      custom_components/tuya_local/devices/yym_805SW_aroma_nightlight.yaml
  61. 0 4
      custom_components/tuya_local/devices/zg205w_mmWave_presence_sensor.yaml
  62. 143 0
      tests/test_device_config.py

+ 1 - 1
custom_components/tuya_local/devices/CT20W_pir_motion_detector.yaml

@@ -29,11 +29,11 @@ secondary_entities:
             value: true
   - entity: sensor
     class: battery
-    unit: "%"
     dps:
       - id: 2
         type: integer
         name: sensor
+        unit: "%"
   - entity: binary_sensor
     class: plug
     dps:

+ 1 - 2
custom_components/tuya_local/devices/README.md

@@ -32,8 +32,7 @@ listing can also have an optional `name`, which is intended to specify the
 specific brand and model name or number of the matching device.  In future
 when local discovery is implemented to discover products by id, this name will
 be displayed on discovery, and be available as manufacturer and model info
-in device settings (so probably in future name will be split into manufacturer
-and model, but for now, putting them together as name is OK).
+in device settings.
 
 ### `primary_entity`
 

+ 2 - 2
custom_components/tuya_local/devices/agl_ultramagic_lock.yaml

@@ -104,7 +104,7 @@ secondary_entities:
         range:
           min: 1
           max: 1200
-          unit: s
+        unit: s
   - entity: number
     category: config
     icon: "mdi:alarm"
@@ -117,4 +117,4 @@ secondary_entities:
         range:
           min: 0
           max: 100
-          unit: s
+        unit: s

+ 1 - 1
custom_components/tuya_local/devices/asip_0622_planter.yaml

@@ -1,5 +1,5 @@
 name: Planter
-products:
+#products:
 #  - id:
 #    name: ASIP-0622 indoor planter
 primary_entity:

+ 0 - 1
custom_components/tuya_local/devices/aspen_asp200_fan.yaml

@@ -56,7 +56,6 @@ secondary_entities:
         name: current_temperature
         type: integer
         unit: F
-        icon: "mdi:thermometer"
   - entity: light
     name: Display
     category: config

+ 0 - 1
custom_components/tuya_local/devices/atorch_s1wp.yaml

@@ -514,7 +514,6 @@ secondary_entities:
       - id: 137
         type: integer
         name: value
-        mode: box
         unit: min
         range:
           min: 0

+ 1 - 2
custom_components/tuya_local/devices/aubess_rainpoint_irrigation_system.yaml

@@ -1,8 +1,7 @@
 name: Irrigation system
 products:
   - id: 2ak7r2culspkc7hx
-    model: RainPoint TTP106W
-    manufacturer: Aubess
+    name: Aubess RainPoint TTP106W
 primary_entity:
   entity: switch
   icon: "mdi:pipe-valve"

+ 1 - 1
custom_components/tuya_local/devices/beca_zht002_thermostat_c.yaml

@@ -81,12 +81,12 @@ secondary_entities:
           max: 5
   - entity: number
     name: High limit temperature ceiling
+    icon: "mdi:thermometer-alert"
     category: config
     dps:
       - id: 19
         name: value
         type: integer
-        icon: "mdi:thermometer-alert"
         range:
           min: 45
           max: 70

+ 0 - 2
custom_components/tuya_local/devices/beok_tr9b_thermostat.yaml

@@ -137,7 +137,6 @@ secondary_entities:
     name: High temperature limit
     category: config
     class: temperature
-    icon: "mdi:thermometer"
     dps:
       - id: 19
         type: integer
@@ -158,7 +157,6 @@ secondary_entities:
         name: value
         type: integer
         unit: C
-        icon: "mdi:thermometer"
         range:
           min: 50
           max: 10000

+ 3 - 3
custom_components/tuya_local/devices/ble_hu06_lock.yaml

@@ -201,9 +201,9 @@ secondary_entities:
         range:
           min: 10
           max: 180
-          mapping:
-            - step: 10
-          unit: s
+        mapping:
+          - step: 10
+        unit: s
   - entity: binary_sensor
     class: door
     category: diagnostic

+ 1 - 1
custom_components/tuya_local/devices/ble_water_valve.yaml

@@ -6,7 +6,7 @@ products:
   - id: bfc513e1f9d4d259a10wzu
     name: Diivoo Water Timer Valve WT-03
   - id: nxquc5lb
-    model: SOP10
+    name: SOP10
   - id: so5ybnw9
     name: BWC-495.bt Royal Gardineer
 primary_entity:

+ 2 - 2
custom_components/tuya_local/devices/bresser_weather_station.yaml

@@ -1,9 +1,9 @@
 # Bresser 7-in-1 ClimateConnect Tuya Smart Home Weather Centre
 # https://www.bresser.de/en/Weather-Time/BRESSER-7-in-1-ClimateConnect-Tuya-Smart-Home-Weather-Centre.html
-name: Bresser weather station
+name: Weather station
 products:
   - id: 8qk6p78udvbjwlof
-    model: C6085A
+    name: Bresser C6085A
 primary_entity:
   entity: sensor
   name: Indoor temperature

+ 2 - 2
custom_components/tuya_local/devices/breville_lad208_dehumidifier.yaml

@@ -155,7 +155,7 @@ secondary_entities:
     class: problem
     name: Tank full
     icon: "mdi:cup-outline"
-    icon-priority: 2
+    icon_priority: 2
     dps:
       - id: 11
         type: bitfield
@@ -165,7 +165,7 @@ secondary_entities:
           - dps_val: 8
             value: true
             icon: "mdi:cup-water"
-            icon-priority: 1
+            icon_priority: 1
           - value: false
   - entity: binary_sensor
     name: Defrost

+ 1 - 1
custom_components/tuya_local/devices/breville_smartairconnect_purifier.yaml

@@ -4,11 +4,11 @@ products:
 primary_entity:
   entity: fan
   translation_only_key: fan_with_presets
+  icon: "mdi:air-purifier"
   dps:
     - id: 1
       name: switch
       type: boolean
-      icon: "mdi:air-purifier"
     - id: 3
       name: preset_mode
       type: string

+ 0 - 1
custom_components/tuya_local/devices/catit_pet_feeder.yaml

@@ -25,7 +25,6 @@ secondary_entities:
       - id: 101
         name: sensor
         type: integer
-    type: integer
   - entity: button
     class: restart
     name: Factory reset

+ 2 - 1
custom_components/tuya_local/devices/cleanair_605b_humidifier.yaml

@@ -14,7 +14,8 @@ primary_entity:
       range:
         min: 30
         max: 75
-        step: 5
+      mapping:
+        - step: 5
     - id: 14
       name: current_humidity
       type: integer

+ 13 - 8
custom_components/tuya_local/devices/cooper_hunter_air_conditioner.yaml

@@ -145,14 +145,19 @@ secondary_entities:
       - id: 9
         name: switch
         type: boolean
-        constraint: mode
-        conditions:
-          - dps_val: auto
-            invalid: true
-          - dps_val: wind
-            invalid: true
-          - dps_val: hot
-            invalid: true
+        mapping:
+          - constraint: mode
+            conditions:
+              - dps_val: auto
+                invalid: true
+              - dps_val: wind
+                invalid: true
+              - dps_val: hot
+                invalid: true
+      - id: 4
+        name: mode
+        type: string
+        hidden: true
   - entity: switch
     name: Ioniser
     category: config

+ 1 - 2
custom_components/tuya_local/devices/diivoo_wt05.yaml

@@ -15,8 +15,7 @@
 name: Dual water timer
 products:
   - id: fdrbxxbg
-    manufacturer: Diivoo
-    model: WT-05
+    name: Diivoo WT-05
 primary_entity:
   entity: switch
   icon: "mdi:pipe-valve"

+ 2 - 3
custom_components/tuya_local/devices/dongguan_garage_door_opener.yaml

@@ -2,11 +2,10 @@
 # Tuya Smart Life WiFi Motorized Swing Gate Sliding Gate Opener Dry Contact
 # 110V 240V Voice Control with Alexa Google Home
 # https://www.aliexpress.com/item/1005003913566298.html
-name: WiFi garage opener
+name: Garage opener
 products:
   - id: 1wwbzczt9hrtwqjr
-    name: Dongguan garage door
-    model: PJ-WGDOOR01
+    name: Dongguan PJ-WGDOOR01
 primary_entity:
   entity: cover
   class: garage

+ 2 - 1
custom_components/tuya_local/devices/dts238_7_energy_meter.yaml

@@ -51,7 +51,8 @@ secondary_entities:
         name: sensor
         unit: kW
         class: measurement
-        scale: 10000
+        mapping:
+          - scale: 10000
   - entity: binary_sensor
     name: Fault
     class: problem

+ 0 - 3
custom_components/tuya_local/devices/earu_smart_wifi_circuit_breaker_with_energy_monitor.yaml

@@ -36,7 +36,6 @@ secondary_entities:
         type: base64
         unit: V
         class: measurement
-        persist: true
         name: sensor
         mapping:
           - mask: "FFFF000000000000"
@@ -49,7 +48,6 @@ secondary_entities:
         optional: true
         force: true
         type: base64
-        persist: true
         unit: A
         name: sensor
         mapping:
@@ -64,7 +62,6 @@ secondary_entities:
         force: true
         type: base64
         unit: kW
-        persist: true
         name: sensor
         mapping:
           - mask: "0000000000FFFFFF"

+ 1 - 1
custom_components/tuya_local/devices/etop_ht_thermostat.yaml

@@ -133,13 +133,13 @@ secondary_entities:
   - entity: number
     name: Temperature correction
     category: config
+    icon: "mdi:wrench-clock"
     mode: slider
     dps:
       - id: 27
         name: value
         type: integer
         unit: C
-        icon: "mdi:wrench-clock"
         range:
           min: -100
           max: 100

+ 1 - 2
custom_components/tuya_local/devices/garza_irrigation_system.yaml

@@ -1,8 +1,7 @@
 name: Garden irrigation system
 products:
   - id: xnajzurgqo1ugohn
-    model: ITV103W
-    manufacturer: Garza
+    name: Garza ITV103W
 primary_entity:
   entity: switch
   icon: "mdi:watering-can"

+ 0 - 1
custom_components/tuya_local/devices/goodcell_ev_charger.yaml

@@ -94,7 +94,6 @@ secondary_entities:
     name: Clear energy
     class: restart
     category: config
-    hidden: true
     dps:
       - id: 16
         type: boolean

+ 1 - 2
custom_components/tuya_local/devices/holman_wx1_taptimer.yaml

@@ -1,8 +1,7 @@
 name: Tap timer
 products:
   - id: zrsgzc8jktsricjj
-    model: WX1
-    manufacturer: Holman
+    name: Holman WX1
     # DP decoding thanks to funtastix
 primary_entity:
   entity: switch

+ 1 - 2
custom_components/tuya_local/devices/holman_wx2_taptimer.yaml

@@ -1,8 +1,7 @@
 name: Tap timer
 products:
   - id: wfchjk5vc9bysjtk
-    model: WX2
-    manufacturer: Holman
+    name: Holman WX2
 primary_entity:
   entity: switch
   name: Manual 1

+ 1 - 2
custom_components/tuya_local/devices/holman_wx8_irrigation_controller.yaml

@@ -1,8 +1,7 @@
 name: Irrigation Controller
 products:
   - id: 3c8bxnseywh7radc
-    model: WX8
-    manufacturer: Holman
+    name: Holman WX8
 primary_entity:
   entity: binary_sensor
   class: running

+ 28 - 24
custom_components/tuya_local/devices/hysen_hy08we2_thermostat.yaml

@@ -219,12 +219,13 @@ secondary_entities:
         range:
           min: 35
           max: 70
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 95
-              max: 158
+        mapping:
+          - constraint: unit
+            conditions:
+              - dps_val: true
+                range:
+                  min: 95
+                  max: 158
       - id: 101
         type: boolean
         name: unit
@@ -244,12 +245,13 @@ secondary_entities:
         range:
           min: 1
           max: 10
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 34
-              max: 50
+        mapping:
+          - constraint: unit
+            conditions:
+              - dps_val: true
+                range:
+                  min: 34
+                  max: 50
       - id: 101
         type: boolean
         name: unit
@@ -269,12 +271,13 @@ secondary_entities:
         range:
           min: 2
           max: 70
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 36
-              max: 158
+        mapping:
+          - constraint: unit
+            conditions:
+              - dps_val: true
+                range:
+                  min: 36
+                  max: 158
       - id: 101
         type: boolean
         name: unit
@@ -294,12 +297,13 @@ secondary_entities:
         range:
           min: 1
           max: 10
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 34
-              max: 50
+        mapping:
+          - constraint: unit
+            conditions:
+              - dps_val: true
+                range:
+                  min: 34
+                  max: 50
       - id: 101
         type: boolean
         name: unit

+ 0 - 3
custom_components/tuya_local/devices/immax_neo_light_vento.yaml

@@ -12,7 +12,6 @@ primary_entity:
     - id: 2
       type: string
       name: preset_mode
-      category: config
       mapping:
         - dps_val: normal
           value: normal
@@ -23,7 +22,6 @@ primary_entity:
     - id: 3
       name: speed
       type: integer
-      category: config
       range:
         min: 1
         max: 6
@@ -37,7 +35,6 @@ primary_entity:
     - id: 8
       name: direction
       type: string
-      category: config
 secondary_entities:
   - entity: light
     dps:

+ 1 - 1
custom_components/tuya_local/devices/inkbird_bbq4t_thermometer.yaml

@@ -60,7 +60,7 @@ secondary_entities:
         unit: F
   - entity: binary_sensor
     class: power
-    category: diagnostics
+    category: diagnostic
     dps:
       - id: 1
         type: boolean

+ 1 - 1
custom_components/tuya_local/devices/inkbird_bbq4t_thermometerv2.yaml

@@ -65,7 +65,7 @@ secondary_entities:
         unit: F
   - entity: binary_sensor
     class: power
-    category: diagnostics
+    category: diagnostic
     dps:
       - id: 1
         type: boolean

+ 0 - 12
custom_components/tuya_local/devices/inkbird_ibs_m1s.yaml

@@ -32,7 +32,6 @@ primary_entity:
           endianness: little
           mask: "FFFF00"
           constraint: type
-          constraint_decode: true
           conditions:
             - dps_val: 0
               invalid: true
@@ -59,7 +58,6 @@ secondary_entities:
           - endianness: little
             mask: "FF000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -86,7 +84,6 @@ secondary_entities:
             endianness: little
             mask: "FFFF0000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -112,7 +109,6 @@ secondary_entities:
           - endianness: little
             mask: "FF00000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -139,7 +135,6 @@ secondary_entities:
             endianness: little
             mask: "FFFF000000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -165,7 +160,6 @@ secondary_entities:
           - endianness: little
             mask: "FF0000000000000000000000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -194,7 +188,6 @@ secondary_entities:
             mask: >-
               FFFF00000000000000000000000000000000000000000000000000000000000000
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -222,7 +215,6 @@ secondary_entities:
             mask: "FF000000000000000000000000000000000000000\
               000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -251,7 +243,6 @@ secondary_entities:
             mask: "FFFF00000000000000000000000000000000000000\
               00000000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -279,7 +270,6 @@ secondary_entities:
             mask: "FF000000000000000000000000000000000000000000000\
               00000000000000000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -308,7 +298,6 @@ secondary_entities:
             mask: "FFFF00000000000000000000000000000000000000000000000\
               0000000000000000000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true
@@ -336,7 +325,6 @@ secondary_entities:
             mask: "FF00000000000000000000000000000000000000000000000000000000\
               00000000000000000000000000000000000000000000000000000000000000"
             constraint: type
-            constraint_decode: true
             conditions:
               - dps_val: 0
                 invalid: true

+ 3 - 3
custom_components/tuya_local/devices/inkbird_itc308_thermostat.yaml

@@ -66,8 +66,8 @@ primary_entity:
       name: hvac_action
       mapping:
         - dps_val: "0"
-          icon: "mdi-thermometer-off"
-          icon-priority: 5
+          icon: "mdi:thermometer-off"
+          icon_priority: 5
           value: idle
         - dps_val: "1"
           icon: "mdi:snowflake"
@@ -220,7 +220,7 @@ secondary_entities:
   - entity: number
     category: config
     name: Heating hysteresis
-    icon: "mdi: thermometer-chevron-up"
+    icon: "mdi:thermometer-chevron-up"
     dps:
       - id: 117
         name: value

+ 0 - 1
custom_components/tuya_local/devices/ironzon_fingerprint_lock.yaml

@@ -39,7 +39,6 @@ primary_entity:
       type: integer
       name: unlock_voice
       optional: true
-      persist: true
     - id: 64
       type: string
       name: offline_password_timestamp

+ 0 - 8
custom_components/tuya_local/devices/its_45hd_heatpump.yaml

@@ -71,38 +71,30 @@ primary_entity:
     - id: 30
       type: boolean
       name: chlorination
-      attribute: true
     - id: 32
       type: boolean
       name: aux_heat
-      readonly: true
     - id: 40
       type: integer
       name: model_code
     - id: 101
       type: integer
       name: current
-      attribute: true
     - id: 102
       type: integer
       name: voltage
-      attribute: true
     - id: 103
       type: integer
       name: power
-      attribute: true
     - id: 104
       type: integer
       name: energy
-      attribute: true
     - id: 105
       type: boolean
       name: electricity_monitor
-      attribute: true
     - id: 106
       type: boolean
       name: linkage
-      attribute: true
     - id: 108
       type: boolean
       name: dipswitch_1

+ 1 - 1
custom_components/tuya_local/devices/kabum_smart500_vacuum.yaml

@@ -54,7 +54,7 @@ primary_entity:
           value: smart
         - dps_val: spiral
           value: clean_spot
-        - dps_value: single
+        - dps_val: single
           value: single_room
         - dps_val: wall_follow
           value: wall_follow

+ 0 - 18
custom_components/tuya_local/devices/ledlux_thermostat.yaml

@@ -145,12 +145,6 @@ secondary_entities:
         range:
           min: 1
           max: 10
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 34
-              max: 50
         unit: C
   - entity: number
     name: High temperature limit
@@ -163,12 +157,6 @@ secondary_entities:
         range:
           min: 2
           max: 70
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 36
-              max: 158
         unit: C
   - entity: number
     name: Low temperature limit
@@ -181,12 +169,6 @@ secondary_entities:
         range:
           min: 1
           max: 10
-        constraint: unit
-        conditions:
-          - dps_val: true
-            range:
-              min: 34
-              max: 50
         unit: C
   - entity: select
     name: Initial state

+ 1 - 1
custom_components/tuya_local/devices/lenovo_e1_vacuum.yaml

@@ -192,7 +192,7 @@ secondary_entities:
       - id: 115
         type: boolean
         name: button
-        optional: trus
+        optional: true
   - entity: select
     name: Scheduled clean
     icon: "mdi:robot-vacuum"

+ 0 - 1
custom_components/tuya_local/devices/leos_loo_too.yaml

@@ -28,7 +28,6 @@ secondary_entities:
       - id: 2
         type: string
         name: option
-        category: config
         mapping:
           - dps_val: auto_clean
             value: Auto clean

+ 0 - 7
custom_components/tuya_local/devices/lytmi_hdmisync_backlight.yaml

@@ -80,7 +80,6 @@ secondary_entities:
   - entity: number
     category: config
     name: Degree of diffusion
-    type: integer
     mode: slider
     dps:
       - id: 108
@@ -95,12 +94,6 @@ secondary_entities:
             step: 10
   - entity: select
     name: Scene
-    format:
-      - name: scene_num
-        bytes: 2
-        range:
-          min: 1
-          max: 8
     icon: "mdi:palette"
     category: config
     dps:

+ 8 - 7
custom_components/tuya_local/devices/minco_mh1823d_thermostat.yaml

@@ -223,13 +223,14 @@ secondary_entities:
         range:
           min: 5
           max: 65
-        constraint: unit
-        conditions:
-          - dps_val: f
-            value_redirect: max_temp_f
-            range:
-              min: 41
-              max: 150
+        mapping:
+          - constraint: unit
+            conditions:
+              - dps_val: f
+                value_redirect: max_temp_f
+                range:
+                  min: 41
+                  max: 150
       - id: 107
         type: integer
         name: max_temp_f

+ 4 - 2
custom_components/tuya_local/devices/mrc_magnum_floorheater.yaml

@@ -341,7 +341,8 @@ secondary_entities:
         type: integer
         name: sensor
         unit: "%"
-        mask: 00FF
+        mapping:
+          - mask: 00FF
   - entity: sensor
     name: Yearly consumption
     category: diagnostic
@@ -350,7 +351,8 @@ secondary_entities:
         type: integer
         name: sensor
         unit: "%"
-        mask: FF00
+        mapping:
+          - mask: FF00
   - entity: select
     name: Floor covering
     icon: "mdi:floor-plan"

+ 1 - 1
custom_components/tuya_local/devices/nx_100ap_air_purifier.yaml

@@ -5,11 +5,11 @@ products:
 primary_entity:
   entity: fan
   translation_only_key: fan_with_presets
+  icon: "mdi:air-purifier"
   dps:
     - id: 1
       name: switch
       type: boolean
-      icon: "mdi:air-purifier"
     - id: 3
       name: preset_mode
       type: string

+ 2 - 2
custom_components/tuya_local/devices/orion_outdoor_siren.yaml

@@ -1,9 +1,9 @@
 name: Outdoor siren
 products:
   - id: im2eqqhj72suwwko
-    model: Orion SWS08HA
+    name: Orion SWS08HA
   - id: likuc5ld1ap3apcm
-    model: Elesion NX-4980
+    name: Elesion NX-4980
 primary_entity:
   entity: siren
   dps:

+ 2 - 2
custom_components/tuya_local/devices/probreeze_pb20.yaml

@@ -136,7 +136,7 @@ secondary_entities:
     name: Tank
     class: problem
     icon: "mdi:cup-outline"
-    icon-priority: 2
+    icon_priority: 2
     category: diagnostic
     dps:
       - id: 11
@@ -146,5 +146,5 @@ secondary_entities:
           - dps_val: 8
             value: true
             icon: "mdi:cup-water"
-            icon-priority: 1
+            icon_priority: 1
           - value: false

+ 0 - 1
custom_components/tuya_local/devices/proscenic_m9_vacuum.yaml

@@ -476,7 +476,6 @@ secondary_entities:
   - entity: select
     name: Working mode
     icon: "mdi:vacuum"
-    optional: true
     dps:
       - id: 41
         name: option

+ 1 - 1
custom_components/tuya_local/devices/rgb_light_bar.yaml

@@ -67,4 +67,4 @@ secondary_entities:
           max: 86400
         mapping:
           - scale: 60
-            steep: 60
+            step: 60

+ 1 - 1
custom_components/tuya_local/devices/rotenso_ronir35wi_heatpump.yaml

@@ -77,7 +77,7 @@ primary_entity:
       type: boolean
       name: temperature_unit
       mapping:
-        - dps_vali: true
+        - dps_val: true
           value: F
         - value: C
     - id: 104

+ 0 - 1
custom_components/tuya_local/devices/rotenso_ronix_heatpump.yaml

@@ -262,7 +262,6 @@ secondary_entities:
             value: false
           - value: true
   - entity: sensor
-    name:
     class: pm25
     category: diagnostic
     dps:

+ 1 - 2
custom_components/tuya_local/devices/sencor_air_conditioner.yaml

@@ -1,8 +1,7 @@
 name: Air conditioner
 products:
   - id: ypgwqvhjrl5chq6h
-    model: SAC MT7048C Air Conditioner
-    manufacturer: Sencor
+    name: Sencor SAC MT7048C
 primary_entity:
   entity: climate
   translation_only_key: aircon_extra

+ 1 - 1
custom_components/tuya_local/devices/smart_led_strip.yaml

@@ -37,11 +37,11 @@ primary_entity:
       range:
         min: 0
         max: 1000
-      invert: true
       mapping:
         - target_range:
             min: 2700
             max: 6500
+          invert: true
     - id: 24
       name: rgbhsv
       type: hex

+ 0 - 1
custom_components/tuya_local/devices/smart_siren_alarm.yaml

@@ -5,7 +5,6 @@ products:
 primary_entity:
   entity: alarm_control_panel
   name: Status
-  trigger: true
   icon: "mdi:shield-off-outline"
   dps:
     - id: 116

+ 0 - 6
custom_components/tuya_local/devices/suntec_coolfix_airconditioner.yaml

@@ -22,12 +22,6 @@ primary_entity:
               value: fan_only
             - dps_val: Heat
               value: heat
-              mapping:
-                - constraint: model_id
-                  conditions:
-                    - dps_val: C
-                      hidden: true
-                      invalid: true
     - id: 2
       type: integer
       name: temperature

+ 1 - 1
custom_components/tuya_local/devices/tonepie_t1pro_catlitterbox.yaml

@@ -29,7 +29,7 @@ secondary_entities:
         unit: visits
   - entity: sensor
     name: Time spent today
-    mdi: "mdi:emoticon-poop"
+    icon: "mdi:emoticon-poop"
     class: duration
     dps:
       - id: 8

+ 8 - 5
custom_components/tuya_local/devices/tv_backlights.yaml

@@ -68,7 +68,6 @@ primary_entity:
 secondary_entities:
   - entity: number
     name: Backlight intensity
-    type: integer
     mode: slider
     icon: mdi:speedometer-medium
     dps:
@@ -180,22 +179,26 @@ secondary_entities:
         type: integer
   - entity: sensor
     category: diagnostic
-    icon: mdi:arrow-expand-horizontal
+    class: distance
     name: Horizontal LED length
-    unit: dm
     dps:
       - id: 116
         name: sensor
         type: integer
+        unit: m
+        mapping:
+          - scale: 10
   - entity: sensor
     category: diagnostic
-    icon: mdi:arrow-expand-vertical
+    class: distance
     name: Vertical LED length
-    unit: dm
     dps:
       - id: 117
         name: sensor
         type: integer
+        unit: m
+        mapping:
+          - scale: 10
   - entity: sensor
     category: diagnostic
     icon: mdi:speedometer-slow

+ 1 - 1
custom_components/tuya_local/devices/ultenic_t10_vacuum.yaml

@@ -27,7 +27,7 @@ primary_entity:
           value: random
         - dps_val: smart
           value: smart
-        - dps_value: wall_follow
+        - dps_val: wall_follow
           value: wall_follow
         - dps_val: mop
           value: mop

+ 1 - 2
custom_components/tuya_local/devices/vivosun_de0003_dehumidifier.yaml

@@ -1,8 +1,7 @@
 name: Dehumidifier
 products:
   - id: qrjffdu2bjrd7v42
-    name: DE0003 10L Smart Dehumidifier
-    manufacturer: Vivosun
+    name: Vivosun DE0003 10L
 primary_entity:
   entity: humidifier
   class: dehumidifier

+ 0 - 1
custom_components/tuya_local/devices/yp_petfeeeder.yaml

@@ -25,7 +25,6 @@ secondary_entities:
       - id: 15
         name: sensor
         type: integer
-    type: integer
   - entity: button
     class: restart
     name: Factory reset

+ 2 - 2
custom_components/tuya_local/devices/yx316wifi_aroma_diffuser.yaml

@@ -1,9 +1,9 @@
 # DPS sample:  { "1": true, "2": true, "3": "MID", "7": true, "8": 1000,
 #                "9": "colourful1", "10": "", "11": 0 }
-name: Aroma Diffuser With Lamp
+name: Aroma diffuser with lamp
 products:
   - id: arkdxfhlkpdyof9x
-    model: YX316WIFI
+    name: YX316WIFI
 primary_entity:
   entity: fan
   icon: "mdi:scent"

+ 3 - 4
custom_components/tuya_local/devices/yym_805SW_aroma_nightlight.yaml

@@ -3,11 +3,11 @@
 name: Aroma diffuser
 products:
   - id: c0nh3LmEk0NDebrq
-    model: YYM-805SW
+    name: YYM-805SW
   - id: 4870500398f4abbfbae4
-    model: GX
+    name: GX
   - id: kgczidn0awas0prr
-    manufacturer: Tellur
+    name: Tellur
 primary_entity:
   entity: fan
   dps:
@@ -103,7 +103,6 @@ secondary_entities:
             value: "6 hours"
       - id: 4
         name: remaining
-        readolny: true
         optional: true
         type: integer
         range:

+ 0 - 4
custom_components/tuya_local/devices/zg205w_mmWave_presence_sensor.yaml

@@ -186,7 +186,6 @@ secondary_entities:
     name: Motion minimum detection distance
     category: config
     icon: mdi:signal-distance-variant
-    hidden: true
     dps:
       - id: 110
         type: integer
@@ -203,7 +202,6 @@ secondary_entities:
     name: Small motion minimum detection distance
     category: config
     icon: mdi:signal-distance-variant
-    hidden: true
     dps:
       - id: 111
         type: integer
@@ -220,7 +218,6 @@ secondary_entities:
     name: Breathing minimum detection distance
     category: config
     icon: mdi:signal-distance-variant
-    hidden: true
     dps:
       - id: 112
         type: integer
@@ -237,7 +234,6 @@ secondary_entities:
     name: Adaptive testing time
     category: config
     icon: mdi:timer
-    hidden: true
     dps:
       - id: 113
         type: integer

+ 143 - 0
tests/test_device_config.py

@@ -4,6 +4,7 @@ from unittest.mock import MagicMock
 
 from fuzzywuzzy import fuzz
 from homeassistant.components.sensor import SensorDeviceClass
+import voluptuous as vol
 
 from custom_components.tuya_local.helpers.config import get_device_id
 from custom_components.tuya_local.helpers.device_config import (
@@ -19,6 +20,141 @@ from custom_components.tuya_local.sensor import TuyaLocalSensor
 
 from .const import GPPH_HEATER_PAYLOAD, KOGAN_HEATER_PAYLOAD
 
+
+PRODUCT_SCHEMA = vol.Schema(
+    {
+        vol.Required("id"): str,
+        vol.Optional("name"): str,
+    }
+)
+CONDMAP_SCHEMA = vol.Schema(
+    {
+        vol.Optional("dps_val"): vol.Maybe(vol.Any(str, int, bool, list)),
+        vol.Optional("value"): vol.Maybe(vol.Any(str, int, bool, float)),
+        vol.Optional("value_redirect"): str,
+        vol.Optional("value_mirror"): str,
+        vol.Optional("range"): {
+            vol.Required("min"): int,
+            vol.Required("max"): int,
+        },
+        vol.Optional("target_range"): {
+            vol.Required("min"): int,
+            vol.Required("max"): int,
+        },
+        vol.Optional("scale"): vol.Any(int, float),
+        vol.Optional("step"): vol.Any(int, float),
+        vol.Optional("mask"): str,
+        vol.Optional("endianness"): str,
+        vol.Optional("invert"): True,
+        vol.Optional("unit"): str,
+        vol.Optional("icon"): vol.Match(r"^mdi:"),
+        vol.Optional("icon_priority"): int,
+        vol.Optional("hidden"): True,
+        vol.Optional("invalid"): True,
+        vol.Optional("default"): True,
+    }
+)
+COND_SCHEMA = CONDMAP_SCHEMA.extend(
+    {
+        vol.Optional("mapping"): [CONDMAP_SCHEMA],
+    }
+)
+MAPPING_SCHEMA = CONDMAP_SCHEMA.extend(
+    {
+        vol.Optional("constraint"): str,
+        vol.Optional("conditions"): [COND_SCHEMA],
+    }
+)
+FORMAT_SCHEMA = vol.Schema(
+    {
+        vol.Required("name"): str,
+        vol.Required("bytes"): int,
+        vol.Optional("range"): {
+            vol.Required("min"): int,
+            vol.Required("max"): int,
+        },
+    }
+)
+DP_SCHEMA = vol.Schema(
+    {
+        vol.Required("id"): int,
+        vol.Required("type"): vol.In(
+            [
+                "string",
+                "integer",
+                "boolean",
+                "hex",
+                "base64",
+                "bitfield",
+                "unixtime",
+                "json",
+            ]
+        ),
+        vol.Required("name"): str,
+        vol.Optional("range"): {
+            vol.Required("min"): int,
+            vol.Required("max"): int,
+        },
+        vol.Optional("unit"): str,
+        vol.Optional("precision"): vol.Any(int, float),
+        vol.Optional("class"): str,
+        vol.Optional("optional"): True,
+        vol.Optional("persist"): False,
+        vol.Optional("hidden"): True,
+        vol.Optional("readonly"): True,
+        vol.Optional("force"): True,
+        vol.Optional("icon_priority"): int,
+        vol.Optional("mapping"): [MAPPING_SCHEMA],
+        vol.Optional("format"): [FORMAT_SCHEMA],
+    }
+)
+ENTITY_SCHEMA = vol.Schema(
+    {
+        vol.Required("entity"): vol.In(
+            [
+                "alarm_control_panel",
+                "binary_sensor",
+                "button",
+                "camera",
+                "climate",
+                "cover",
+                "event",
+                "fan",
+                "humidifier",
+                "lawn_mower",
+                "light",
+                "lock",
+                "number",
+                "remote",
+                "select",
+                "sensor",
+                "siren",
+                "switch",
+                "vacuum",
+                "water_heater",
+            ]
+        ),
+        vol.Optional("name"): str,
+        vol.Optional("class"): str,
+        vol.Optional(vol.Or("translation_key", "translation_only_key")): str,
+        vol.Optional("category"): vol.In(["config", "diagnostic"]),
+        vol.Optional("icon"): vol.Match(r"^mdi:"),
+        vol.Optional("icon_priority"): int,
+        vol.Optional("deprecated"): str,
+        vol.Optional("mode"): vol.In(["box", "slider"]),
+        vol.Required("dps"): [DP_SCHEMA],
+    }
+)
+YAML_SCHEMA = vol.Schema(
+    {
+        vol.Required("name"): str,
+        vol.Optional("legacy_type"): str,
+        vol.Optional("products"): [PRODUCT_SCHEMA],
+        vol.Required("primary_entity"): ENTITY_SCHEMA,
+        vol.Optional("secondary_entities"): [ENTITY_SCHEMA],
+    }
+)
+
 KNOWN_DPS = {
     "alarm_control_panel": {
         "required": ["alarm_state"],
@@ -342,6 +478,11 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
             if isinstance(parsed, str) or isinstance(parsed._config, str):
                 self.fail(f"unparsable yaml in {cfg}")
 
+            try:
+                YAML_SCHEMA(parsed._config)
+            except vol.MultipleInvalid as e:
+                self.fail(f"Validation error in {cfg}: {e}")
+
             self.assertIsNotNone(
                 parsed._config.get("name"),
                 f"name missing from {cfg}",
@@ -373,8 +514,10 @@ class TestDeviceConfig(IsolatedAsyncioTestCase):
 
     def test_match_quality(self):
         """Test the match_quality function."""
+
         cfg = get_config("deta_fan")
         q = cfg.match_quality({**KOGAN_HEATER_PAYLOAD, "updated_at": 0})
+
         self.assertEqual(q, 0)
         q = cfg.match_quality({**GPPH_HEATER_PAYLOAD})
         self.assertEqual(q, 0)