Sfoglia il codice sorgente

Auto detect stringified dps.

Remove the explicit stringify property from the config files.
Instead, detect when reading the property whether it is quoted, and if so,
quote it when writing too.

This compensates for the fact that previously added devices did not pay much
attention to this, and future software updates may change the use of quotes
for those devices that do come marked as stringified.
Jason Rumney 4 anni fa
parent
commit
db17ab41da

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

@@ -253,7 +253,7 @@ attribute. The contents are the same as Mapping Rules, but `dps_val` applies
 to the attribute specified by `constraint`. All others act on the current
 attribute as they would in the mapping.  Although conditions are specified
 within a mapping, they can also contain a `mapping` of their own to override
-that mapping.  Normally such mappings will be simple `dps_val` to `value`
-substitutions, as more complex rules will quickly become too complex to
+that mapping.  These nested mappings are limited to simple `dps_val` to `value`
+substitutions, as more complex rules would quickly become too complex to
 manage.
 

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

@@ -17,7 +17,6 @@ primary_entity:
           value: sleep
     - id: 3
       type: integer
-      stringify: true
       name: speed
       range:
         min: 1

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

@@ -8,7 +8,6 @@ primary_entity:
     - id: 3
       type: integer
       name: speed
-      stringify: true
       range:
         min: 1
         max: 3
@@ -16,7 +15,6 @@ primary_entity:
         - scale: 0.03
     - id: 102
       type: integer
-      stringify: true
       name: timer
 secondary_entities:
   - entity: light
@@ -28,7 +26,6 @@ secondary_entities:
       - id: 103
         type: integer
         name: timer
-        stringify: true
   - entity: switch
     name: Master
     dps:

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

@@ -204,6 +204,7 @@ class TuyaDpsConfig:
     def __init__(self, entity, config):
         self._entity = entity
         self._config = config
+        self.stringify = False
 
     @property
     def id(self):
@@ -313,10 +314,6 @@ class TuyaDpsConfig:
     def readonly(self):
         return self._config.get("readonly", False)
 
-    @property
-    def stringify(self):
-        return self._config.get("stringify", False)
-
     def invalid_for(self, value, device):
         mapping = self._find_map_for_value(value)
         if mapping:
@@ -339,12 +336,15 @@ class TuyaDpsConfig:
         return default
 
     def _map_from_dps(self, value, device):
-        # For stringified dps, convert to desired type if possible
-        if self.stringify and value is not None:
+        if value is not None and self.type is not str and isinstance(value, str):
             try:
                 value = self.type(value)
+                self.stringify = True
             except ValueError:
-                pass
+                self.stringify = False
+        else:
+            self.stringify = False
+
         result = value
         mapping = self._find_map_for_dps(value)
         if mapping:

+ 3 - 3
tests/devices/test_anko_fan.py

@@ -153,17 +153,17 @@ class TestAnkoFan(IsolatedAsyncioTestCase):
 
     async def test_set_speed_in_normal_mode(self):
         self.dps[PRESET_DPS] = "normal"
-        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: "2"}):
+        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 2}):
             await self.subject.async_set_percentage(25)
 
     async def test_set_speed_in_normal_mode_snaps(self):
         self.dps[PRESET_DPS] = "normal"
-        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: "6"}):
+        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 6}):
             await self.subject.async_set_percentage(80)
 
     def test_device_state_attributes(self):
         self.dps[TIMER_DPS] = "5"
-        self.assertEqual(self.subject.device_state_attributes, {"timer": "5"})
+        self.assertEqual(self.subject.device_state_attributes, {"timer": 5})
 
     async def test_update(self):
         result = AsyncMock()

+ 7 - 1
tests/devices/test_deta_fan.py

@@ -109,11 +109,17 @@ class TestDetaFan(IsolatedAsyncioTestCase):
         self.assertAlmostEqual(self.subject.percentage_step, 33.3, 1)
 
     async def test_set_speed(self):
+        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 2}):
+            await self.subject.async_set_percentage(66.7)
+
+    async def test_auto_stringify_speed(self):
+        self.dps[SPEED_DPS] = "1"
+        self.assertAlmostEqual(self.subject.percentage, 33.3, 1)
         async with assert_device_properties_set(self.subject._device, {SPEED_DPS: "2"}):
             await self.subject.async_set_percentage(66.7)
 
     async def test_set_speed_snaps(self):
-        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: "2"}):
+        async with assert_device_properties_set(self.subject._device, {SPEED_DPS: 2}):
             await self.subject.async_set_percentage(55)
 
     def test_device_state_attributes(self):