Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pair by QR code or NFC tap #244

Open
Jc2k opened this issue Nov 7, 2022 · 0 comments
Open

Pair by QR code or NFC tap #244

Jc2k opened this issue Nov 7, 2022 · 0 comments

Comments

@Jc2k
Copy link
Owner

Jc2k commented Nov 7, 2022

NFC tags and QR codes contain URL's that look like this:

X-HM://0071WK4SM7OSX (From the open source ADK)
X-HM://0LGPH8HKW76WCKHQ7VMDVQSG95Y5ERK (From a Wemo Stage NFC tag)

I recently got a Wemo Stage and the setup code It came with was wrong. But pairing by NFC worked. I was able to get the real setup code from the NFC tag - as its embedded in the URL and advertised when the device is unpaired and the device is in pairing mode.

We can probably implement a controller.async_pair_by_url(url) that takes one of these urls and pairs the device. If the HA apps get QR code readers (e.g. for pairing matter devices) we could hook in and pair HomeKit devices that way.

These urls are base36 encoded and contain the pairing code, the "setup id", whether the device is paired, whether the device supports IP or BLE, the category of the device, etc.

https://github.com/espressif/esp-homekit-sdk/blob/39f6bd94020289566555c5dc68ab4036bad52166/components/homekit/esp_hap_core/src/esp_hap_setup_payload.c
https://github.com/maximkulkin/esp-homekit/blob/master/tools/gen_qrcode
https://github.com/apple/HomeKitADK/blob/4967f698bdcf0af122e13e986a2c9b595a68cdc5/Tests/HAPAccessorySetupGetSetupPayloadTest.c
https://github.com/apple/HomeKitADK/blob/4967f698bdcf0af122e13e986a2c9b595a68cdc5/HAP/HAPAccessorySetup.c#L102

AIUI, the "setup id" in the NFC/QR code is related to the "sh" field in zeroconf and BLE advertisement so we can scan the sticker or NFC tag and find the right device. This isn't documented in the R2 spec.

Looking at the ADK, the setup hash is the first 4 bytes of a sha512 of the setup id and the device ID:

https://github.com/apple/HomeKitADK/blob/master/HAP/HAPAccessorySetup.c#L195-L218

Here is the test case:

https://github.com/apple/HomeKitADK/blob/4967f698bdcf0af122e13e986a2c9b595a68cdc5/Tests/HAPAccessorySetupGetSetupHashTest.c

It looks like:

  • the device ID looks to be what we call the hkid:
  • the device ID needs to be upper case with : intact
  • the setup ID is taken in its textual form from the hash - for X-HM://0071WK4SM7OSX, the setup ID is 70SX.

To look up a device by its setup ID, we have to go through every discovered device and hash the setup ID from the URL and the device ID in the discovery, and compare the result to the sh field.

For some devices we'll be able to tell from the URL if the device isn't in pairing mode or if its already paired, and reject them before trying to make bluetooth calls.

Once we have a discovery, we can pair it with the pairing code in the url.

Crappy code:

    payload  = int(url.split("://")[1][:9], 36)
    print("Payload:", payload)

    print("Setup code", str(payload & 0x7ffffff).zfill(8))
    print("Category", (payload >> 0x1f) & 0xff)    
    print("Flags", (payload >> 0x1b) & 0xf)    
    print("Reserved", (payload >> 0x27) & 15)    
    print("Version", (payload >> 0x2b) & 7)    
   
    print("Paired", ((payload >> 0x1b) & 0xf) & 1 )
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant