diff --git a/custom_components/ble_monitor/ble_parser/xiaomi.py b/custom_components/ble_monitor/ble_parser/xiaomi.py index bac734f1d..e2274fc55 100755 --- a/custom_components/ble_monitor/ble_parser/xiaomi.py +++ b/custom_components/ble_monitor/ble_parser/xiaomi.py @@ -846,8 +846,8 @@ def obj4c14(xobj): def obj4e0c(xobj, device_type): """Click""" - click = xobj[0] if device_type == "XMWXKG01YL": + click = xobj[0] if click == 1: result = { "two btn switch left": "toggle", @@ -865,6 +865,7 @@ def obj4e0c(xobj, device_type): "button switch": "single press", } elif device_type == "K9BB-1BTN": + click = xobj[0] if click == 1: result = { "one btn switch": "toggle", @@ -892,8 +893,8 @@ def obj4e0c(xobj, device_type): def obj4e0d(xobj, device_type): """Double Click""" - click = xobj[0] if device_type == "XMWXKG01YL": + click = xobj[0] if click == 1: result = { "two btn switch left": "toggle", @@ -922,8 +923,8 @@ def obj4e0d(xobj, device_type): def obj4e0e(xobj, device_type): """Long Press""" - click = xobj[0] if device_type == "XMWXKG01YL": + click = xobj[0] if click == 1: result = { "two btn switch left": "toggle", @@ -1266,7 +1267,7 @@ def parse_xiaomi(self, data, source_mac, rssi): _LOGGER.debug("Invalid payload data length, payload: %s", payload.hex()) break dobject = payload[payload_start + 3:next_start] - if dobject and obj_length != 0: + if dobject and obj_length != 0 or hex(obj_typecode) in ["0x4e0c", "0x4e0d", "0x4e0e"]: resfunc = xiaomi_dataobject_dict.get(obj_typecode, None) if resfunc: if hex(obj_typecode) in ["0x8", "0x100e", "0x1001", "0xf", "0xb", "0x4e0c", "0x4e0d", "0x4e0e"]: diff --git a/custom_components/ble_monitor/test/test_xiaomi_parser.py b/custom_components/ble_monitor/test/test_xiaomi_parser.py index 276e6e707..caff1b5ef 100644 --- a/custom_components/ble_monitor/test/test_xiaomi_parser.py +++ b/custom_components/ble_monitor/test/test_xiaomi_parser.py @@ -849,3 +849,84 @@ def test_MJZNZ018H_battery(self): assert sensor_msg["data"] assert sensor_msg["battery"] == 76 assert sensor_msg["rssi"] == -52 + + def test_XMWXKG01LM_single_click(self): + """Test Xiaomi parser for XMWXKG01LM single click on switch.""" + self.aeskeys = {} + data_string = "043E28020100000d692a3cc2181C020106181695fe58598723ff0d692a3cc21876d7a70800006024e757C0" + data = bytes(bytearray.fromhex(data_string)) + + aeskey = "c533a5ab361b0a24de4d21d1d9a3d8a1" + + 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"] == "XMWXKG01LM" + assert sensor_msg["mac"] == "18C23C2A690D" + assert sensor_msg["packet"] == 255 + assert sensor_msg["data"] + assert sensor_msg["one btn switch"] == "toggle" + assert sensor_msg["button switch"] == "single press" + assert sensor_msg["rssi"] == -64 + + def test_XMWXKG01LM_double_click(self): + """Test Xiaomi parser for XMWXKG01LM double click on switch.""" + self.aeskeys = {} + data_string = "043E28020100000d692a3cc2181C020106181695fe58598723010d692a3cc218f397dd09000079826b9dC0" + data = bytes(bytearray.fromhex(data_string)) + + aeskey = "c533a5ab361b0a24de4d21d1d9a3d8a1" + + 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"] == "XMWXKG01LM" + assert sensor_msg["mac"] == "18C23C2A690D" + assert sensor_msg["packet"] == 1 + assert sensor_msg["data"] + assert sensor_msg["one btn switch"] == "toggle" + assert sensor_msg["button switch"] == "double press" + assert sensor_msg["rssi"] == -64 + + def test_XMWXKG01LM_long_click(self): + """Test Xiaomi parser for XMWXKG01LM long click on switch.""" + self.aeskeys = {} + data_string = "043E28020100000d692a3cc2181C020106181695fe58598723030d692a3cc218258824090000a360b8a1C0" + data = bytes(bytearray.fromhex(data_string)) + + aeskey = "c533a5ab361b0a24de4d21d1d9a3d8a1" + + 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"] == "XMWXKG01LM" + assert sensor_msg["mac"] == "18C23C2A690D" + assert sensor_msg["packet"] == 3 + assert sensor_msg["data"] + assert sensor_msg["one btn switch"] == "toggle" + assert sensor_msg["button switch"] == "long press" + assert sensor_msg["rssi"] == -64