Skip to content

Commit b1c4d4d

Browse files
committed
Add parser for PS1BB
1 parent ba9fb8e commit b1c4d4d

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

custom_components/ble_monitor/ble_parser/xiaomi.py

+42
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
0x3F0F: "RS1BB",
7878
0x38BB: "PTX",
7979
0x3531: "XMPIRO2SXS",
80+
0x3F4C: "PS1BB",
8081
}
8182

8283
# Structured objects for data conversions
@@ -759,6 +760,35 @@ def obj4818(xobj):
759760
return {}
760761

761762

763+
def obj483c(xobj):
764+
"""Pressure Present State"""
765+
return {"pressure state": xobj[0]}
766+
767+
768+
def obj483d(xobj):
769+
"""Pressure Present Duration"""
770+
(duration,) = struct.unpack("<I", xobj)
771+
return {"pressure present duration": duration}
772+
773+
774+
def obj483e(xobj):
775+
"""Pressure Not Present Duration"""
776+
(duration,) = struct.unpack("<I", xobj)
777+
return {"pressure not present duration": duration}
778+
779+
780+
def obj483f(xobj):
781+
"""Pressure present time set"""
782+
(duration,) = struct.unpack("<I", xobj)
783+
return {"pressure present time set": duration}
784+
785+
786+
def obj4840(xobj):
787+
"""Pressure Not Present Time Set"""
788+
(duration,) = struct.unpack("<I", xobj)
789+
return {"pressure not present time set": duration}
790+
791+
762792
def obj4a01(xobj):
763793
"""Low Battery"""
764794
low_batt = xobj[0]
@@ -839,6 +869,12 @@ def obj4a1a(xobj):
839869
return {}
840870

841871

872+
def obj4a1c(xobj):
873+
"""Device reset"""
874+
reset = xobj[0]
875+
return {"reset": reset}
876+
877+
842878
def obj4c01(xobj):
843879
"""Temperature"""
844880
if len(xobj) == 4:
@@ -1095,6 +1131,11 @@ def obj5a16(xobj):
10951131
0x4810: obj4810,
10961132
0x4811: obj4811,
10971133
0x4818: obj4818,
1134+
0x483c: obj483c,
1135+
0x483d: obj483d,
1136+
0x483e: obj483e,
1137+
0x483f: obj483f,
1138+
0x4840: obj4840,
10981139
0x4a01: obj4a01,
10991140
0x4a08: obj4a08,
11001141
0x4a0c: obj4a0c,
@@ -1104,6 +1145,7 @@ def obj5a16(xobj):
11041145
0x4a12: obj4a12,
11051146
0x4a13: obj4a13,
11061147
0x4a1a: obj4a1a,
1148+
0x4a1c: obj4a1c,
11071149
0x4c01: obj4c01,
11081150
0x4c02: obj4c02,
11091151
0x4c03: obj4c03,

custom_components/ble_monitor/const.py

+2
Original file line numberDiff line numberDiff line change
@@ -1790,6 +1790,7 @@ class BLEMonitorBinarySensorEntityDescription(
17901790
'YLYK01YL-VENFAN' : [["rssi"], ["ventilator fan remote"], []],
17911791
'YLYB01YL-BHFRC' : [["rssi"], ["bathroom heater remote"], []],
17921792
'YLKG07YL/YLKG08YL' : [["rssi"], ["dimmer"], []],
1793+
'PS1BB' : [["battery", "rssi"], [], []],
17931794
'SU001-T' : [["battery", "rssi"], [], ["motion", "switch"]],
17941795
'ATC' : [["temperature", "humidity", "battery", "voltage", "rssi"], [], ["switch", "opening"]],
17951796
'Mi Scale V1' : [["rssi"], ["weight", "non-stabilized weight"], ["weight removed"]],
@@ -1919,6 +1920,7 @@ class BLEMonitorBinarySensorEntityDescription(
19191920
'K9BB-1BTN' : 'Linptech',
19201921
'MS1BB(MI)' : 'Linptech',
19211922
'HS1BB(MI)' : 'Linptech',
1923+
'PS1BB' : 'Linptech',
19221924
'XMWXKG01YL' : 'Xiaomi',
19231925
'XMWXKG01LM' : 'Xiaomi',
19241926
'PTX' : 'Xiaomi',

custom_components/ble_monitor/test/test_xiaomi_parser.py

+26
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,32 @@ def test_Xiaomi_RS1BB(self):
366366
assert sensor_msg["moisture detected"] == 0
367367
assert sensor_msg["rssi"] == -64
368368

369+
def test_Xiaomi_PS1BB(self):
370+
"""Test Xiaomi parser for Linptech PS1BB."""
371+
self.aeskeys = {}
372+
data_string = "043E26020100009bd60f38c1a41a020106161695fe48594c3f21f4957fb405c9cf040000d8252537CC"
373+
data = bytes(bytearray.fromhex(data_string))
374+
375+
aeskey = "9b4441bc2505db3c3484bae6b7631b34"
376+
377+
is_ext_packet = True if data[3] == 0x0D else False
378+
mac = (data[8 if is_ext_packet else 7:14 if is_ext_packet else 13])[::-1]
379+
mac_address = mac.hex()
380+
p_mac = bytes.fromhex(mac_address.replace(":", "").lower())
381+
p_key = bytes.fromhex(aeskey.lower())
382+
self.aeskeys[p_mac] = p_key
383+
# pylint: disable=unused-variable
384+
ble_parser = BleParser(aeskeys=self.aeskeys)
385+
sensor_msg, tracker_msg = ble_parser.parse_raw_data(data)
386+
387+
assert sensor_msg["firmware"] == "Xiaomi (MiBeacon V5 encrypted)"
388+
assert sensor_msg["type"] == "PS1BB"
389+
assert sensor_msg["mac"] == "A4C1380FD69B"
390+
assert sensor_msg["packet"] == 33
391+
assert sensor_msg["data"]
392+
assert sensor_msg["pressure present duration"] == 0
393+
assert sensor_msg["rssi"] == -52
394+
369395
def test_Xiaomi_MJYD02YL(self):
370396
"""Test Xiaomi parser for MJYD02YL."""
371397

0 commit comments

Comments
 (0)