Przeglądaj źródła

Use HA scaling functions for fan speed and light brightness

HA 2024.1 introduced some new functions for scaling percentages and
light brightness. Using these should give standardised behaviour
compared with other integrations.

User visible changes:

- lights that do not allow brightness to be set all the way down to 1%
  will now adjust their range to use the full range available in HA.
- fan speeds scale to integers. This mostly affects the speeds
  reported by 3 speed and 6 speed fans

Developer visible changes:

- it is no longer neccesary to specify scale mappings for light
  brightness or fan speed. Since these have a fixed range in HA,
  they are automatically scaled into that range.

- TuyaDpsConfig.range now returns a (min, max) tuple compatible with
  the HA scaling functions instead of a dict with min and max items.

Issue #1444
Jason Rumney 2 lat temu
rodzic
commit
7f8210c4ed
100 zmienionych plików z 137 dodań i 275 usunięć
  1. 4 4
      custom_components/tuya_local/climate.py
  2. 4 3
      custom_components/tuya_local/devices/README.md
  3. 0 6
      custom_components/tuya_local/devices/advancedfires_1500_fireplace.yaml
  4. 1 3
      custom_components/tuya_local/devices/arlec_19speed_fan.yaml
  5. 0 2
      custom_components/tuya_local/devices/arlec_ceiling_fan_remote.yaml
  6. 1 3
      custom_components/tuya_local/devices/arlec_fan.yaml
  7. 1 4
      custom_components/tuya_local/devices/arlec_fan_light.yaml
  8. 1 3
      custom_components/tuya_local/devices/aspen_asp200_fan.yaml
  9. 1 5
      custom_components/tuya_local/devices/atomi_ceiling_fan.yaml
  10. 0 4
      custom_components/tuya_local/devices/atorch_at2pl_breaker.yaml
  11. 1 2
      custom_components/tuya_local/devices/ble_solar_light.yaml
  12. 0 2
      custom_components/tuya_local/devices/blitzwolf_bw_lt31.yaml
  13. 0 2
      custom_components/tuya_local/devices/breville_airdynamic3d_fan.yaml
  14. 0 2
      custom_components/tuya_local/devices/cadence_aroma_diffuser.yaml
  15. 3 9
      custom_components/tuya_local/devices/carro_pn04f02d_fan_light.yaml
  16. 0 6
      custom_components/tuya_local/devices/carro_smart_ceiling_fan_light.yaml
  17. 0 4
      custom_components/tuya_local/devices/casafan_ceiling_fan_light.yaml
  18. 0 2
      custom_components/tuya_local/devices/cct_lightbulb.yaml
  19. 0 3
      custom_components/tuya_local/devices/cecotec_fan_light.yaml
  20. 1 5
      custom_components/tuya_local/devices/chanfok_fan_light.yaml
  21. 0 2
      custom_components/tuya_local/devices/deta_dimmer_switch.yaml
  22. 1 3
      custom_components/tuya_local/devices/deta_fan.yaml
  23. 0 2
      custom_components/tuya_local/devices/dimming_lightbulb.yaml
  24. 1 3
      custom_components/tuya_local/devices/djive_arc_fan.yaml
  25. 0 1
      custom_components/tuya_local/devices/dreamlight_led_strip.yaml
  26. 1 5
      custom_components/tuya_local/devices/fanco_ecosilentdeluxe.yaml
  27. 0 2
      custom_components/tuya_local/devices/feit_dimmer.yaml
  28. 0 2
      custom_components/tuya_local/devices/galaxy_projector_light.yaml
  29. 0 2
      custom_components/tuya_local/devices/ge_jasco_ultra_pro_toggle_dimmer_v2.yaml
  30. 1 3
      custom_components/tuya_local/devices/goldair_101cm_tower_fan.yaml
  31. 2 3
      custom_components/tuya_local/devices/goldair_fan.yaml
  32. 1 3
      custom_components/tuya_local/devices/goldair_platinum_tower_fan.yaml
  33. 0 2
      custom_components/tuya_local/devices/hdmi_sync_light.yaml
  34. 2 3
      custom_components/tuya_local/devices/immax_neo_light_vento.yaml
  35. 1 5
      custom_components/tuya_local/devices/ledkia_fan_light.yaml
  36. 1 3
      custom_components/tuya_local/devices/lexy_f501_fan.yaml
  37. 0 2
      custom_components/tuya_local/devices/loycco_sound_nightlight.yaml
  38. 0 2
      custom_components/tuya_local/devices/lytmi_hdmisync_backlight.yaml
  39. 0 2
      custom_components/tuya_local/devices/mantra_fan.yaml
  40. 0 1
      custom_components/tuya_local/devices/marpou_ceiling_lamp_ledlight.yaml
  41. 0 2
      custom_components/tuya_local/devices/modernflames_orion_fireplace.yaml
  42. 0 2
      custom_components/tuya_local/devices/moes_dimmer.yaml
  43. 0 2
      custom_components/tuya_local/devices/moes_star_projector.yaml
  44. 0 2
      custom_components/tuya_local/devices/moesgo_dimmer.yaml
  45. 0 2
      custom_components/tuya_local/devices/momcozy_white_noise_machine.yaml
  46. 0 2
      custom_components/tuya_local/devices/momcozy_white_noise_machine_v2.yaml
  47. 0 2
      custom_components/tuya_local/devices/mrc_magnum_floorheater.yaml
  48. 0 2
      custom_components/tuya_local/devices/ovlaim_ceiling_fan_light.yaml
  49. 0 2
      custom_components/tuya_local/devices/pir_rgbcw_light.yaml
  50. 0 2
      custom_components/tuya_local/devices/pir_spotlight.yaml
  51. 0 2
      custom_components/tuya_local/devices/reiga_52_fan_light.yaml
  52. 0 1
      custom_components/tuya_local/devices/rgbcw_lightbulb.yaml
  53. 0 2
      custom_components/tuya_local/devices/rgbw_lightbulbv2.yaml
  54. 0 2
      custom_components/tuya_local/devices/simple_rgbcw_lightbulb.yaml
  55. 1 3
      custom_components/tuya_local/devices/skyfan_dc_fan.yaml
  56. 1 5
      custom_components/tuya_local/devices/skyfan_fan_light.yaml
  57. 0 1
      custom_components/tuya_local/devices/smart_led_strip.yaml
  58. 0 2
      custom_components/tuya_local/devices/soleusair_air_purifier.yaml
  59. 0 2
      custom_components/tuya_local/devices/space_dog_music_lamp.yaml
  60. 1 3
      custom_components/tuya_local/devices/stirling_fs140dc_fan.yaml
  61. 0 2
      custom_components/tuya_local/devices/sulion_ceiling_fan.yaml
  62. 0 1
      custom_components/tuya_local/devices/t5e_wf_thermostat.yaml
  63. 0 2
      custom_components/tuya_local/devices/tampa_led_system.yaml
  64. 4 4
      custom_components/tuya_local/devices/tesla_air_purifier_pro.yaml
  65. 1 1
      custom_components/tuya_local/devices/tmwf02_fan.yaml
  66. 1 2
      custom_components/tuya_local/devices/treatlife_ds03_fan_light.yaml
  67. 0 4
      custom_components/tuya_local/devices/treatlife_dual_plugin_dimmer.yaml
  68. 1 6
      custom_components/tuya_local/devices/tv_backlights.yaml
  69. 0 2
      custom_components/tuya_local/devices/ustellar_ut99911_rgb.yaml
  70. 0 2
      custom_components/tuya_local/devices/wf39m_dimmer_smartplug.yaml
  71. 0 4
      custom_components/tuya_local/devices/wf520d_wifi_dual_touch_dimmer.yaml
  72. 1 3
      custom_components/tuya_local/devices/windcalm_fan.yaml
  73. 1 5
      custom_components/tuya_local/devices/windcalm_fan_with_light.yaml
  74. 1 1
      custom_components/tuya_local/devices/yidi_fan_light_switch.yaml
  75. 0 2
      custom_components/tuya_local/devices/yx316wifi_aroma_diffuser.yaml
  76. 0 2
      custom_components/tuya_local/devices/zigbee_smart_bulb.yaml
  77. 19 3
      custom_components/tuya_local/fan.py
  78. 5 7
      custom_components/tuya_local/helpers/device_config.py
  79. 2 2
      custom_components/tuya_local/humidifier.py
  80. 19 2
      custom_components/tuya_local/light.py
  81. 2 2
      custom_components/tuya_local/number.py
  82. 2 2
      custom_components/tuya_local/water_heater.py
  83. 1 1
      hacs.json
  84. 1 1
      tests/devices/test_arlec_fan_light.py
  85. 4 4
      tests/devices/test_aspen_adv200_fan.py
  86. 2 2
      tests/devices/test_beca_bhp6000_thermostat.py
  87. 2 2
      tests/devices/test_betterlife_bl1500_heater.py
  88. 2 2
      tests/devices/test_deta_fan.py
  89. 2 2
      tests/devices/test_digoo_dgsp01_dual_nightlight_switch.py
  90. 2 2
      tests/devices/test_eberg_cooly_c35hd.py
  91. 2 2
      tests/devices/test_eberg_qubo_q40hd_heatpump.py
  92. 2 2
      tests/devices/test_eurom_600_heater.py
  93. 3 3
      tests/devices/test_eurom_600v2_heater.py
  94. 2 2
      tests/devices/test_eurom_601_heater.py
  95. 2 2
      tests/devices/test_fersk_vind_2_climate.py
  96. 2 2
      tests/devices/test_goldair_geco_heater.py
  97. 10 10
      tests/devices/test_goldair_gpph_heater.py
  98. 2 2
      tests/devices/test_hydrotherm_dynamicx8.py
  99. 3 3
      tests/devices/test_immax_neo_light_vento.py
  100. 2 2
      tests/devices/test_kogan_kawfpac09ya_airconditioner.py

+ 4 - 4
custom_components/tuya_local/climate.py

@@ -209,7 +209,7 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
             r = self._temp_low_dps.range(self._device)
         else:
             r = self._temperature_dps.range(self._device)
-        return DEFAULT_MIN_TEMP if r is None else r["min"]
+        return DEFAULT_MIN_TEMP if r is None else r[0]
 
     @property
     def max_temp(self):
@@ -226,7 +226,7 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
             r = self._temp_high_dps.range(self._device)
         else:
             r = self._temperature_dps.range(self._device)
-        return DEFAULT_MAX_TEMP if r is None else r["max"]
+        return DEFAULT_MAX_TEMP if r is None else r[1]
 
     async def async_set_temperature(self, **kwargs):
         """Set new target temperature."""
@@ -284,7 +284,7 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         if self._humidity_dps is None:
             return None
         r = self._humidity_dps.range(self._device)
-        return DEFAULT_MIN_HUMIDITY if r is None else r["min"]
+        return DEFAULT_MIN_HUMIDITY if r is None else r[0]
 
     @property
     def max_humidity(self):
@@ -292,7 +292,7 @@ class TuyaLocalClimate(TuyaLocalEntity, ClimateEntity):
         if self._humidity_dps is None:
             return None
         r = self._humidity_dps.range(self._device)
-        return DEFAULT_MAX_HUMIDITY if r is None else r["max"]
+        return DEFAULT_MAX_HUMIDITY if r is None else r[1]
 
     async def async_set_humidity(self, humidity: int):
         if self._humidity_dps is None:

+ 4 - 3
custom_components/tuya_local/devices/README.md

@@ -582,8 +582,9 @@ Either **position** or **open** should be specified.
 - **switch** (optional, boolean): a dp to control the power state of the fan
 - **preset_mode** (optional, mapping of strings): a dp to control different modes of the fan.
    Values `"off", low, medium, high` used to be handled specially by HA as deprecated speed aliases. If these are the only "presets", consider mapping them as **speed** values instead, as voice assistants will respond to phrases like "turn the fan up/down" for speed.
-- **speed** (optional, number 0-100): a dp to control the speed of the fan (%).
-    scale and step can be used to convert smaller ranges to percentages, or a mapping for discrete values.
+- **speed** (optional, number): a dp to control the speed of the fan (%).
+    if a range is supplied, it will be automatically scaled to the 0-100 range.
+    if a mapping is used for dicrete steps, the values must be mapped within that range.
 - **oscillate** (optional, boolean): a dp to control whether the fan will oscillate or not.
 - **direction** (optional, string): a dp to control the spin direction of the fan.
    Valid values are `forward, reverse`.
@@ -603,7 +604,7 @@ Humidifer can also cover dehumidifiers (use class to specify which).
 
 ### `light`
 - **switch** (optional, boolean): a dp to control the on/off state of the light
-- **brightness** (optional, number 0-255): a dp to control the dimmer if available.
+- **brightness** (optional, number): a dp to control the dimmer if available.  If a range is provided, the value will be automatically scaled into the 0-255 range for HA, so there is no need to provide a scale. If there is a fixed list of mappings, the values should be between 0 (off) and 255 (full brightness). If there is no switch dp, a brightness of 0 will be sent to turn the light off.
 - **color_temp** (optional, number): a dp to control the color temperature if available. See `target_range` above for mapping Tuya's range into Kelvin.
 
 - **rgbhsv** (optional, hex): a dp to control the color of the light, using encoded RGB and HSV values. The `format` field names recognized for decoding this field are `r`, `g`, `b`, `h`, `s`, `v`.

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

@@ -105,8 +105,6 @@ secondary_entities:
           min: 0
           max: 100
         optional: true
-        mapping:
-          - scale: 0.392
       - id: 109
         name: rgbhsv
         type: base64
@@ -173,8 +171,6 @@ secondary_entities:
         range:
           min: 0
           max: 100
-        mapping:
-          - scale: 0.392
       - id: 110
         name: rgbhsv
         type: base64
@@ -219,8 +215,6 @@ secondary_entities:
         range:
           min: 0
           max: 100
-        mapping:
-          - scale: 0.392
       - id: 111
         name: rgbhsv
         type: base64

+ 1 - 3
custom_components/tuya_local/devices/arlec_19speed_fan.yaml

@@ -23,10 +23,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 19
-      mapping:
-        - scale: 0.19
     - id: 5
       name: oscillate
       type: boolean

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

@@ -14,8 +14,6 @@ primary_entity:
       range:
         min: 1
         max: 3
-      mapping:
-        - scale: 0.03
 secondary_entities:
   - entity: light
     dps:

+ 1 - 3
custom_components/tuya_local/devices/arlec_fan.yaml

@@ -10,10 +10,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 4
       name: direction
       type: string

+ 1 - 4
custom_components/tuya_local/devices/arlec_fan_light.yaml

@@ -10,10 +10,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 4
       name: direction
       type: string
@@ -39,7 +37,6 @@ secondary_entities:
           max: 100
         mapping:
           - step: 2
-            scale: 0.392
       - id: 11
         type: integer
         name: color_temp

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

@@ -21,10 +21,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 3
-      mapping:
-        - scale: 0.03
     - id: 101
       type: boolean
       name: preset_mode

+ 1 - 5
custom_components/tuya_local/devices/atomi_ceiling_fan.yaml

@@ -21,10 +21,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 3
-      mapping:
-        - scale: 0.03
     - id: 71
       type: string
       name: unknown_71
@@ -47,8 +45,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 23
         name: color_temp
         type: integer

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

@@ -148,8 +148,6 @@ secondary_entities:
         range:
           min: 1
           max: 9
-        mapping:
-          - scale: 0.0353
   - entity: light
     name: Display standby
     category: config
@@ -160,8 +158,6 @@ secondary_entities:
         range:
           min: 0
           max: 9
-        mapping:
-          - scale: 0.0353
   - entity: number
     name: Standby delay
     category: config

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

@@ -27,8 +27,7 @@ primary_entity:
         min: 10
         max: 1000
       mapping:
-        - scale: 3.92
-          constraint: standby
+        - constraint: standby
           conditions:
             - dps_val: true
               value_redirect: standby_brightness

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

@@ -28,8 +28,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 24
       name: rgbhsv
       type: hex

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

@@ -14,8 +14,6 @@ primary_entity:
       range:
         min: 0
         max: 8
-      mapping:
-        - scale: 0.08
     - id: 2
       type: string
       name: preset_mode

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

@@ -41,8 +41,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       # 10: rgbhsv, but not present in log and no color_mode to select it,
       #     so probably a doc error
       - id: 105

+ 3 - 9
custom_components/tuya_local/devices/carro_pn04f02d_fan_light.yaml

@@ -20,8 +20,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 28
       type: string
       name: control_data
@@ -35,10 +33,6 @@ secondary_entities:
       - id: 62
         type: integer
         name: speed
-        mapping:
-          - dps_val: 1
-            value: 33
-          - dps_val: 2
-            value: 66
-          - dps_val: 3
-            value: 100
+        range:
+          min: 1
+          max: 3

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 1
         max: 10
-      mapping:
-        - scale: 0.1
     - id: 103
       type: string
       name: direction
@@ -57,8 +55,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
   - entity: light
     name: Daylight light
     dps:
@@ -71,5 +67,3 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 8
       type: string
       name: direction
@@ -42,8 +40,6 @@ secondary_entities:
         range:
           min: 10
           max: 100
-        mapping:
-          - scale: 0.392
       - id: 17
         # 17 is listed as color_temp, and reported by the device, but light
         # is fixed 3000K light

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

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

@@ -26,9 +26,6 @@ primary_entity:
     - id: 3
       name: speed
       type: string
-      range:
-        min: 1
-        max: 6
       mapping:
         - dps_val: "1"
           value: 17

+ 1 - 5
custom_components/tuya_local/devices/chanfok_fan_light.yaml

@@ -21,10 +21,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 63
       type: string
       name: direction
@@ -43,8 +41,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 23
         name: color_temp
         type: integer

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

@@ -14,8 +14,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 secondary_entities:
   - entity: number
     name: Minimum brightness

+ 1 - 3
custom_components/tuya_local/devices/deta_fan.yaml

@@ -9,10 +9,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 3
-      mapping:
-        - scale: 0.03
     - id: 102
       type: integer
       name: timer

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

@@ -18,8 +18,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 secondary_entities:
   - entity: number
     name: Timer

+ 1 - 3
custom_components/tuya_local/devices/djive_arc_fan.yaml

@@ -27,10 +27,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 9
-      mapping:
-        - scale: 0.09
     - id: 5
       type: boolean
       name: oscillate

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

@@ -30,7 +30,6 @@ primary_entity:
       mapping:
         - dps_val: null
           value: 0
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

+ 1 - 5
custom_components/tuya_local/devices/fanco_ecosilentdeluxe.yaml

@@ -12,10 +12,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 8
       name: direction
       type: string
@@ -31,8 +29,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 17
         name: color_temp
         type: integer

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

@@ -18,8 +18,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 3
       # advisory only, the integration does not actually use this, setting it
       # does not seem to work, so probably determined by bulb type

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

@@ -60,8 +60,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 51
         name: effect
         type: string

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

@@ -17,8 +17,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 secondary_entities:
   - entity: select
     name: Bulb Type

+ 1 - 3
custom_components/tuya_local/devices/goldair_101cm_tower_fan.yaml

@@ -23,10 +23,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 3
-      mapping:
-        - scale: 0.03
     - id: 5
       type: boolean
       name: oscillate

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

@@ -11,11 +11,10 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 12
       mapping:
-        - scale: 0.12
-          constraint: preset_mode
+        - constraint: preset_mode
           conditions:
             - dps_val: nature
               step: 4

+ 1 - 3
custom_components/tuya_local/devices/goldair_platinum_tower_fan.yaml

@@ -25,10 +25,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 3
-      mapping:
-        - scale: 0.03
     - id: 4
       type: string
       name: oscillate

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 0
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 24
       type: hex
       name: rgbhsv

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

@@ -25,11 +25,10 @@ primary_entity:
       type: integer
       category: config
       range:
-        min: 0
+        min: 1
         max: 6
       mapping:
-        - scale: 0.06
-          constraint: preset_mode
+        - constraint: preset_mode
           conditions:
             - dps_val: nature
               step: 5

+ 1 - 5
custom_components/tuya_local/devices/ledkia_fan_light.yaml

@@ -13,10 +13,8 @@ primary_entity:
       name: speed
       optional: true
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 63
       type: string
       name: direction
@@ -38,8 +36,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 23
         type: integer
         name: color_temp

+ 1 - 3
custom_components/tuya_local/devices/lexy_f501_fan.yaml

@@ -43,10 +43,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 15
-      mapping:
-        - scale: 0.15
 secondary_entities:
   - entity: light
     category: config

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

@@ -31,8 +31,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 5
       name: rgbhsv
       type: hex

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

@@ -16,8 +16,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 24
       name: rgbhsv
       type: hex

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

@@ -129,8 +129,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 11
         name: color_temp
         type: integer

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

@@ -31,7 +31,6 @@ primary_entity:
       mapping:
         - dps_val: null
           value: 0
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

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

@@ -280,8 +280,6 @@ secondary_entities:
         range:
           min: 0
           max: 100
-        mapping:
-          - scale: 0.392
       - id: 109
         name: effect
         type: string

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

@@ -11,8 +11,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 13
       name: work_mode
       type: string

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

@@ -56,8 +56,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
   - entity: number
     name: Star rotation speed
     category: config

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

@@ -14,8 +14,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 secondary_entities:
   - entity: number
     name: Minimum brightness

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

@@ -27,8 +27,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 5
       name: rgbhsv
       type: hex

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

@@ -27,8 +27,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 5
       name: rgbhsv
       type: hex

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

@@ -320,8 +320,6 @@ secondary_entities:
         range:
           min: 1
           max: 10
-        mapping:
-          - scale: 0.0392
   - entity: number
     name: Display timeout
     icon: "mdi:television-ambient-light"

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

@@ -50,8 +50,6 @@ secondary_entities:
         range:
           min: 0
           max: 100
-        mapping:
-          - scale: 0.392
       - id: 17
         name: color_temp
         type: integer

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

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

@@ -19,8 +19,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 8
       type: string
       name: direction

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

@@ -38,7 +38,6 @@ primary_entity:
       mapping:
         - dps_val: null
           value: 0
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

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

@@ -25,8 +25,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 24
       name: rgbhsv
       type: hex

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

@@ -19,8 +19,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

+ 1 - 3
custom_components/tuya_local/devices/skyfan_dc_fan.yaml

@@ -22,10 +22,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 5
-      mapping:
-        - scale: 0.05
     - id: 8
       type: string
       name: direction

+ 1 - 5
custom_components/tuya_local/devices/skyfan_fan_light.yaml

@@ -23,10 +23,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 5
-      mapping:
-        - scale: 0.05
     - id: 8
       type: string
       name: direction
@@ -42,8 +40,6 @@ secondary_entities:
         range:
           min: 1
           max: 5
-        mapping:
-          - scale: 0.0196
       - id: 19
         name: color_temp
         type: string

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

@@ -30,7 +30,6 @@ primary_entity:
       mapping:
         - dps_val: null
           value: 0
-        - scale: 3.92
     - id: 23
       name: color_temp
       type: integer

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

@@ -18,8 +18,6 @@ primary_entity:
       range:
         min: 1
         max: 5
-      mapping:
-        - scale: 0.05
     - id: 3
       name: preset_mode
       type: string

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

@@ -29,8 +29,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 
     # Color
     # sample values: 00f003e803e8, 00b403e803e8, 000003e803e8, 00f003e803e8

+ 1 - 3
custom_components/tuya_local/devices/stirling_fs140dc_fan.yaml

@@ -20,10 +20,8 @@ primary_entity:
       name: speed
       type: integer
       range:
-        min: 0
+        min: 1
         max: 15
-      mapping:
-        - scale: 0.15
     - id: 5
       name: oscillate
       type: boolean

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

@@ -12,8 +12,6 @@ primary_entity:
       range:
         min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 54
       type: string
       name: direction

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

@@ -380,7 +380,6 @@ secondary_entities:
           max: 100
         mapping:
           - step: 10
-            scale: 0.392
   - entity: binary_sensor
     name: Fault
     category: diagnostic

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

@@ -17,8 +17,6 @@ primary_entity:
       range:
         min: 0
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 4
       name: color_temp
       type: integer

+ 4 - 4
custom_components/tuya_local/devices/tesla_air_purifier_pro.yaml

@@ -23,13 +23,13 @@ primary_entity:
       type: string
       mapping:
         - dps_val: "sleep"
-          value: "sleep"
+          value: 25
         - dps_val: "low"
-          value: "low"
+          value: 50
         - dps_val: "mid"
-          value: "mid"
+          value: 75
         - dps_val: "high"
-          value: "high"
+          value: 100
 secondary_entities:
   - entity: light
     category: config

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

@@ -12,7 +12,7 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 100
 secondary_entities:
   - entity: number

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

@@ -48,5 +48,4 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
+

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

@@ -16,8 +16,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 3
       name: min_brightness
       type: integer
@@ -46,8 +44,6 @@ secondary_entities:
         range:
           min: 0
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 9
         name: min_brightness
         type: integer

+ 1 - 6
custom_components/tuya_local/devices/tv_backlights.yaml

@@ -17,8 +17,7 @@ primary_entity:
         min: 0
         max: 100
       mapping:
-        - scale: 0.392
-          constraint: video_mode
+        - constraint: video_mode
           conditions:
             - dps_val: ambi_mode
               value_redirect: scene_brightness
@@ -31,8 +30,6 @@ primary_entity:
       range:
         min: 0
         max: 100
-      mapping:
-        - scale: 0.392
     - id: 112
       hidden: true
       name: color_brightness
@@ -40,8 +37,6 @@ primary_entity:
       range:
         min: 0
         max: 100
-      mapping:
-        - scale: 0.392
     - id: 111
       name: rgbhsv
       type: hex

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

@@ -16,8 +16,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 23
       type: integer
       name: color_temp

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

@@ -14,8 +14,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 secondary_entities:
   - entity: select
     name: Light type

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

@@ -12,8 +12,6 @@ primary_entity:
       range:
         min: 10
         max: 1000
-      mapping:
-        - scale: 3.92
 secondary_entities:
   - entity: light
     name: Dimmer 2
@@ -27,8 +25,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
   - entity: number
     name: Minimum brightness 1
     category: config

+ 1 - 3
custom_components/tuya_local/devices/windcalm_fan.yaml

@@ -9,10 +9,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 63
       type: string
       name: direction

+ 1 - 5
custom_components/tuya_local/devices/windcalm_fan_with_light.yaml

@@ -9,10 +9,8 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 6
-      mapping:
-        - scale: 0.06
     - id: 63
       type: string
       name: direction
@@ -28,8 +26,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 23
         name: color_temp
         type: integer

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

@@ -12,7 +12,7 @@ primary_entity:
       type: integer
       name: speed
       range:
-        min: 0
+        min: 1
         max: 100
 secondary_entities:
   - entity: light

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

@@ -62,8 +62,6 @@ secondary_entities:
         range:
           min: 10
           max: 1000
-        mapping:
-          - scale: 3.92
       - id: 10
         name: rgbhsv
         type: hex

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

@@ -17,8 +17,6 @@ primary_entity:
       range:
         min: 0
         max: 1000
-      mapping:
-        - scale: 3.92
     - id: 4
       name: color_temp
       optional: true

+ 19 - 3
custom_components/tuya_local/fan.py

@@ -5,7 +5,10 @@ import logging
 from typing import Any
 
 from homeassistant.components.fan import FanEntity, FanEntityFeature
-
+from homeassistant.util.percentage import (
+    percentage_to_ranged_value,
+    ranged_value_to_percentage,
+)
 from .device import TuyaLocalDevice
 from .helpers.config import async_tuya_setup_platform
 from .helpers.device_config import TuyaEntityConfig
@@ -82,6 +85,10 @@ class TuyaLocalFan(TuyaLocalEntity, FanEntity):
             }
 
         if percentage is not None and self._speed_dps:
+            r = self._speed_dps.range(self._device)
+            if r:
+                percentage = percentage_to_ranged_value(r, percentage)
+
             settings = {
                 **settings,
                 **self._speed_dps.get_values_to_set(self._device, percentage),
@@ -106,7 +113,11 @@ class TuyaLocalFan(TuyaLocalEntity, FanEntity):
         """Return the currently set percentage."""
         if self._speed_dps is None:
             return None
-        return self._speed_dps.get_value(self._device)
+        r = self._speed_dps.range(self._device)
+        val = self._speed_dps.get_value(self._device)
+        if r:
+            val = ranged_value_to_percentage(r, val)
+        return val
 
     @property
     def percentage_step(self):
@@ -115,7 +126,9 @@ class TuyaLocalFan(TuyaLocalEntity, FanEntity):
             return None
         if self._speed_dps.values(self._device):
             return 100 / len(self._speed_dps.values(self._device))
-        return self._speed_dps.step(self._device)
+        r = self._speed_dps.range(self._device)
+        scale = 100 / r[1] if r else 1.0
+        return self._speed_dps.step(self._device) * scale
 
     @property
     def speed_count(self):
@@ -140,6 +153,9 @@ class TuyaLocalFan(TuyaLocalEntity, FanEntity):
                 self._speed_dps.values(self._device),
                 key=lambda x: abs(x - percentage),
             )
+        elif self._speed_dps.range(self._device):
+            r = self._speed_dps.range(self._device)
+            percentage = percentage_to_ranged_value(r, percentage)
 
         values_to_set = self._speed_dps.get_values_to_set(self._device, percentage)
         if not self.is_on and self._switch_dps:

+ 5 - 7
custom_components/tuya_local/helpers/device_config.py

@@ -42,9 +42,7 @@ def _typematch(vtype, value):
 
 def _scale_range(r, s):
     "Scale range r by factor s"
-    if s == 1:
-        return r
-    return {"min": r["min"] / s, "max": r["max"] / s}
+    return (r["min"] / s, r["max"] / s)
 
 
 _unsigned_fmts = {
@@ -923,13 +921,13 @@ class TuyaDpsConfig:
 
         r = self.range(device, scaled=False)
         if r and isinstance(result, Number):
-            mn = r["min"]
-            mx = r["max"]
+            mn = r[0]
+            mx = r[1]
             if round(result) < mn or round(result) > mx:
                 # Output scaled values in the error message
                 r = self.range(device, scaled=True)
-                mn = r["min"]
-                mx = r["max"]
+                mn = r[0]
+                mx = r[1]
                 raise ValueError(f"{self.name} ({value}) must be between {mn} and {mx}")
 
         if mask and isinstance(result, Number):

+ 2 - 2
custom_components/tuya_local/humidifier.py

@@ -103,7 +103,7 @@ class TuyaLocalHumidifier(TuyaLocalEntity, HumidifierEntity):
         if self._humidity_dp is None:
             return None
         r = self._humidity_dp.range(self._device)
-        return DEFAULT_MIN_HUMIDITY if r is None else r["min"]
+        return DEFAULT_MIN_HUMIDITY if r is None else r[0]
 
     @property
     def max_humidity(self):
@@ -111,7 +111,7 @@ class TuyaLocalHumidifier(TuyaLocalEntity, HumidifierEntity):
         if self._humidity_dp is None:
             return None
         r = self._humidity_dp.range(self._device)
-        return DEFAULT_MAX_HUMIDITY if r is None else r["max"]
+        return DEFAULT_MAX_HUMIDITY if r is None else r[1]
 
     async def async_set_humidity(self, humidity):
         if self._humidity_dp is None:

+ 19 - 2
custom_components/tuya_local/light.py

@@ -150,7 +150,11 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
     @property
     def _white_brightness(self):
         if self._brightness_dps:
-            return self._brightness_dps.get_value(self._device)
+            r = self._brightness_dps.range(self._device)
+            val = self._brightness_dps.get_value(self._device)
+            if r:
+                val = color_util.value_to_brightness(r, val)
+            return val
 
     @property
     def _unpacked_rgbhsv(self):
@@ -237,6 +241,10 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                     "Setting brightness via WHITE parameter to %d",
                     bright,
                 )
+                r = self._brightness_dps.range(self._device)
+                if r:
+                    bright = color_util.brightness_to_value(r, bright)
+
                 settings = {
                     **settings,
                     **self._brightness_dps.get_values_to_set(
@@ -360,6 +368,10 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
         ):
             bright = params.get(ATTR_BRIGHTNESS)
             _LOGGER.debug("Setting brightness to %s", bright)
+            r = self._brightness_dps.range(self._device)
+            if r:
+                bright = color_util.brightness_to_value(r, bright)
+
             settings = {
                 **settings,
                 **self._brightness_dps.get_values_to_set(
@@ -397,8 +409,13 @@ class TuyaLocalLight(TuyaLocalEntity, LightEntity):
                     self._device, True
                 )
         elif self._brightness_dps and not self.is_on:
+            bright = 255
+            r = self._brightness_dps.range(self._device)
+            if r:
+                bright = color_util.brightness_to_value(r, bright)
+
             settings = settings | self._brightness_dps.get_values_to_set(
-                self._device, 255
+                self._device, bright
             )
 
         if settings:

+ 2 - 2
custom_components/tuya_local/number.py

@@ -71,14 +71,14 @@ class TuyaLocalNumber(TuyaLocalEntity, NumberEntity):
         if self._min_dps is not None:
             return self._min_dps.get_value(self._device)
         r = self._value_dps.range(self._device)
-        return DEFAULT_MIN_VALUE if r is None else r["min"]
+        return DEFAULT_MIN_VALUE if r is None else r[0]
 
     @property
     def native_max_value(self):
         if self._max_dps is not None:
             return self._max_dps.get_value(self._device)
         r = self._value_dps.range(self._device)
-        return DEFAULT_MAX_VALUE if r is None else r["max"]
+        return DEFAULT_MAX_VALUE if r is None else r[1]
 
     @property
     def native_step(self):

+ 2 - 2
custom_components/tuya_local/water_heater.py

@@ -214,7 +214,7 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
 
         if self._temperature_dps:
             r = self._temperature_dps.range(self._device)
-            return r.get("min")
+            return r[0]
 
     @property
     def max_temp(self):
@@ -225,7 +225,7 @@ class TuyaLocalWaterHeater(TuyaLocalEntity, WaterHeaterEntity):
 
         if self._temperature_dps:
             r = self._temperature_dps.range(self._device)
-            return r.get("max")
+            return r[1]
 
     async def async_turn_on(self):
         """

+ 1 - 1
hacs.json

@@ -1,5 +1,5 @@
 {
   "name": "Tuya Local",
   "render_readme": true,
-  "homeassistant": "2023.9.0"
+  "homeassistant": "2024.1.0"
 }

+ 1 - 1
tests/devices/test_arlec_fan_light.py

@@ -132,7 +132,7 @@ class TestArlecFan(SwitchableTests, BasicSelectTests, TuyaDeviceTestCase):
 
     def test_light_brightness(self):
         self.dps[BRIGHTNESS_DPS] = 50
-        self.assertAlmostEqual(self.light.brightness, 128, 0)
+        self.assertAlmostEqual(self.light.brightness, 129, 0)
 
     def test_light_color_temp(self):
         self.dps[COLORTEMP_DPS] = 70

+ 4 - 4
tests/devices/test_aspen_adv200_fan.py

@@ -47,8 +47,8 @@ class TestAspenASP200Fan(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.climate,
-            min=40,
-            max=95,
+            min=40.0,
+            max=95.0,
         )
         self.mark_secondary(["light_display"])
 
@@ -94,9 +94,9 @@ class TestAspenASP200Fan(
 
     def test_fan_speed(self):
         self.dps[SPEED_DPS] = "1"
-        self.assertAlmostEqual(self.subject.percentage, 33.3, 1)
+        self.assertAlmostEqual(self.subject.percentage, 33, 0)
         self.dps[SPEED_DPS] = "2"
-        self.assertAlmostEqual(self.subject.percentage, 66.7, 1)
+        self.assertAlmostEqual(self.subject.percentage, 66, 0)
         self.dps[SPEED_DPS] = "3"
         self.assertEqual(self.subject.percentage, 100)
 

+ 2 - 2
tests/devices/test_beca_bhp6000_thermostat.py

@@ -34,8 +34,8 @@ class TestBecaBHP6000Thermostat(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=40,
-            max=95,
+            min=40.0,
+            max=95.0,
         )
         self.setUpBasicLight(LIGHT_DPS, self.entities.get("light_display"))
         self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))

+ 2 - 2
tests/devices/test_betterlife_bl1500_heater.py

@@ -33,8 +33,8 @@ class TestBetterlifeBL1500Heater(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=15,
-            max=30,
+            min=15.0,
+            max=30.0,
         )
         self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
         self.setUpBasicSelect(

+ 2 - 2
tests/devices/test_deta_fan.py

@@ -35,7 +35,7 @@ class TestDetaFan(
 
     def test_speed(self):
         self.dps[SPEED_DPS] = "1"
-        self.assertAlmostEqual(self.subject.percentage, 33.3, 1)
+        self.assertAlmostEqual(self.subject.percentage, 33, 0)
 
     def test_speed_step(self):
         self.assertAlmostEqual(self.subject.percentage_step, 33.3, 1)
@@ -46,7 +46,7 @@ class TestDetaFan(
 
     async def test_auto_stringify_speed(self):
         self.dps[SPEED_DPS] = "1"
-        self.assertAlmostEqual(self.subject.percentage, 33.3, 1)
+        self.assertAlmostEqual(self.subject.percentage, 33, 0)
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: "2"}):
             await self.subject.async_set_percentage(66.7)
 

+ 2 - 2
tests/devices/test_digoo_dgsp01_dual_nightlight_switch.py

@@ -43,7 +43,7 @@ class TestDigooNightlightSwitch(BasicSwitchTests, TuyaDeviceTestCase):
     def test_light_brightness(self):
         self.dps[BRIGHTNESS_DPS] = 45
         self.dps[COLORMODE_DPS] = "white"
-        self.assertEqual(self.light.brightness, 45)
+        self.assertEqual(self.light.brightness, 23)
 
     def test_light_color_mode(self):
         self.dps[COLORMODE_DPS] = "colour"
@@ -126,7 +126,7 @@ class TestDigooNightlightSwitch(BasicSwitchTests, TuyaDeviceTestCase):
         async with assert_device_properties_set(
             self.light._device,
             {
-                BRIGHTNESS_DPS: 128,
+                BRIGHTNESS_DPS: 140,
             },
         ):
             await self.light.async_turn_on(brightness=128)

+ 2 - 2
tests/devices/test_eberg_cooly_c35hd.py

@@ -41,8 +41,8 @@ class TestEbergCoolyC35HDHeatpump(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=13,
-            max=32,
+            min=13.0,
+            max=32.0,
         )
         self.setUpBasicSelect(
             UNIT_DPS,

+ 2 - 2
tests/devices/test_eberg_qubo_q40hd_heatpump.py

@@ -41,8 +41,8 @@ class TestEbergQuboQ40HDHeatpump(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=17,
-            max=30,
+            min=17.0,
+            max=30.0,
         )
         self.setUpBasicNumber(
             TIMER_DPS,

+ 2 - 2
tests/devices/test_eurom_600_heater.py

@@ -25,8 +25,8 @@ class TestEurom600Heater(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=0,
-            max=37,
+            min=0.0,
+            max=37.0,
         )
         self.setUpBasicBinarySensor(
             ERROR_DPS,

+ 3 - 3
tests/devices/test_eurom_600v2_heater.py

@@ -14,7 +14,7 @@ CURRENTTEMP_DPS = "5"
 ERROR_DPS = "7"
 
 
-class TestEurom600Heater(
+class TestEurom600v2Heater(
     BasicBinarySensorTests, TargetTemperatureTests, TuyaDeviceTestCase
 ):
     __test__ = True
@@ -25,8 +25,8 @@ class TestEurom600Heater(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=0,
-            max=37,
+            min=0.0,
+            max=37.0,
         )
         self.setUpBasicBinarySensor(
             ERROR_DPS,

+ 2 - 2
tests/devices/test_eurom_601_heater.py

@@ -31,8 +31,8 @@ class TestEurom601Heater(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=0,
-            max=37,
+            min=0.0,
+            max=37.0,
         )
         self.setUpBasicBinarySensor(
             ERROR_DPS,

+ 2 - 2
tests/devices/test_fersk_vind_2_climate.py

@@ -36,8 +36,8 @@ class TestFerskVind2Climate(TargetTemperatureTests, TuyaDeviceTestCase):
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=16,
-            max=32,
+            min=16.0,
+            max=32.0,
         )
 
     def test_supported_features(self):

+ 2 - 2
tests/devices/test_goldair_geco_heater.py

@@ -33,8 +33,8 @@ class TestGoldairGECOHeater(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=15,
-            max=35,
+            min=15.0,
+            max=35.0,
         )
         self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
         self.setUpBasicNumber(

+ 10 - 10
tests/devices/test_goldair_gpph_heater.py

@@ -49,8 +49,8 @@ class TestGoldairHeater(
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=5,
-            max=35,
+            min=5.0,
+            max=35.0,
         )
         self.setUpBasicLight(LIGHT_DPS, self.entities.get("light_display"))
         self.setUpBasicLock(LOCK_DPS, self.entities.get("lock_child_lock"))
@@ -129,23 +129,23 @@ class TestGoldairHeater(
 
     def test_minimum_temperature(self):
         self.dps[PRESET_DPS] = "C"
-        self.assertEqual(self.subject.min_temp, 5)
+        self.assertEqual(self.subject.min_temp, 5.0)
 
         self.dps[PRESET_DPS] = "ECO"
-        self.assertEqual(self.subject.min_temp, 5)
+        self.assertEqual(self.subject.min_temp, 5.0)
 
         self.dps[PRESET_DPS] = "AF"
-        self.assertIs(self.subject.min_temp, 5)
+        self.assertEqual(self.subject.min_temp, 5.0)
 
     def test_maximum_target_temperature(self):
         self.dps[PRESET_DPS] = "C"
-        self.assertEqual(self.subject.max_temp, 35)
+        self.assertEqual(self.subject.max_temp, 35.0)
 
         self.dps[PRESET_DPS] = "ECO"
-        self.assertEqual(self.subject.max_temp, 21)
+        self.assertEqual(self.subject.max_temp, 21.0)
 
         self.dps[PRESET_DPS] = "AF"
-        self.assertIs(self.subject.max_temp, 5)
+        self.assertEqual(self.subject.max_temp, 5.0)
 
     async def test_legacy_set_temperature_with_preset_mode(self):
         async with assert_device_properties_set(
@@ -179,12 +179,12 @@ class TestGoldairHeater(
         self.dps[PRESET_DPS] = "ECO"
 
         with self.assertRaisesRegex(
-            ValueError, "eco_temperature \\(4\\) must be between 5 and 21"
+            ValueError, "eco_temperature \\(4\\) must be between 5.0 and 21.0"
         ):
             await self.subject.async_set_target_temperature(4)
 
         with self.assertRaisesRegex(
-            ValueError, "eco_temperature \\(22\\) must be between 5 and 21"
+            ValueError, "eco_temperature \\(22\\) must be between 5.0 and 21.0"
         ):
             await self.subject.async_set_target_temperature(22)
 

+ 2 - 2
tests/devices/test_hydrotherm_dynamicx8.py

@@ -58,10 +58,10 @@ class TestHydrothermDynamicX8(
         self.assertEqual(self.subject.current_temperature, 55)
 
     def test_min_temp(self):
-        self.assertEqual(self.subject.min_temp, 15)
+        self.assertEqual(self.subject.min_temp, 15.0)
 
     def test_max_temp(self):
-        self.assertEqual(self.subject.max_temp, 75)
+        self.assertEqual(self.subject.max_temp, 75.0)
 
     def test_target_temperature(self):
         self.dps[TEMPERATURE_DP] = 61

+ 3 - 3
tests/devices/test_immax_neo_light_vento.py

@@ -65,13 +65,13 @@ class TestImmaxNeoLightVento(
 
     def test_speed(self):
         self.dps[SPEED_DPS] = 2
-        self.assertAlmostEqual(33.3, self.fan.percentage, 1)
+        self.assertAlmostEqual(33, self.fan.percentage, 0)
         self.dps[SPEED_DPS] = 3
         self.assertEqual(50, self.fan.percentage)
         self.dps[SPEED_DPS] = 4
-        self.assertAlmostEqual(66.7, self.fan.percentage, 1)
+        self.assertAlmostEqual(66, self.fan.percentage, 0)
         self.dps[SPEED_DPS] = 5
-        self.assertAlmostEqual(83.3, self.fan.percentage, 1)
+        self.assertAlmostEqual(83, self.fan.percentage, 0)
         self.dps[SPEED_DPS] = 6
         self.assertEqual(100, self.fan.percentage)
         self.dps[SPEED_DPS] = 0

+ 2 - 2
tests/devices/test_kogan_kawfpac09ya_airconditioner.py

@@ -29,8 +29,8 @@ class TestKoganKAWFPAC09YA(TargetTemperatureTests, TuyaDeviceTestCase):
         self.setUpTargetTemperature(
             TEMPERATURE_DPS,
             self.subject,
-            min=16,
-            max=30,
+            min=16.0,
+            max=30.0,
         )
 
     def test_supported_features(self):

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików