Closed Maragues closed 3 years ago
Hi, you are right. There is another case that I didn't discuss in my article. I happened to run into it as when this week when I was playing with the Omron X4. I just published version 2.0.9 of Blessed that addresses this issue.
However, it is a tricky issue. The Omron is the first device I have seen that does a 'peripheral initiated bond request' that is not done directly after connecting. In your case the same is happening:
So I put a fix in now that checks if we are bonding whenever a new command is about to start. If so, it pauses the queue until bonding succeeds.
This is however, not a 100% foolproof fix. As in your case, the discoverServices() command has already started. Luckily in your case, it still succeeds so no issues. This way of triggering a bond is not desirable. It is better to have the bonding start by Android because of a GATT authorization error. Apple also recommends this approach. But I guess in your case, and mine, we cannot control the peripheral firmware so we just have to deal with it.
Thank you very much for a detailed answer.
Fortunately in my case, I can ask our firmware team to look into this. The product is in early development stage, so hopefully we can improve the behavior.
Answer from firmware dev
I had seen that Apple recommended that approach of having the bonding start from the phone upon GATT authorization error . However the way we do bonding is the way it is (poorly) documented in the ESP32 BLE stack documentation. What it does behind the scene is not documented anywhere I could find. Until now, I did not even know if it actively requested bonding or waited for the phone to ask. Now I know :disappointed:. Now I don't know if doing as Apple recommends is just outright impossible on the ESP32 or if it's possible but not well documented.
Do you happen to know where to find this documentation 😅 ?
On a different topic, I tested the fix on Blessed. Here are the logs
Non-bonded Balance
12:35:30.744 8898-8898 BluetoothPeripheral: connect to 'MyBalance' (...) using TRANSPORT_LE
12:35:30.772 8898-8898 BluetoothPeripheral: peripheral '...' is connecting
12:35:34.883 8898-8961 BluetoothPeripheral: connected to 'MyBalance' (NONE) in 4,1s
12:35:34.887 8898-8898 BluetoothPeripheral: discovering services of 'MyBalance' with delay of 0 ms
12:35:35.001 8898-8898 BluetoothPeripheral: starting bonding with 'MyBalance' (...)
12:35:35.030 8898-8898 BluetoothPeripheral: pairing request received: PAIRING_VARIANT_CONSENT (3)
12:35:35.347 8898-8961 BluetoothPeripheral: connection parameters: interval=7.5ms latency=0 timeout=5s
12:35:35.821 8898-8961 BluetoothPeripheral: discovered 7 services for 'MyBalance'
12:35:35.823 8898-8898 BluetoothHandler: connected to 'MyBalance'
12:35:35.824 8898-8898 BluetoothPeripheral: bonding is in progress, waiting for bonding to complete
12:35:35.825 8898-8898 BluetoothPeripheral: bonding is in progress, waiting for bonding to complete
12:35:35.916 8898-8961 BluetoothPeripheral: connection parameters: interval=15.0ms latency=0 timeout=0s
12:35:36.681 8898-8898 BluetoothCentralManager: other scan still active, stopping scan
12:35:36.693 8898-8898 BluetoothCentralManager: scan stopped
12:35:36.712 8898-8961 BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=10 mScannerId=0
12:35:36.718 8898-8898 BluetoothCentralManager: scan started
12:35:37.563 8898-8898 BluetoothPeripheral: bonded with 'MyBalance' (...)
12:35:37.567 8898-8898 BluetoothPeripheral: requesting MTU of 185
12:35:37.620 8898-8898 BluetoothHandler: new MTU set: 128
12:35:37.628 8898-8898 BluetoothPeripheral: requesting connection priority HIGH
12:35:37.788 8898-8961 BluetoothPeripheral: connection parameters: interval=11.3ms latency=0 timeout=5s
12:35:38.133 8898-8898 BluetoothPeripheral: reading characteristic <...>
12:35:38.164 8898-8898 BluetoothHandler: Received battery level 99%
12:35:38.195 8898-8898 BluetoothHandler: SUCCESS: Notify set to 'true' for ...
Already bonded
12:39:53.917 11450-11450 BluetoothPeripheral: connect to 'MyBalance' (...) using TRANSPORT_LE
12:39:53.922 11450-11450 BluetoothPeripheral: peripheral '...' is connecting
12:39:54.056 11450-11450 BluetoothCentralManager: popup hack completed
12:39:54.060 11450-11485 BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=12 mScannerId=0
12:39:54.065 11450-11450 BluetoothCentralManager: scan started
12:39:54.263 11450-11485 BluetoothPeripheral: connected to 'MyBalance' (BONDED) in 0,3s
12:39:54.264 11450-11450 BluetoothPeripheral: discovering services of 'MyBalance' with delay of 0 ms
12:39:54.790 11450-11485 BluetoothPeripheral: connection parameters: interval=7.5ms latency=0 timeout=5s
12:39:55.319 11450-11485 BluetoothPeripheral: discovered 7 services for 'MyBalance'
12:39:55.324 11450-11450 BluetoothHandler: connected to 'MyBalance'
12:39:55.331 11450-11450 BluetoothPeripheral: requesting MTU of 185
12:39:55.354 11450-11450 BluetoothHandler: new MTU set: 128
12:39:55.358 11450-11450 BluetoothPeripheral: requesting connection priority HIGH
12:39:55.389 11450-11485 BluetoothPeripheral: connection parameters: interval=15.0ms latency=0 timeout=0s
12:39:55.562 11450-11485 BluetoothPeripheral: connection parameters: interval=11.3ms latency=0 timeout=5s
12:39:55.863 11450-11450 BluetoothPeripheral: reading characteristic <...>
12:39:55.890 11450-11450 BluetoothHandler: Received battery level 99%
12:39:55.923 11450-11450 BluetoothHandler: SUCCESS: Notify set to 'true' for ...
Ok, so it looks like the fix works. Right?
As for documentation for your firmware engineer: https://developer.apple.com/accessories/Accessory-Design-Guidelines.pdf
Quote from page 155:
The accessory should not request pairing until an ATT request is rejected using the Insufficient Authentication error code. See the Bluetooth 4.0 specification, Volume 3, Part F, Section 4 for details.
If, for security reasons,the accessory requires a bonded relationship with the Central,the Peripheral should reject the ATT request using the Insufficient Authentication error code, as appropriate. As a result, the Apple product may proceed with the necessary security procedures.
Yes, I'll close the issue
Thank you very much for your work 🙏🏻
Hi, after reading your article on bonding, I wanted to check how you had implemented the following constraint:
It seems to be very important, since you remark it again at the bottom:
I'm working on a weight balance that requires bonding, so I tweaked a bit the example app to scan for it and establish a connection
My surprise was, you don't seem to respect the advice on the article. Here are the relevant logs
Did I misunderstood something from your article?
Since you can't know beforehand if a device requires bonding or not, Is it just not possible to halt service discovery until bonding is completed?
I also checked on a BLE device that doesn't require bonding, and you don't get any
ACTION_BOND_STATE_CHANGED
broadcast. Which means, you can't block service discovery until you know the bonding state, because you won't get any event when the BLE device doesn't require bonding.Also, nothing prevents the clients of blessed to attempt to read/write on a characteristic while bonding is ongoing.
Looking forward to your answer. Thank you very much for your work and for the articles, they really helped me grasp the concept.