AlexxIT / XiaomiGateway3

Home Assistant custom component for control Xiaomi Multimode Gateway (aka Gateway 3), Xiaomi Multimode Gateway 2, Aqara Hub E1 on default firmwares over LAN
https://github.com/AlexxIT/Blog
MIT License
2.47k stars 349 forks source link

[Feature]Support Xiaomi Smart Door Lock with Face Unlock(without X) #874

Closed LANB0 closed 1 year ago

LANB0 commented 1 year ago

Hey @AlexxIT! First of all, amazing work you've done with this repo. I'm on a quest to integrate Xiaomi Smart Door Lock with Face Unlock(without X) to Home Assistant somehow.

I have made some attempts, and catch the data from mqtt. But I am not familiar with the relevant code. So I need your help. BLE code:6017, device model: XMZNMS09LM the data:

Lock(eid:18964)(2B | 4B | 1B | 1B | 1B)
open inside:
{"did":"1038140837","eid":18964,"edata":"0000 e32b8463 02 0f 01","pdid":6017,"seq":116} 
auto lock:
{"did":"1038140837","eid":18964,"edata":"0000 e92b8463 01 10 03","pdid":6017,"seq":118} 
open outside with the fingerprint:
{"did":"1038140837","eid":18964,"edata":"0300 e92b8463 02 02 02","pdid":6017,"seq":119} 
open outside with the face:
{"did":"1038140837","eid":18964,"edata":"0200 b44f8463 02 05 02","pdid":6017,"seq":126}
DoorBell(eid:22022)(4B)
the door bell:
{"did":"1038140837","eid":22022,"edata":"58568463","pdid":6017,"seq":138}  
Abnormal (eid:18951)(4B | 1B)
 Abnormal Condition: unlock the door for long time:
{"did":"1038140837","eid":18951,"edata":"65598463 17","pdid":6017,"seq":156}
Battery(eid:20483)(1B)
the battery percent:
{"did":"1038140837","eid":20483,"edata":"64","pdid":6017,"seq":122} 

All the enums for the data is same as miot-spec And I try to add some code to support, but not work. core/converters/devices.py:

    6017: ["Xiaomi", "Face Recognition Smart Door Lock", "XMZNMS09LM"],
    "spec": [
        MiBeacon,
        Converter("action", "sensor"),
        Converter("battery", "sensor"),
        Converter("contact", "binary_sensor"),
        Converter("lock", "binary_sensor"),
    ],

core/converters/mibeacon.py:

        elif eid == 0x5003:  # 20483
            # xiaomi face recogenize lock battery
            payload['battery'] = data[0]
        elif eid == 0x4A14:   #18964
            # xiaomi face recogenize lock action
            action = data[6] & 0x0F
            method = data[7] & 0x0F
            key_id = short.from_bytes(data[0:1], 'little')
            # error = BLE_LOCK_ERROR.get(key_id)

            # all keys except Bluetooth have only 65536 values
            # if error is None and method > 0:
            #     key_id &= 0xFFFF
            # elif error:
            #     key_id = hex(key_id)

            timestamp = int.from_bytes(data[2:6], 'little')
            timestamp = datetime.fromtimestamp(timestamp).isoformat()

            if data[6] == 1:
                payload['contact'] = True
            elif data[6] == 2:
                payload['contact'] = False

            # if action not in BLE_LOCK_ACTION or method not in BLE_LOCK_METHOD:
            #     return

            payload.update({
                'action': 'lock',
                'action_id': action,
                'method_id': method,
                # 'message': BLE_LOCK_ACTION[action],
                # 'method': BLE_LOCK_METHOD[method],
                'key_id': key_id,
                # 'error': error,
                'timestamp': timestamp
            })
        elif eid == 0x5606: #22022
            # xiaomi face recogenize lock doorbell
            timestamp = int.from_bytes(data[0:4], 'little')
            timestamp = datetime.fromtimestamp(timestamp).isoformat()

            payload['doorbell'] = timestamp
        elif eid == 0x4A07:
            # xiaomi face recogenize lock abnormal-condition
            payload['error'] = data[5]
LANB0 commented 1 year ago

sorry for my code, I try to use "short.from_bytes" to parse 2 byte data (I'm a Cxx programmer). When I modify to "int.from_bytes", it works. I'll test and tidy up my code, then open a PR to support the new device.