mbakhtin 2 лет назад
Родитель
Сommit
94a9eb8c17

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

@@ -166,7 +166,7 @@ Whether to persist the value if the device does not return it on every status
 refresh.  Some devices don't return every value on every status poll. In most
 cases, it is better to remember the previous value, but in some cases the
 dp is used to signal an event, so when it is next sent, it should trigger
-automations even if it is the same value as previously sent.  In that case 
+automations even if it is the same value as previously sent.  In that case
 the value needs to go to null in between when the device is not sending it.
 
 ### `force`
@@ -260,6 +260,12 @@ the device type.
 
 For base64 and hex types, this specifies how to extract a single numeric value from the binary data.  The value should be a hex bit mask (eg 00FF00 to extract the middle byte of a 3 byte value).  Unlike format, this does not require special handling in the entity platform, as only a single value is being extracted.
 
+### `endianness`
+
+*Optional, default="big"*
+
+For base64 and hex types, this specifies the endianess of the data and mask. Could be "big" or "little".
+
 ## Mapping Rules
 
 Mapping rules can change the behavior of attributes beyond simple
@@ -643,7 +649,7 @@ The value "off" will be used for turning off the siren, and will be filtered fro
 
 - **min_temperature** (optional, number): a dp that reports the minimum temperature the water heater can be set to, in case this is not a fixed value.
 
-- **max_temperature** (optional, number): a dp that reports the maximum temperature the water heater can be set to, in case this is not a fixed value. 
+- **max_temperature** (optional, number): a dp that reports the maximum temperature the water heater can be set to, in case this is not a fixed value.
 
 - **away_mode** (optional, boolean): a dp to control whether the water heater is in away mode.
 

+ 326 - 0
custom_components/tuya_local/devices/inkbird_ibs_m1s.yaml

@@ -0,0 +1,326 @@
+name: Inkbird IBS-M1S hub
+products:
+  - id: ojlc1dnjbrybk7di
+    name: IBS-M1S
+primary_entity:
+  entity: sensor
+  name: Temperature probe 1
+  class: temperature
+  dps:
+    - id: 110
+      type: integer
+      name: dummy
+      persist: false
+    - id: 111
+      type: boolean
+      name: dummy2
+      persist: false
+    - id: 114
+      optional: true
+      type: base64
+      name: type
+      persist: false
+      mapping:
+        - endianness: little
+          mask: "FF"
+    - id: 114
+      optional: true
+      type: base64
+      name: sensor
+      unit: C
+      class: measurement
+      mapping:
+        - scale: 10
+          endianness: little
+          mask: "FFFF00"
+          constraint: type
+          constraint_decode: true
+          conditions:
+            - dps_val: 0
+              invalid: true
+secondary_entities:
+  - entity: sensor
+    name: Battery 1
+    class: battery
+    category: diagnostic
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF"
+      - id: 114
+        type: base64
+        name: sensor
+        unit: "%"
+        mapping:
+          - endianness: little
+            mask: "FF000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Temperature probe 2
+    class: temperature
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF00000000000000000000"
+      - id: 114
+        optional: true
+        type: base64
+        name: sensor
+        unit: C
+        class: measurement
+        mapping:
+          - scale: 10
+            endianness: little
+            mask: "FFFF0000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Battery 2
+    class: battery
+    category: diagnostic
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF00000000000000000000"
+      - id: 114
+        type: base64
+        name: sensor
+        unit: "%"
+        mapping:
+          - endianness: little
+            mask: "FF00000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Temperature probe 3
+    class: temperature
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF0000000000000000000000000000000000000000"
+      - id: 114
+        optional: true
+        type: base64
+        name: sensor
+        unit: C
+        class: measurement
+        mapping:
+          - scale: 10
+            endianness: little
+            mask: "FFFF000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Battery 3
+    class: battery
+    category: diagnostic
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF0000000000000000000000000000000000000000"
+      - id: 114
+        type: base64
+        name: sensor
+        unit: "%"
+        mapping:
+          - endianness: little
+            mask: "FF0000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Temperature probe 4
+    class: temperature
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF000000000000000000000000000000000000000000000000000000000000"
+      - id: 114
+        optional: true
+        type: base64
+        name: sensor
+        unit: C
+        class: measurement
+        mapping:
+          - scale: 10
+            endianness: little
+            mask: "FFFF00000000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Battery 4
+    class: battery
+    category: diagnostic
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF000000000000000000000000000000000000000000000000000000000000"
+      - id: 114
+        type: base64
+        name: sensor
+        unit: "%"
+        mapping:
+          - endianness: little
+            mask: "FF000000000000000000000000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Temperature probe 5
+    class: temperature
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF00000000000000000000000000000000000000000000000000000000000000000000000000000000"
+      - id: 114
+        optional: true
+        type: base64
+        name: sensor
+        unit: C
+        class: measurement
+        mapping:
+          - scale: 10
+            endianness: little
+            mask: "FFFF0000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Battery 5
+    class: battery
+    category: diagnostic
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF00000000000000000000000000000000000000000000000000000000000000000000000000000000"
+      - id: 114
+        type: base64
+        name: sensor
+        unit: "%"
+        mapping:
+          - endianness: little
+            mask: "FF00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Temperature probe 6
+    class: temperature
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+      - id: 114
+        optional: true
+        type: base64
+        name: sensor
+        unit: C
+        class: measurement
+        mapping:
+          - scale: 10
+            endianness: little
+            mask: "FFFF000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true
+  - entity: sensor
+    name: Battery 6
+    class: battery
+    category: diagnostic
+    dps:
+      - id: 114
+        optional: true
+        type: base64
+        name: type
+        persist: false
+        mapping:
+          - endianness: little
+            mask: "FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+      - id: 114
+        type: base64
+        name: sensor
+        unit: "%"
+        mapping:
+          - endianness: little
+            mask: "FF0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
+            constraint: type
+            constraint_decode: true
+            conditions:
+              - dps_val: 0
+                invalid: true

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

@@ -386,15 +386,23 @@ class TuyaDpsConfig:
             if mask:
                 return int(mask, 16)
 
+    def endianness(self, device):
+        mapping = self._find_map_for_dps(device.get_property(self.id))
+        if mapping:
+            endianness = mapping.get("endianness")
+            if endianness:
+                return endianness
+        return "big"
+
     def get_value(self, device):
         """Return the value of the dps from the given device."""
         mask = self.mask(device)
         bytevalue = self.decoded_value(device)
         if mask and isinstance(bytevalue, bytes):
-            value = int.from_bytes(bytevalue, "big")
+            value = int.from_bytes(bytevalue, self.endianness(device))
             scale = mask & (1 + ~mask)
             map_scale = self.scale(device)
-            return ((value & mask) // scale) / map_scale
+            return self._map_from_dps((value & mask) // scale, device)
         else:
             return self._map_from_dps(device.get_property(self.id), device)
 
@@ -746,7 +754,9 @@ class TuyaDpsConfig:
         c_match = None
         if constraint and conditions:
             c_dps = self._entity.find_dps(constraint)
-            c_val = None if c_dps is None else device.get_property(c_dps.id)
+            # base64 and hex have to be decoded
+            binary_type = c_dps.rawtype == "base64" or c_dps.rawtype == "hex"
+            c_val = None if c_dps is None else (c_dps.get_value(device) if binary_type else device.get_property(c_dps.id))
             for cond in conditions:
                 if c_val is not None and (_equal_or_in(c_val, cond.get("dps_val"))):
                     c_match = cond
@@ -781,6 +791,7 @@ class TuyaDpsConfig:
             redirect = mapping.get("value_redirect")
             invert = mapping.get("invert", False)
             mask = mapping.get("mask")
+            endianness = mapping.get("endianness", "big")
             step = mapping.get("step")
             if not isinstance(step, Number):
                 step = None
@@ -870,9 +881,9 @@ class TuyaDpsConfig:
             # Convert to int
             mask = int(mask, 16)
             mask_scale = mask & (1 + ~mask)
-            current_value = int.from_bytes(self.decoded_value(device), "big")
+            current_value = int.from_bytes(self.decoded_value(device), endianness)
             result = (current_value & ~mask) | (mask & (result * mask_scale))
-            result = self.encode_value(result.to_bytes(length, "big"))
+            result = self.encode_value(result.to_bytes(length, endianness))
 
         dps_map[self.id] = self._correct_type(result)
         return dps_map