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

Bonding at initialize() or reading Char that requires bond #32

Closed
Rawa opened this issue Oct 4, 2018 · 18 comments
Closed

Bonding at initialize() or reading Char that requires bond #32

Rawa opened this issue Oct 4, 2018 · 18 comments
Assignees
Labels
Milestone

Comments

@Rawa
Copy link

Rawa commented Oct 4, 2018

Hello again!

Thanks for you last fix, it solved my issue. :) I've ran into another strange case. Let's say you want to connect to a device and bond that device. What is the flow for this? I've tried several different ways but ran into different issues.

  • enqueue a bond in the initialization?
/** BleManagerGattCallback **/
        override fun initialize() {
            super.initialize()
            createBond().enqueue()
            readCharacteristic(bondCharacteristics).with(bondDataCallback).enqueue()            
            readCharacteristic(modeCharacteristics).with(modeCallback).enqueue()
            setNotificationCallback(modeCharacteristics).with(modeCallback)

        }
        ...

In the case above everything below createBond() will be ignored.

  • read a characteristic that require bonding, and handle onBondingRequired?
        override fun initialize() {
            super.initialize()
            readCharacteristic(bondCharacteristics).with(bondDataCallback).enqueue()           
        }
        ...

In this case I get:

E/BleManager: onCharacteristicRead error 8

It does not seem to match the BluetoothGatt.GATT_INSUFFICIENT_AUTHENTICATION, see https://github.com/NordicSemiconductor/Android-BLE-Library/blob/master/ble/src/main/java/no/nordicsemi/android/ble/BleManager.java#L1316
However, it will log in the nRF Logger: Error (0x8): GATT INSUF AUTHORIZATION.

Or is the right way to go to create a bond after connect done callback and then do additional reading for characteristics that require bond?

@philips77
Copy link
Member

Hello!

So I was hoping, that both approaches are working. They both should. If not, there's a bug.
Do you have a small app that I could use for debugging? I would really like to test it. I can try with some samples from our SDK.

Any idea why the other requests below createBond() are ignored? Did you try to debug it?

Regarding error 8, it can be found here: https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/master/stack/include/gatt_api.h#36

@philips77 philips77 self-assigned this Oct 4, 2018
@philips77 philips77 added the bug label Oct 4, 2018
@philips77 philips77 added this to the Version 2.0 milestone Oct 4, 2018
@Rawa
Copy link
Author

Rawa commented Oct 4, 2018

Yes, I have an example. I need to clean it up a bit but I can provide it later today.

@Rawa
Copy link
Author

Rawa commented Oct 4, 2018

https://github.com/Rawa/Android-BLE-Library-32

Currently showcases the last bug, producing the "error 8", do produce the other on you can just add the bondRequest and the rest of the request will be dropped. You'll have to change the model and the BluetoothServices to match you device. I've tried slimming it down as much as possible while still making it usable. If you have any questions feel free to ask me.

@philips77
Copy link
Member

Thanks! Do you have any HEX file that I could quickly drop on my nRF5x DK, or you are working on some special hardware? I can use any of the samples, or replicate it using 2 Android phones and nRF Connect, so no problem if that's not possible.

@Rawa
Copy link
Author

Rawa commented Oct 4, 2018

We using a nRF52832. However, I can not provide a HEX file since we are not the producer of the firmware and it is integrated into the hardware we are using.

@Rawa Rawa changed the title Bonding onConnect Bonding at initialize() or reading Char that requires bond Oct 4, 2018
philips77 added a commit that referenced this issue Oct 11, 2018
@philips77
Copy link
Member

Hi, so with the changes I made the createBond().enqueue() in initialization should work now. Also, I wonder what happens when you will use the latter approach. It will now go into the if statement, as I added == 8 there, but will the bond be started? Will library repeat reading after bond is complete? Could you verify this?

Also, in the new version I removed dependency to nRF Logger. The log(...) method will do nothing now, so you have to override it to get logs with lower then warning priority.

@philips77
Copy link
Member

I can release the version beta6 (I think I should start moving to gamma now ;) ) tomorrow if it works for you.

@Rawa
Copy link
Author

Rawa commented Oct 11, 2018

Hi! I'll try this out tomorrow and i'll come back to you with an answer when I have access to all the equipment

@philips77
Copy link
Member

Hi, did you have time to look into that?

@Rawa
Copy link
Author

Rawa commented Oct 12, 2018

Hello @philips77!

Sorry for late response. I've been very busy today so this got put off a bit. But yes, I can now confirm that createBond().enqueue() does work as intented! The second example do not work, (reading a bond characteristic straight away) does not work.

I also had some troubles running the project after importing it. Since I'm using the Jetifier and Androidx the annotations could not be loaded. Had to manually search and replace to get your code base to run. Working with the library do you know if there is a simpler way?

@philips77
Copy link
Member

What phone and Android version were you testing on? I'm trying to get GATT INSUF AUTHORIZATION error.

Regarding annotations, jetifier should port android.support annotations to androidx. At least I thought so.
I've also added (1709633) many more annotations, with range, type, etc.

I will release beta6 now and try porting nRF Blinky app to AndroidX to see how it works.

@philips77
Copy link
Member

2.0-beta6 released.

@Rawa
Copy link
Author

Rawa commented Oct 15, 2018

@philips77
I no longer seem to be able to reproduce the error. However, the still same applies:

Galaxy S9:

override fun initialize() {
            super.initialize()
            readCharacteristic(modeCharacteristics).with(modeCallback).enqueue()
            readCharacteristic(bondCharacteristics).with(bondDataCallback).enqueue()

            setNotificationCallback(modeCharacteristics).with(modeCallback)
            enableNotifications(modeCharacteristics).enqueue()
        }

Nothing happens after readCharacteristics(bondCharacteristics) without explicitly doing createBond().enqueue() before reading from the bond characteristic. So basically connect never ends up finishing. It seems like it ends up blocking because it is unable to read from the bonded characteristic.

Same is issue reproducible on a Google Pixel XL. I have some other phones I can test on if needed as well (e.g Oneplus 6, and P20 Pro)

Further testing yields in the same result. E.g Try and connect to a device, then (after connected) read from a characteristic that requires bond. It will lock up all reads from that device and not create a bond or call the onBondingRequired callback.

I'm not sure what the desired behavior is, if reading a char that needs bond should create a bond or not. I'm just assuming it shouldn't lock up the queue without producing any error.

@philips77
Copy link
Member

Android should initiate bonding automatically. The lib should proceed (repeat the last operation (on older Android versions) or wait until Android does it on its own (on newer)) after the bond is complete. I'll look into it. Perhaps there is something that should be done on the peripheral side? I'll test against another Android phone running nRF Connect and some of our samples from the SDK.

@philips77
Copy link
Member

Hi @Rawa,
First of all, nice piece of code this project of yours. We didn't start with Kotlin yet, and I have troubles with understanding, that good it is :) I already know Swift, but Kotlin, with those hundreds of extensions and inline functions, is the next level. I hope we can start the Kotlin adventure soon.

Secondly, I tried your app, as I said, with another Android phone running nRF Connect. Your app was running on Pixel 2 with Pie, while nRF Connect on Nexus 5X with Android 8.1. I set up 2 services, and added 3 characteristics, based on MyBleManager. The Pairing characteristic had Read encrypted permission (requires just works bonding). Your app connected, initiated bonding by reading this characteristic, paired (I had to click 2 times Pair on the target phone and once on master phone), read everything, reported Ready and read Pairing again. Here are logs:


D/BluetoothAdapter: isLeEnabled(): ON
D/BluetoothLeScanner: onScannerRegistered() - status=0 scannerId=8 mScannerId=0
D/DeviceFragment: Address: 43:86:C5:B2:94:F6
D/DeviceManager: BeforeConnect: false
V/BleLibrary: Connecting...
D/DeviceManager: onDeviceConnecting
D/BleLibrary: gatt = device.connectGatt(autoConnect = false, TRANSPORT_LE, LE 1M)
D/BluetoothGatt: connect() - device: 43:86:C5:B2:94:F6, auto: false
D/BluetoothGatt: registerApp()
D/BluetoothGatt: registerApp() - UUID=75067124-38be-4a39-8e76-77e0af918e1f
D/BluetoothGatt: onClientRegistered() - status=0 clientIf=9
D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=9 device=43:86:C5:B2:94:F6
D/BleLibrary: [Callback] Connection state changed with status: 0 and new state: 2 (CONNECTED)
I/BleLibrary: Connected to 43:86:C5:B2:94:F6
D/DeviceManager: onDeviceConnected
D/BleLibrary: wait(300)
V/BleLibrary: Discovering services...
D/BleLibrary: gatt.discoverServices()
D/BluetoothGatt: discoverServices() - device: 43:86:C5:B2:94:F6
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=6 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)
D/BluetoothGatt: onSearchComplete() = Device=43:86:C5:B2:94:F6 Status=0
I/BleLibrary: Services discovered
V/BleLibrary: Primary service found
D/DeviceManager: onServicesDiscovered

// Reading Pairing initiated
V/BleLibrary: Reading characteristic 00001820-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.readCharacteristic(00001820-1212-efde-1223-785feabcd123)
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=36 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=6 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 7.5ms, latency: 0, timeout: 5000ms)

// Device started to bond
D/BleLibrary: [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDING (11)
D/DeviceManager: onBondingRequired
D/BleLibrary: [Broadcast] Action received: android.bluetooth.device.action.PAIRING_REQUEST, pairing variant: PAIRING_VARIANT_PASSKEY_CONFIRMATION (2)

// Automatically, when devices are bonded, the Android returns read value (even before state is BONDED)
I/BleLibrary: Read Response received from 00001820-1212-efde-1223-785feabcd123, value: (0x) 01
D/DeviceManager: onBondChanged

// The lib proceeds with next read (FunctionMode)
V/BleLibrary: Reading characteristic 00001554-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.readCharacteristic(00001554-1212-efde-1223-785feabcd123)

// Finally the broadcast comes, notifying that we are bonded
D/BleLibrary: [Broadcast] Action received: android.bluetooth.device.action.BOND_STATE_CHANGED, bond state changed to: BOND_BONDED (12)
I/BleLibrary: Device bonded
D/DeviceManager: onBonded

// But the lib just continues to receive requested data
I/BleLibrary: Read Response received from 00001554-1212-efde-1223-785feabcd123, value: (0x) 06-00
D/DeviceManager: onFunctionModeChanged: Init()
D/BleLibrary: gatt.setCharacteristicNotification(00001554-1212-efde-1223-785feabcd123, true)
D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001554-1212-efde-1223-785feabcd123 enable: true
V/BleLibrary: Enabling notifications for 00001554-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
I/BleLibrary: Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
I/BleLibrary: Notifications enabled
D/BleLibrary: gatt.setCharacteristicNotification(00001591-1212-efde-1223-785feabcd123, true)
D/BluetoothGatt: setCharacteristicNotification() - uuid: 00001591-1212-efde-1223-785feabcd123 enable: true
V/BleLibrary: Enabling notifications for 00001591-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.writeDescriptor(00002902-0000-1000-8000-00805f9b34fb, value=0x01-00)
D/BluetoothGatt: onConnectionUpdated() - Device=43:86:C5:B2:94:F6 interval=36 latency=0 timeout=500 status=0
I/BleLibrary: Connection parameters updated (interval: 45.0ms, latency: 0, timeout: 5000ms)
I/BleLibrary: Data written to descr. 00002902-0000-1000-8000-00805f9b34fb, value: (0x) 01-00
I/BleLibrary: Notifications enabled

// Device is ready
D/DeviceManager: onDeviceReady
D/DeviceManager: connect Success

// You read Pairing again in connect's done callback
V/BleLibrary: Reading characteristic 00001820-1212-efde-1223-785feabcd123
D/BleLibrary: gatt.readCharacteristic(00001820-1212-efde-1223-785feabcd123)
I/BleLibrary: Read Response received from 00001820-1212-efde-1223-785feabcd123, value: (0x) 01
D/DeviceManager: onBondChanged

@philips77
Copy link
Member

Does it work on an iPhone? Is your device returning the correct error when you try to read protected characteristic? Shouldn't it be INSUF AUTHENTICATION, not INSUF AUTHORIZATION? Are you able to sniff it, or get the HCI logs from the phone?
Could you also try Proximity sample from our SDK, which is also using automatic just-works pairing when the app tries to write alert level.

@Rawa
Copy link
Author

Rawa commented Oct 17, 2018

Thank you, I quickly made that project together so it is not all clean but readable enough I hope. Working with Kotlin makes everything so much easier. I've been doing Kotlin for almost a year now (coming from a Java background) and I can tell you it has many benefits, and you should definitely consider switching to it.

I reproduced your test case, setting up a phone provding the services and indeed it does bond. I'm starting to believe this issue probably is caused by our device. I'm gonna close this issue for now until I can find something that points towards otherwise.

Thank you again for your great work with this library.

@Rawa Rawa closed this as completed Oct 17, 2018
@philips77
Copy link
Member

Great! We are then almost ready with releasing it as 2.0-final. I'm just busy fixing bugs in DFU, I didn't look there since long time... Thanks for the help with the library!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants