Open savejeff opened 11 months ago
Hi there. I did a quick check and it looks like we didn't add support for sending notifications to the Arduino Wrapper.
Is there a chance BTstack could be used directly without this additional wrapper in the Arduino world? As a quick hack, I guess you could call att_server_notify directly although you might get a "cannot send right now". If that works, you should call att_server_request_to_send_notification() to register a callback that is called when it's safe to call att_server_notify().
On the Pico W, you can directly use BTstack as part of the C/C++ SDK and all examples are ready to use, too.
Hi, thanks for the quick response.
I have previously looked into btstack itself but if found it quite complicated to get what I want. the gatt config file etc is IMHO not as elegant as the ESP32 BLE wrapper. I think it would be very beneficial for the wider Arduino community to offer a Wrapper for BLE functionality similar to the ESP32 one. I'm personally quite experienced with embedded development, but I still prefer to use the Arduino libraries, because they make it easy to get started and that is I think the most important thing for more people to get into embedded development.
As there is already the mentioned wrapper for BTstack I would be very grateful if it would be extended to have the utmost basic GATT functionality for the embedded device action as a BLE "Server" a Remote device can connect to. I should include these features:
I have also looked through the BTstack example but there is not really a basic example that shows how to use the above-listed functionality. Especially for the notify feature i had a hard time finding an example code
Hi @savejeff.
BTstack did initially only support GATT DB configuration via the .gatt file as it requires no RAM at run time. We later added the option to build the GATT DB in memory programmatically.
If you want to extend the existing Arduino Wrapper, you're welcome to do so.
A Characteristic can support Read, Write and/or Notify. UART simulation is usually done using ATT Write without Notify and sending ATT Notifications. You get the writes via the existing callback. To send, you'll need to call att_server_request_to_send_notification() with a btstack_context_callback_registration_t object to store your request. When you get the callback, you can then call att_server_notify().
The GATT Server is documented here: https://bluekitchen-gmbh.com/btstack/#profiles/#gatt-server The gatt_streamer_server example shows how to send as fast as possible when notifications get enabled.
with the new generation of embedded processors like the ESP32 and RP2040, the ram is less of a problem. I prefer clean easy to read and well maintainable code over memory or flash optimization. I often have projects where i have different variants of the base code that is reconfigured through #ifdefs and "setting"-variables. the programmatic approach is very helpful here
A Characteristic can support Read, Write and/or Notify. UART simulation is usually done using ATT Write without Notify and sending ATT Notifications. You get the writes via the existing callback. To send, you'll need to call att_server_request_to_send_notification() with a btstack_context_callback_registration_t object to store your request. When you get the callback, you can then call att_server_notify().
Before putting in a weekend of getting into btstack and trying to implement it myself, would i be possible for a dev already familiar with the code to implement it. it should like quite a straightforward implementation if one knows how to do it.
Im mainly using ESP32 for my projects/products, but i don't like that i am that dependent on a single manufacturer (the stm32 users learned why this i a bad idea during the chip shortage 😅). And thus I tried to add RP2040 support to my firmware, and currently, I'm only missing the BLE implementation.
I it would be helpful i could define the interface and test code for the Wrapper, then only the btstack background functionality would need to be implemented. I would really love to have something very close to how the ESP32 arduino core has implemented it.
Talking about vendor lock-in, BTstack is all about being portable, as you can run the same code on POSIX & Windows desktops, microcontrollers, esp. ESP32 and Pico W without any changes.
Yes, an interface for the Notify would be nice. Please keep in mind that a) we need to call att_server_request_to_send_notification() to let the stack know that the app wants send a notification, b) it should be malloc free, at least I don't want to allocate memory for data from the application.
I hit the same problem and landed here looking for a solution. Trying to follow mringwal advice, I found a simple way of doing this without modifying the Arduino library, although it won't work 100% of the time.
Create a global variable in your Arduino program to hold the connection handle.
hci_con_handle_t con_handle;
You will obtain the handle and save it during the Connect event (callback):
void deviceConnectedCallback(BLEStatus status, BLEDevice *device) {
switch (status) {
case BLE_STATUS_OK:
con_handle = device->getHandle();
Serial.println("Device connected!");
break;
default:
break;
}
}
newCharValue
is the new value of your characteristic (assuming String):
bool notify_client_characteristic_changed(String newCharValue){
//att_server_request_can_send_now_event(con_handle);
if (att_server_can_send_packet_now(con_handle)){
uint8_t buffer[256];//create a buffer large enough
newCharValue.toCharArray((char*)buffer, sizeof(buffer));//Convert the string to a char array and put it in the buffer
att_server_notify(con_handle, characteristicHandle, buffer, newCharValue.length());//push the new value to the client
Serial.println("Notification sent");
return true;//success
}else{
Serial.println("Client busy. Could not send");
}
return false;//failed
}
The characteristicHandle
above is the value returned by BTstack.addGATTCharacteristic
when you register your characteristic.
Now, this may fail, for instance, if the Client is busy when we try to push the notification
.
The official way of avoiding this failure is by calling att_server_request_can_send_now_event(con_handle);
, which will put a special message in the packet handler when the client is ready to receive the notification. When you receive that message, you call the function above and it should work. But the packet handler is inside the Arduino library, so doing a full implementation requires changes to it. The solution presented here is simple and should work most of the time.
To me sure, does you code implement the equivalent of this:
// set Characteristics and notify client
pCharacteristic_UART_TX->setValue((uint8_t*)buff, len);
pCharacteristic_UART_TX->notify();
It looks very similar, with the exception that your code seems to be storing the new data in the characteristic and then pushing a notification to the client. If the characteristic is defined as Read / Notify, the client would have an opportunity to read it later, if required. In the code that I showed, the characteristic value is not stored, so if the intention is to allow the client to read it at a later time, it has to be stored somewhere (this is trivial to do, but my code does not include it). And like I mentioned, the "notify" part of my code is not very robust (it may fail)
Hi, I'm trying to get the Arduino Wrapper for BTstack working to send data to a connected client (for example Android Smartphone) I want to get the quasi-standard UART Service working to send data bi-directional. I first asked this here on the alternative Arduino RP2040 Core, but i was told this Wrapper was also part of the btstack project. Is that the case? i have a hard time finding this code this repo.
anyway here the original problem I'm working on.
for this i have these two Characteristics:
The problem is, that i cant find functionality to write to the pCharacteristic_UART_TX (which should then notify the connected client that the characteristic has changed)
In general, how can i write to created characteristics created with addGATTCharacteristicDynamic?
I know the library is still under development, i looked at this around half a year ago, and there seemed to be some changes, but i still can't find this functionality. Am i overlooking something? I feel like this functionality of having a device with a readable characteristic that is updated with sensor data is pretty much the basic use case for BLE GATT.
I also looked at the underlying btstack library but its far too complicated and i would rather wait for the arduino wrapper to get the functionality i need.
here equivalent code written for the ESP32 as a reference