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

Don't consider hidden mappings at all when mapping back to dps_val

When a hidden mapping maps to the same dps_val as a normal mapping, the
normal mapping should be used.

But in the previous code, the hidden mapping could be returned from
_find_map_for_value then filtered out later (but only if the hidden
marking was on the map, not an embedded condition).

Instead, do the filtering inside _find_map_for_value, and improve the
logic so that hidden at the map level does not hide all the conditions
within, as that is used in some more complex conditional mappings.

Also take into account available attributes.

PR #2701
Jason Rumney 1 год назад
Родитель
Сommit
b5fe10200e
1 измененных файлов с 12 добавлено и 5 удалено
  1. 12 5
      custom_components/tuya_local/helpers/device_config.py

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

@@ -797,32 +797,39 @@ class TuyaDpsConfig:
         nearest = None
         distance = float("inf")
         for m in self._config.get("mapping", {}):
-            if "dps_val" not in m:
+            # no reverse mapping of hidden values
+            ignore = m.get("hidden", False) or not self.mapping_available(m, device)
+
+            if "dps_val" not in m and not ignore:
                 default = m
             # The following avoids further matching on the above case
             # and in the null mapping case, which is intended to be
             # a one-way map to prevent the entity showing as unavailable
             # when no value is being reported by the device.
             if m.get("dps_val") is None:
-                continue
-            if "value" in m and str(m["value"]) == str(value):
+                ignore = True
+
+            if "value" in m and str(m["value"]) == str(value) and not ignore:
                 return m
             if (
                 "value" in m
                 and isinstance(m["value"], Number)
                 and isinstance(value, Number)
+                and not ignore
             ):
                 d = abs(m["value"] - value)
                 if d < distance:
                     distance = d
                     nearest = m
 
-            if "value" not in m and "value_mirror" in m:
+            if "value" not in m and "value_mirror" in m and not ignore:
                 r_dps = self._entity.find_dps(m["value_mirror"])
                 if r_dps and str(r_dps.get_value(device)) == str(value):
                     return m
 
             for c in m.get("conditions", {}):
+                if c.get("hidden", False) or not self.mapping_available(c, device):
+                    continue
                 if "value" in c and str(c["value"]) == str(value):
                     c_dp = self._entity.find_dps(m.get("constraint", self.name))
                     # only consider the condition a match if we can change
@@ -900,7 +907,7 @@ class TuyaDpsConfig:
             step = mapping.get("step")
             if not isinstance(step, Number):
                 step = None
-            if "dps_val" in mapping and not mapping.get("hidden", False):
+            if "dps_val" in mapping:
                 result = mapping["dps_val"]
                 replaced = True
             # Conditions may have side effect of setting another value.