Received status 0xF1 on GDIO after lock action (Smart Lock v1)

Hey there,

Has anyone ever received a status message (command identifier 0x0E) with a status 241 (0xF1)? The documentation only refers to 0x00 (complete) and 0x01 (accepted).

When sending a lock action (0x0D) to my Smart Lock v1 on USDIO (encrypted) the flow completes as usual (accepted, keyturner states, …, completed) on USDIO. After the last message on USDIO the Smart Lock sends an additional status command (0x0E) with status 0xF1 on GDIO (unencrypted): 0e00f1a328

On some occasions this status can even interrupt the flow on USDIO (never receiving status complete). However, this I only have seen happening when sending a lock command to an already locked Smart Lock or unlock for an unlocked Smart Lock.

Looking forward to some insights.

Best Regards,
Peter

Hi Peter,

It looks like you’ve paired your device as a bridge and not as an app.
Not sure if you did that on purpose.
During pairing process the “ID type” is passed on command 0x0006 and tells the Smart Lock what kind of authorization you’d like to create.
Please note that there can only be one bridge paired so if you already have a Nuki Bridge paired, you’ll overwrite that pairing.

The status 0xF1 is dedicated for the bridge only to notify it about a status change.
As the communication between app and Smart Lock is encrypted the bridge can only forward encrypted commands but is unable to decrypt them.
So in order for the bridge to be aware of any status change (and to keep its HTTP API up to date) it is notified by the Smart Lock, that it should update the Smart Locks status.

I’ll have a look at the missing COMPLETE in your mentioned case as this should not happen.
Will update you on that.

best,
Marc

1 Like

Hey Marc,

Excellent, that makes sense. And yes, in this instance it was intended to use a bridge pairing.

So essentially status 0xF1 is equivalent to the notification flag (LSB of TX) in the advertisement, meaning upon receiving this I should request the keyturner states for an update? If so, why not just use the advertisement? Are there more (publicly) undocumented status values?

If this status is only meant for the bridge, if it cannot decrypt the communication when forwarding commands, why am I receiving it when using the shared secret of the bridge pairing and thereby being able to read the communication? Moreover, how come I am receiving this status when sending an (un-)lock action to an already (un-)locked Smart Lock? The status would not change, would it? Although, the last lock action/trigger/completion status could. I would expect similar behavior for the Opener as well, but I don’t see the status message there at all. So does this only apply to the Smart Lock?

Opening a can of worms here: How does the Smart Lock know, if a command is being bridged and therefore should send the aforementioned status message? Is this where the duplicate authorization ID for encrypted messages (PDATA and ADATA) comes into play? According to my testing the ID specified in PDATA indicates which shared key was used to encrypt the message. The ID specified in ADATA determines what shared key to use to encrypt the response. However, this does not seem to be documented publicly. Specifying an invalid authorization ID in ADATA still produces a response, although I would expect an authentication error.

So when relaying data from the app remotely via the bridge, the app would initiate the connection by asking the bridge to send the first command with its own shared key, thereby indicating to the Smart Lock, that it needs to send an unencrypted status message on GIDO. Does that work out?

One last one: It also seems to be required to wait for that status message before sending consecutive commands, otherwise they essentially will be ignored resulting in a timeout. Is this intended?

Well, that’s a lot of questions. Sorry for that. :slight_smile: Just trying to improve my custom BLE implementation and error handling. Thanks for being open about this.

Best Regards,
Peter

Hi Peter,

The reason for not waiting for the advertisement is speed & efficiency. The bridge is already connected so it can retrieve the information immediately instead of waiting for the disconnect, scan for the advertisement, connect again and retrieve the info.

The Smart Lock does not care who the originator of the status change is. If the bridge is connected it is informed about the status change via GDIO. Keeps the flow simple.
It may also happen that the bridge is connected and the status is change does happen because of a manual turn on the Smart Lock or by using the button on the Smart Lock.

Even if the Smart Lock is already unlocked and you’re unlocking it again this produces a Log Entry and therefore a change on the Smart Lock. The bridge does also update the timestamp in HTTP APIs /list in that case.

As you correctly pointed out, the ID in the unencrypted part is necessary for the Smart Lock to know which app’s key to use for decryption and to not need to try all the keys.

Regarding consecutive commands:
Yes, you always need to wait for the command to complete.
So if you are requesting a single info (e.g. challenge) you need to wait for either the expected response (challenge) or an error response.
If you’re requesting a list (e.g. user list, activity log) or a command that is intended to take longer (e.g. lock action) you need to wait for either a Status Complete (0x00) message or an error response before sending the next one.

The can of worms needs to stay closed at the moment as the information about how bridging works is not part of the public documentation yet.
However, your request is noted and will be part of future decisions about the public documentation.

best,
Marc

Hey Marc,

Thanks for the elaborate answer. I was just curious about the unknown status code. I understand that some specifications cannot be part of the public documentation (looking forward to it though, should that change at some point). :slight_smile:

Yes, you always need to wait for the command to complete.

This I am aware of. However when connecting as a bridge, the additional status 0xF1 may or may not be sent depending on whether the status has changed. The problem I am facing now is that sending a consecutive command after receiving COMPLETE will fail if the Smart Lock is about the send 0xF1 but the message has not yet been received. Hence, I need to place an additional timeout between consecutive command to check, whether I receive 0xF1.

Regarding the opener I did not see status 0xF1 on GDIO yet. Is this a Smart Lock only thing then?

Best Regards,
Peter

Hi Peter,

The status 0xF1 should be sent by the opener as well if the firmware is up to date.

I see why this is causing problems in your case and actually the problem is that your application is paired as a bridge but not forwarding commands like a bridge would. And this is - as I’ve mentioned - not documented at the moment.
So unfortunately the timeout is the only solution at the moment if you are paired as a bridge.

However this should only cause problems with Smart Lock 1.0. The BLE stack on later devices is a different one (capable of multiple connections as well) and not immediately handling 0xF1 should not cause problems there.

Just to be able to think of other solutions:
The only reason for your application to be paired as a bridge is to clear the notification flag (LSB of TX) right?
So if there would be an option to clear the TX flag from a “normal” authorization your application could be paired as an app as well?

best,
Marc

Hey Marc,

Precisely. Having a command solely for clearing the notification flag from any pairing ID type would indeed help and even improve things, as using a bridge pairing does come with some more caveats, such as not being able to retrieve the full list of authorizations.

The status 0xF1 should be sent by the opener as well if the firmware is up to date.

I’ll double check on that.

Best Regards,
Peter