Bluetooth Specification questions

Hi there,
I recently upgrade from the Nuki Lock v1.0 to v2.0 and it’s been great so far. The door sensor works really great, although I miss the bridge as the HTTP API doesn’t work on the new bridges. The door sensor isn’t available anyway, even on the old bridges.

I am currently developing a Node.JS library for Nuki and have already implemented the basic protocol. However the Bluetooth specification is missing some important information.

  1. How does Nuki signal a state change to the authorised apps? The bridge can call a web hook but how is the state change indicated via the bluetooth protocol? What I have seen so far on GitHub is, that one user inferred the state change by looking at a specific bit in the manufacturer data that Nuki advertises via Bluetooth. Is there any specification on that?

The Bluetooth API does not push state changes by itself, as this doesn’t make any sense if no device is connected. (If you are sending lock actions on the same BLE connection you get the status change ofc.) On the other hand you can’t constantly connect to the Smart Lock via Bluetooth.
So you either have to check the status (via Bluetooth) in some intervall or at an event where the data is needed.

Hi Stephan,
that’s correct. However there must be some mechanism for the Smart Lock to signal that the internal state has changed. How does the bridge notice that the Smart Lock locked? The functionality is there via web hooks and I don’t think that the bridge is connected 100% of the time. My guess that it is somewhere hidden in the manufacturer data advertised, as this does change when the lock is engaged, but there is no documentation on that.

Edit: I now found out, that Nuki apparently sends a counter in the manufacturer data on advertisements.
There are two advertisements which are sent continuously. One, which is 25 bytes long and byte 4-20 contain the Nuki Service UUID. The other one (21 bytes) has a 8 bit unsigned integer counter (byte 14) which is incremented each time the door is locked/unlocked. I believe that’s also the way the Nuki Bridge finds out when the state changed, right? Although this works great it would be cool to also signal a change for the door sensor. It should also increase the counter. Although this behaviour already leaks some information (door state changed/someone at home) I recommend to increase the counter randomly throughout the day. The energy impact by the bridge retrieving a new state should be negligible but it prevents attackers from easily finding out when the lock was triggered.

Hi Henry,

We’re regularly advertising an iBeacon with the UUID of our keyturner service.
The iBeacon also contains 4 bytes for major/minor (which are filled with the nuki id in our case) and the rssi value.

There comes the magic.

Normally, the rssi value within the iBeacon data is -60 (0xC4).
If the status of the smart lock changes in any way, that would trigger a new entry in the activity log, the rssi value within the iBeacon changes to -59 (0xC5) and that triggers the bridge.
Once the bridge has connected to the smart lock and fetched the new status, the rssi value changes back to -60.

The other advertisement (with the counter) you found is HomeKit specific advertisement (defined by apple) and only changes, if the lock status (locked/unlocked) changes.


1 Like

Hi Marc,
thanks, it works perfectly.

After updating to the Beta firmware I still have an issue with the Lock crashing (rebooting) and showing Position Detection while Locking/Unlocking. How can we debug this? It doesn’t happen via the app, but when I manually send commands to the Smart Lock via Bluetooth. The only thing that’s different from the documentation is the app id. I generate it randomly. Is that an issue?

This shouldn’t be an issue.

Can you tell me the bluetooth connection parameters you’re using to connect to the smart lock?
Connection interval, supervision timeout and slave latency.

not sure where to look. I’m just connecting with a bluetooth dongle via a Raspberry Pi. But even if the connection parameters were incorrect and the connection drops, the Smart Lock shouldn’t crash, right?
Any other commands like pairing, Get Keyturner States etc. works and I can be connected to the Smart Lock for 10 seconds without problems. After that the Smart Lock terminates the connection (I think due to battery saving), so stability is not a problem.

Of course it shouldn’t but to reproduce this I’ve wanted to test it exactly with your setup.
Can you send me the whole payload (unencrypted) of your lock action command as a hex byte array?
I’ll try to send the same command to one of our smart locks.

sure. That’s the full unencrypted payload including the app id, nonce and authorisation id.

f2 5c 34 00 0d 00 02 71 96 70 44 00 7b 06 2b 92 f0 98 3c a8 3c 8a b2 71 ec 5f ae 1f 12 7e 9f 50 a4 1c 11 3b 0f 2e 4c 39 20 12 78 d5

Well, I think it’s because of the app id. If I send an app id that is invalid (randomly generated but not paired with) the Smart Lock crashes too. I guess I somehow send an invalid app id but it was set during pairing. Can only registered app ids be used?

So if you send the correct appId, it doesn’t crash?
You’re saying ([…] crashes too […]). What’s the other crash (besides invalid appId) you’re referring to?

I tried to do this with a different appId than from the pairing as well and my test smart locks did not crash with an ivalid appId.
I also tried the same appId than yours (1148229233).

What happens if you use 0 as appId?

I found the issue. It’s not the App ID, it’s the Name sent by the client during pairing (Authorization Data).
What I did is filled the Buffer with spaces after the name. However that seems to crash the Smart Lock during locking/unlocking. I now filled the Buffer with zeroes and it works now.

Therefore if the name looks like this, it crashes:
XX XX XX XX 20 20 20 20 20 20 20 20 …

Thanks for pointing that out.
This has now been fixed with todays 2.4.2 Beta Update.

1 Like

Please mention the RSSI trick in the documentation!