-
Notifications
You must be signed in to change notification settings - Fork 618
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
ArduinoBLE: BTstack's Enable Notifications fails against ArduinoBLE GATT Server #529
Comments
I didn't know anybody is still using this Arduino abstraction. If possible please use the native BTstack API. Anyway, please check if you get an error for the call to device->subscribeForNotifications() Also, please enable the packet logger to see if the Bluetooth communication is correct. See here: https://github.com/raspberrypi/pico-examples/pull/427/files |
What is the native BTstack API? I'm not aware of any other arduino library for the pi pico w that enables bluetooth so this appears to be the only option currently out there. Since I'm not using this directly but using the project that is using this as it's core BT API, I don't really have a way to enable debugging directly as it doesn't appear to have the same options in the make file for that project. |
Well, I was referring to use the Pico SDK that includes BTstack. PacketLogger: there are enablePacketLogger() and enableDebugLogger() in the BTstackManager class. Anyway, please also check if you get an error for the call to device->subscribeForNotifications() |
Per bluekitchen/btstack#529 (comment) Don't run BTstackLib examples in CI
I'll have to spend some time with the pico SDK, haven't dealt with that as I've relied on this arduino library for past projects so it'll be some work to try to move everything to that dev style.
Are you referring to using this library as is? Might have been lost in the original issue report as it was long but this always returns an error until you attempt to read a characteristic. I can attempt to subscribe to a characteristic in a loop forever and it will always return BLE_STATUS_OTHER_ERROR. Once you read the characteristic, that's where you start seeing subscribe callbacks (even though subscribes aren't happening) and never a characteristic notification callback. |
Yes. This call Ok, then let's the packet logger to shed some light on the issue: BTstack.enablePacketLogger() |
Make sure you've enabled |
Here is the debug output. Not really sure what to make of it though.
|
Thanks for the log. If possible, please remove the time stamps from your serial terminal, the conversion tool does not expect them as the HCI log already has time stamps. -- After removing the PC timestamps, you can run the log through btstack/tool/create_packet_log.py to get a .pklg that can be analyzed in Wireshark. Here it is (zipped as GitHub doesnn't accept .pklg files): arduino.pklg.zip -- The Arduino wrapper and your code seem to be ok. The stack first looks and finds the RX characteristic with ATT handles 0x000b - 0x000d:
So we have:
Next, the stack first tries to read the current value of the CCCD but gets an error! Jan 01 11:00:13.453 ATT Send Read By Type Request - Start Handle: 0x000C - End Handle: 0x000D - UUID: Client Characteristic Configuration SEND If the remote side does have a CCCD at handle 0x000D, the ATT_READ_BY_TYPE_REQ should return it. However, it doesn't. Although you've tested with your Android phone, this looks like a bug in the Bluetooth Stack on the NanoBLE. Which one is this? It looks like BTstack uses different, but valid ATT requests to enable notifications, which are handled incorrectly by the Peripheral. -- Could you try with a different Peripheral / different Bluetooth Stack to see if your Central on top of BTstack on Pico works correctly then? Could you ask the developer of the stack on the NanoBLE about this behaviour and provide your log? |
Looks like the NanoBLE33 is running this code here - didn't know that Arduino implemented an LE Host Stack: Maybe the end condition in the loop is off by one or something like that. Could you print:
|
I don't have another peripheral I can test at the moment. Here is the output with that modification from the nano:
|
I think I found it. The attribute->type() only returns BLETypeService (2800), BLETypeCharacteristic (2803) or BLETypeDescriptor (2900), but never 2902. With this if (attribute->type() == readByTypeReq->uuid) is never true for our query - although there's code to explicitly handle 2902 but it's not possible to reach it. Could you try this hack/patch: diff --git a/src/local/BLELocalDescriptor.cpp b/src/local/BLELocalDescriptor.cpp enum BLEAttributeType BLELocalDescriptor::type() const
This let's the CCCD return 0x2902 as type() and should enable the code to handle ATT Read By Type for UUID 2902. |
Reported as arduino-libraries/ArduinoBLE#326 |
I updated the code, slightly modified so it would compile as follows:
No change in behavior. |
This comment was marked as outdated.
This comment was marked as outdated.
That is how the original code looked, just returned the type with no check. |
Oh, the diff didn't survive. The idea was to have the BLELocalDescriptor return 0x2902 if the UUID is 2902, such that this comparison in the ATT.cpp code becomes true:
(as the readByTypeReq->uuid is 2902 and the BLELocalDescriptor should have UUID "2902" as well). Again, a correct way (give the 'cross-layer optimization': ATT.cpp is implementing the logic for GATT) would be to do a switch on attribute->type() and for BLETypeDescriptor, compare the attribute->uuid() to the request UUID. |
Could you also log attribute->type() and paste the output? |
Where do you want me to add that output? It is already in the first output with the updatedATT.cpp file and that hasn't changed from the previous output. |
Btw, it would be convenient to print the attribute->type() as hex. Anyway, when the hack/patch works, it should list type 0x2902 = 10498. When it attribute->type() returns 0x2902, the ATT Read By Type Request should be answered correctly (at least that's what I read in the code) |
Changed the print statement in the ATT.cpp readByTypeReq for loop and get the output below. I do see the expected 2902 value showing up but still no change in behavior. Not sure if there's something farther down the line in the code still having issues.
Generated from this updated code in the ATT.cpp readByTypeReq function.
|
I'm not sure if it would help here, but the latest |
Ok, so the attribute->type is now fixed to 2902, but it's not working. Could you a) provide a new HCI trace from the Pico? b) add more debug output to see if the code after |
@earlephilhower
Or is there some other logging I am able to turn on to help troubleshoot? Code modified to print after if statement:
Results in this output:
Pi PIco Output:
|
Nice. Progress! Here's the packet log for Wireshark Jan 01 12:03:58.760 ATT Receive Read By Type Response RECV With the changes, the ATT Read By Type Request is answered correctly: BTstack learns that the CCCD Handle is 0x000d. Ok, next BTstack sends a write request to enable notifications. Jan 01 12:03:58.761 ATT Send Write Request - Handle:0x000D - F897177B-AEE8-4767-8ECC-CC694FD5FCEE - Value: 0100 SEND Looks good. The Nano responds with: Jan 01 12:03:58.850 ATT Receive Error Response - Attribute Handle: 0x000D - Error Code: Write Not Permitted (0x03) - Write Not Permitted RECV Quick look into the code, it looks like the previous hack broke the write request. and replace BLETypeDescriptor with |
Originally reported this bug to the pi pico arduino library here: earlephilhower/arduino-pico#1735 but was directed to check here for a potential issue/fix as the implementation is based on btstack and the issue could be here. Here is the full content of that issue:
Hardware: Pi Pico W
Library Version: 3.6.0 (earlephilhower/arduino-pico)
I am not sure if it I am doing something wrong with the Bluetooth implementation or this is an actual bug but it does appear the callbacks are not working as expected in the current Bluetooth stack.
I am connecting to a Nano33BLESense that has 1 characteristic that is setup to notify and writes a new value every 5 seconds. I have tested the notify options with an android app to verify notification updates are working on the nano
I modified the LECentral code slightly to try to get updates from characteristic subscriptions but these callbacks do not appear to work.
Basic state order:
1-2 work as expected
3. Subscribe callback will always return BLEState of BLE_STATUS_OTHER_ERROR when you attempt to subscribe, no matter how many times you attempt. If you perform a read of the characteristic, then subscribe, you will receive a subscribe call back status of BLE_STATUS_OK
4. Never receives any callback even after a subscribe callback of BLE_STATUS_OK
Additional testing on just reading the characteristic value every second resulted in a subscribe callback every time a read callback was completed. No further subscriptions are occurring past the very first successful subscription but a successful read callback in turn receives a subscription callback.
The gattCharacteristicNotification is never called despite successful subscription callback status and continual update of the characteristic in the nano.
Console Output showing connection and initial subscription failure, read, then success:
One second reads showing a updates from nano but also a seemingly random subscription callback during every read and no gattCharacteristicNotification ever received:
Pi Pico W Code:
NanoBLE33Sense Code:
The text was updated successfully, but these errors were encountered: