Explorar o 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 %!s(int64=4) %!d(string=hai) anos
pai
achega
be63972f82

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

@@ -319,6 +319,7 @@ class TuyaDpsConfig:
             scale = mapping.get("scale", 1)
             if not isinstance(scale, (int, float)):
                 scale = 1
+            redirect = mapping.get("value-redirect")
             replaced = "value" in mapping
             result = mapping.get("value", result)
             cond = self._active_condition(mapping, device)
@@ -328,12 +329,19 @@ class TuyaDpsConfig:
                 replaced = replaced or "value" in cond
                 result = cond.get("value", result)
                 scale = cond.get("scale", scale)
+                redirect = cond.get("value-redirect", redirect)
+
                 if "mapping" in cond:
                     for m in cond["mapping"]:
                         if str(m.get("dps_val")) == str(result):
                             replaced = "value" in m
                             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)):
                 result = result / scale
                 replaced = True
@@ -384,6 +392,7 @@ class TuyaDpsConfig:
         if mapping is not None:
             replaced = False
             scale = mapping.get("scale", 1)
+            redirect = mapping.get("value-redirect")
             if not isinstance(scale, (int, float)):
                 scale = 1
             step = mapping.get("step")
@@ -400,6 +409,12 @@ class TuyaDpsConfig:
                     dps_map.update(c_dps.get_values_to_set(device, cond["dps_val"]))
                 scale = cond.get("scale", scale)
                 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)):
                 _LOGGER.debug(f"Scaling {result} by {scale}")
@@ -426,8 +441,7 @@ class TuyaDpsConfig:
             maximum = range["max"]
             if result < minimum or result > maximum:
                 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:

+ 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):
         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)
 
         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)
 

+ 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):
         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)
 
         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)
 

+ 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):
         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)
 
         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)
 

+ 0 - 8
tests/devices/test_goldair_dehumidifier.py

@@ -583,14 +583,6 @@ class TestGoldairDehumidifier(IsolatedAsyncioTestCase):
         # ):
         #     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):
         self.dps[ERROR_DPS] = None
         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):
         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)
 
         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)
 

+ 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):
         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)
 
         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)
 

+ 4 - 8
tests/devices/test_goldair_gpph_heater.py

@@ -112,7 +112,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         self.dps[PRESET_DPS] = "C"
         self.assertEqual(self.subject.target_temperature, 25)
 
-    @skip("Conditional redirection not supported.")
     def test_target_temperature_in_eco_and_af_modes(self):
         self.dps[TEMPERATURE_DPS] = 25
         self.dps[ECOTEMP_DPS] = 15
@@ -182,7 +181,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         ):
             await self.subject.async_set_target_temperature(25)
 
-    @skip("Redirection not yet supported")
     async def test_set_target_temperature_in_eco_mode(self):
         self.dps[PRESET_DPS] = "ECO"
 
@@ -202,12 +200,12 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         self.dps[PRESET_DPS] = "C"
 
         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)
 
         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)
 
@@ -215,12 +213,12 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         self.dps[PRESET_DPS] = "ECO"
 
         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)
 
         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)
 
@@ -298,7 +296,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         ):
             await self.subject.async_set_preset_mode("away")
 
-    @skip("Conditional redirection not yet supported")
     def test_power_level_returns_user_power_level(self):
         self.dps[SWING_DPS] = "user"
 
@@ -336,7 +333,6 @@ class TestGoldairHeater(IsolatedAsyncioTestCase):
         ):
             await self.subject.async_set_swing_mode("Stop")
 
-    @skip("Conditional redirection not supported yet")
     async def test_set_swing_mode_to_auto(self):
         async with assert_device_properties_set(
             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):
         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)
 
         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)
 

+ 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):
         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)
 
         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)
 

+ 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):
         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)
 
         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)