Explorar el Código

Add some basic redirection capability.

Also changed the error message for out of range values to not include "Target", as this might be misleading for some DPS.
Jason Rumney hace 5 años
padre
commit
be63972f82

+ 16 - 2
custom_components/tuya_local/helpers/device_config.py

@@ -319,6 +319,7 @@ class TuyaDpsConfig:
             scale = mapping.get("scale", 1)
             scale = mapping.get("scale", 1)
             if not isinstance(scale, (int, float)):
             if not isinstance(scale, (int, float)):
                 scale = 1
                 scale = 1
+            redirect = mapping.get("value-redirect")
             replaced = "value" in mapping
             replaced = "value" in mapping
             result = mapping.get("value", result)
             result = mapping.get("value", result)
             cond = self._active_condition(mapping, device)
             cond = self._active_condition(mapping, device)
@@ -328,12 +329,19 @@ class TuyaDpsConfig:
                 replaced = replaced or "value" in cond
                 replaced = replaced or "value" in cond
                 result = cond.get("value", result)
                 result = cond.get("value", result)
                 scale = cond.get("scale", scale)
                 scale = cond.get("scale", scale)
+                redirect = cond.get("value-redirect", redirect)
+
                 if "mapping" in cond:
                 if "mapping" in cond:
                     for m in cond["mapping"]:
                     for m in cond["mapping"]:
                         if str(m.get("dps_val")) == str(result):
                         if str(m.get("dps_val")) == str(result):
                             replaced = "value" in m
                             replaced = "value" in m
                             result = m.get("value", result)
                             result = m.get("value", result)
 
 
+            if redirect is not None:
+                _LOGGER.debug(f"Redirecting {self.name} to {redirect}")
+                r_dps = self._entity.find_dps(redirect)
+                return r_dps.get_value(device)
+
             if scale != 1 and isinstance(result, (int, float)):
             if scale != 1 and isinstance(result, (int, float)):
                 result = result / scale
                 result = result / scale
                 replaced = True
                 replaced = True
@@ -384,6 +392,7 @@ class TuyaDpsConfig:
         if mapping is not None:
         if mapping is not None:
             replaced = False
             replaced = False
             scale = mapping.get("scale", 1)
             scale = mapping.get("scale", 1)
+            redirect = mapping.get("value-redirect")
             if not isinstance(scale, (int, float)):
             if not isinstance(scale, (int, float)):
                 scale = 1
                 scale = 1
             step = mapping.get("step")
             step = mapping.get("step")
@@ -400,6 +409,12 @@ class TuyaDpsConfig:
                     dps_map.update(c_dps.get_values_to_set(device, cond["dps_val"]))
                     dps_map.update(c_dps.get_values_to_set(device, cond["dps_val"]))
                 scale = cond.get("scale", scale)
                 scale = cond.get("scale", scale)
                 step = cond.get("step", step)
                 step = cond.get("step", step)
+                redirect = cond.get("value-redirect", redirect)
+
+            if redirect is not None:
+                _LOGGER.debug(f"Redirecting {self.name} to {redirect}")
+                r_dps = self._entity.find_dps(redirect)
+                return r_dps.get_values_to_set(device, value)
 
 
             if scale != 1 and isinstance(result, (int, float)):
             if scale != 1 and isinstance(result, (int, float)):
                 _LOGGER.debug(f"Scaling {result} by {scale}")
                 _LOGGER.debug(f"Scaling {result} by {scale}")
@@ -426,8 +441,7 @@ class TuyaDpsConfig:
             maximum = range["max"]
             maximum = range["max"]
             if result < minimum or result > maximum:
             if result < minimum or result > maximum:
                 raise ValueError(
                 raise ValueError(
-                    f"Target {self.name} ({value}) must be between "
-                    f"{minimum} and {maximum}"
+                    f"{self.name} ({value}) must be between " f"{minimum} and {maximum}"
                 )
                 )
 
 
         if self.type is int:
         if self.type is int:

+ 2 - 2
tests/devices/test_andersson_gsh_heater.py

@@ -116,12 +116,12 @@ class TestAnderssonGSHHeater(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(4\\) must be between 5 and 35"
+            ValueError, "temperature \\(4\\) must be between 5 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(4)
             await self.subject.async_set_target_temperature(4)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 5 and 35"
+            ValueError, "temperature \\(36\\) must be between 5 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 

+ 2 - 2
tests/devices/test_eurom_600_heater.py

@@ -103,12 +103,12 @@ class TestEurom600Heater(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(14\\) must be between 15 and 35"
+            ValueError, "temperature \\(14\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(14)
             await self.subject.async_set_target_temperature(14)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 15 and 35"
+            ValueError, "temperature \\(36\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 

+ 2 - 2
tests/devices/test_gardenpac_heatpump.py

@@ -124,12 +124,12 @@ class TestGardenPACPoolHeatpump(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(14\\) must be between 18 and 45"
+            ValueError, "temperature \\(14\\) must be between 18 and 45"
         ):
         ):
             await self.subject.async_set_target_temperature(14)
             await self.subject.async_set_target_temperature(14)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(46\\) must be between 18 and 45"
+            ValueError, "temperature \\(46\\) must be between 18 and 45"
         ):
         ):
             await self.subject.async_set_target_temperature(46)
             await self.subject.async_set_target_temperature(46)
 
 

+ 0 - 8
tests/devices/test_goldair_dehumidifier.py

@@ -583,14 +583,6 @@ class TestGoldairDehumidifier(IsolatedAsyncioTestCase):
         # ):
         # ):
         #     await self.subject.async_set_fan_mode(FAN_HIGH)
         #     await self.subject.async_set_fan_mode(FAN_HIGH)
 
 
-    @skip("Redirection not supported yet")
-    def test_tank_full_or_missing(self):
-        self.dps[ERROR_DPS] = None
-        self.assertEqual(self.subject.tank_full_or_missing, False)
-
-        self.dps[ERROR_DPS] = 8
-        self.assertEqual(self.subject.tank_full_or_missing, True)
-
     def test_device_state_attributes(self):
     def test_device_state_attributes(self):
         self.dps[ERROR_DPS] = None
         self.dps[ERROR_DPS] = None
         self.dps[DEFROST_DPS] = False
         self.dps[DEFROST_DPS] = False

+ 2 - 2
tests/devices/test_goldair_geco_heater.py

@@ -123,12 +123,12 @@ class TestGoldairGECOHeater(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(14\\) must be between 15 and 35"
+            ValueError, "temperature \\(14\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(14)
             await self.subject.async_set_target_temperature(14)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 15 and 35"
+            ValueError, "temperature \\(36\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 

+ 2 - 2
tests/devices/test_goldair_gpcv_heater.py

@@ -137,12 +137,12 @@ class TestGoldairGPCVHeater(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(14\\) must be between 15 and 35"
+            ValueError, "temperature \\(14\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(14)
             await self.subject.async_set_target_temperature(14)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 15 and 35"
+            ValueError, "temperature \\(36\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 

+ 4 - 8
tests/devices/test_goldair_gpph_heater.py

@@ -112,7 +112,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         self.dps[PRESET_DPS] = "C"
         self.dps[PRESET_DPS] = "C"
         self.assertEqual(self.subject.target_temperature, 25)
         self.assertEqual(self.subject.target_temperature, 25)
 
 
-    @skip("Conditional redirection not supported.")
     def test_target_temperature_in_eco_and_af_modes(self):
     def test_target_temperature_in_eco_and_af_modes(self):
         self.dps[TEMPERATURE_DPS] = 25
         self.dps[TEMPERATURE_DPS] = 25
         self.dps[ECOTEMP_DPS] = 15
         self.dps[ECOTEMP_DPS] = 15
@@ -182,7 +181,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         ):
         ):
             await self.subject.async_set_target_temperature(25)
             await self.subject.async_set_target_temperature(25)
 
 
-    @skip("Redirection not yet supported")
     async def test_set_target_temperature_in_eco_mode(self):
     async def test_set_target_temperature_in_eco_mode(self):
         self.dps[PRESET_DPS] = "ECO"
         self.dps[PRESET_DPS] = "ECO"
 
 
@@ -202,12 +200,12 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         self.dps[PRESET_DPS] = "C"
         self.dps[PRESET_DPS] = "C"
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(4\\) must be between 5 and 35"
+            ValueError, "temperature \\(4\\) must be between 5 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(4)
             await self.subject.async_set_target_temperature(4)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 5 and 35"
+            ValueError, "temperature \\(36\\) must be between 5 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 
@@ -215,12 +213,12 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         self.dps[PRESET_DPS] = "ECO"
         self.dps[PRESET_DPS] = "ECO"
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(4\\) must be between 5 and 21"
+            ValueError, "eco_temperature \\(4\\) must be between 5 and 21"
         ):
         ):
             await self.subject.async_set_target_temperature(4)
             await self.subject.async_set_target_temperature(4)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(22\\) must be between 5 and 21"
+            ValueError, "eco_temperature \\(22\\) must be between 5 and 21"
         ):
         ):
             await self.subject.async_set_target_temperature(22)
             await self.subject.async_set_target_temperature(22)
 
 
@@ -298,7 +296,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         ):
         ):
             await self.subject.async_set_preset_mode("away")
             await self.subject.async_set_preset_mode("away")
 
 
-    @skip("Conditional redirection not yet supported")
     def test_power_level_returns_user_power_level(self):
     def test_power_level_returns_user_power_level(self):
         self.dps[SWING_DPS] = "user"
         self.dps[SWING_DPS] = "user"
 
 
@@ -336,7 +333,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         ):
         ):
             await self.subject.async_set_swing_mode("Stop")
             await self.subject.async_set_swing_mode("Stop")
 
 
-    @skip("Conditional redirection not supported yet")
     async def test_set_swing_mode_to_auto(self):
     async def test_set_swing_mode_to_auto(self):
         async with assert_device_properties_set(
         async with assert_device_properties_set(
             self.subject._device,
             self.subject._device,

+ 2 - 2
tests/devices/test_kogan_heater.py

@@ -136,12 +136,12 @@ class TestGoldairKoganHeater(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(14\\) must be between 15 and 35"
+            ValueError, "temperature \\(14\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(14)
             await self.subject.async_set_target_temperature(14)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 15 and 35"
+            ValueError, "temperature \\(36\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 

+ 2 - 2
tests/devices/test_purline_m100_heater.py

@@ -147,12 +147,12 @@ class TestPulineM100Heater(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(4\\) must be between 15 and 35"
+            ValueError, "temperature \\(4\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(4)
             await self.subject.async_set_target_temperature(4)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(36\\) must be between 15 and 35"
+            ValueError, "temperature \\(36\\) must be between 15 and 35"
         ):
         ):
             await self.subject.async_set_target_temperature(36)
             await self.subject.async_set_target_temperature(36)
 
 

+ 2 - 2
tests/devices/test_remora_heatpump.py

@@ -117,12 +117,12 @@ class TestRemoraHeatpump(IsolatedAsyncioTestCase):
 
 
     async def test_set_target_temperature_fails_outside_valid_range(self):
     async def test_set_target_temperature_fails_outside_valid_range(self):
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(4\\) must be between 5 and 40"
+            ValueError, "temperature \\(4\\) must be between 5 and 40"
         ):
         ):
             await self.subject.async_set_target_temperature(4)
             await self.subject.async_set_target_temperature(4)
 
 
         with self.assertRaisesRegex(
         with self.assertRaisesRegex(
-            ValueError, "Target temperature \\(41\\) must be between 5 and 40"
+            ValueError, "temperature \\(41\\) must be between 5 and 40"
         ):
         ):
             await self.subject.async_set_target_temperature(41)
             await self.subject.async_set_target_temperature(41)