diff --git a/custom_components/ble_monitor/ble_parser/xiaomi.py b/custom_components/ble_monitor/ble_parser/xiaomi.py index 4023ccb20..d257f82a8 100755 --- a/custom_components/ble_monitor/ble_parser/xiaomi.py +++ b/custom_components/ble_monitor/ble_parser/xiaomi.py @@ -74,6 +74,7 @@ 0x20DB: "MJZNZ018H", 0x18E3: "ZX1", 0x11C2: "SV40", + 0x3F0F: "RS1BB", } # Structured objects for data conversions @@ -721,6 +722,12 @@ def obj4805(xobj): return {"illuminance": illu} +def obj4806(xobj): + """Moisture detected (wet/dry)""" + wet = xobj[0] + return {"moisture detected": wet} + + def obj4810(xobj): """Sleep State""" sleep_state = xobj[0] @@ -1052,6 +1059,7 @@ def obj5a16(xobj): 0x4803: obj4803, 0x4804: obj4804, 0x4805: obj4805, + 0x4806: obj4806, 0x4810: obj4810, 0x4811: obj4811, 0x4818: obj4818, diff --git a/custom_components/ble_monitor/const.py b/custom_components/ble_monitor/const.py index be9f64d95..7418b2591 100755 --- a/custom_components/ble_monitor/const.py +++ b/custom_components/ble_monitor/const.py @@ -1950,6 +1950,7 @@ class BLEMonitorBinarySensorEntityDescription( 'Tilt Pink' : 'Tilt', 'MMC-W505' : 'Xiaomi', 'SJWS01LM' : 'Xiaomi', + 'RS1BB' : 'Linptech', } diff --git a/custom_components/ble_monitor/manifest.json b/custom_components/ble_monitor/manifest.json index 12f0eaa3b..7bedaa54b 100644 --- a/custom_components/ble_monitor/manifest.json +++ b/custom_components/ble_monitor/manifest.json @@ -14,5 +14,5 @@ "btsocket>=0.2.0", "pyric>=0.1.6.3" ], - "version": "12.8.2" + "version": "12.9.0" } diff --git a/custom_components/ble_monitor/test/test_xiaomi_parser.py b/custom_components/ble_monitor/test/test_xiaomi_parser.py index c2a0a3dc2..bf0c86e57 100644 --- a/custom_components/ble_monitor/test/test_xiaomi_parser.py +++ b/custom_components/ble_monitor/test/test_xiaomi_parser.py @@ -340,6 +340,32 @@ def test_Xiaomi_SJWS01LM(self): assert sensor_msg["moisture detected"] assert sensor_msg["rssi"] == -88 + def test_Xiaomi_RS1BB(self): + """Test Xiaomi parser for LINP-RS1BB.""" + self.aeskeys = {} + data_string = "043E2902010000674cb938c1a41d020106191695fe58590F3F4A674CB938C1A4D6E57B83040000D01E0B4BC0" + data = bytes(bytearray.fromhex(data_string)) + + aeskey = "33ede53321bc73c790a8daae4581f3d5" + + is_ext_packet = True if data[3] == 0x0D else False + mac = (data[8 if is_ext_packet else 7:14 if is_ext_packet else 13])[::-1] + mac_address = mac.hex() + p_mac = bytes.fromhex(mac_address.replace(":", "").lower()) + p_key = bytes.fromhex(aeskey.lower()) + self.aeskeys[p_mac] = p_key + # pylint: disable=unused-variable + ble_parser = BleParser(aeskeys=self.aeskeys) + sensor_msg, tracker_msg = ble_parser.parse_raw_data(data) + + assert sensor_msg["firmware"] == "Xiaomi (MiBeacon V5 encrypted)" + assert sensor_msg["type"] == "RS1BB" + assert sensor_msg["mac"] == "A4C138B94C67" + assert sensor_msg["packet"] == 74 + assert sensor_msg["data"] + assert sensor_msg["moisture detected"] == 0 + assert sensor_msg["rssi"] == -64 + def test_Xiaomi_MJYD02YL(self): """Test Xiaomi parser for MJYD02YL.""" diff --git a/docs/_devices/RS1BB.md b/docs/_devices/RS1BB.md new file mode 100644 index 000000000..6fbc6049a --- /dev/null +++ b/docs/_devices/RS1BB.md @@ -0,0 +1,16 @@ +--- +manufacturer: Linptech +name: Water Immersion and Rainwater sensor +model: RS1BB +image: RS1BB.png +physical_description: +broadcasted_properties: + - moisture detected + - rssi +broadcasted_property_notes: +broadcast_rate: +active_scan: +encryption_key: true +custom_firmware: +notes: +--- diff --git a/docs/_devices/SJWS01LM.md b/docs/_devices/SJWS01LM.md index 551d415a0..2a2b079c0 100644 --- a/docs/_devices/SJWS01LM.md +++ b/docs/_devices/SJWS01LM.md @@ -5,7 +5,7 @@ model: SJWS01LM image: SJWS01LM.png physical_description: broadcasted_properties: - - moisture + - moisture detected - button - battery - rssi diff --git a/docs/assets/images/RS1BB.png b/docs/assets/images/RS1BB.png new file mode 100644 index 000000000..390a912e8 Binary files /dev/null and b/docs/assets/images/RS1BB.png differ