Bluefruit GATT "String" Characteristic Update not working as expected

For CircuitPython issues, ask in the Adafruit CircuitPython forum.

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
LePetitRenard
 
Posts: 15
Joined: Tue Oct 25, 2022 10:24 am

Bluefruit GATT "String" Characteristic Update not working as expected

Post by LePetitRenard »

My project involves an MCU sending data to a smartphone app via BLE GATT. The projects works on ESP32/Arduino Nano boards, and I'm porting to the Adafruit nRF52840 Feather Sense.

The problem is I can't get the BLE Characteristic update to work.

BLE updates are carried out and optimized in the following way. The code is shortened for readability, but this method means all necessary information can be sent in one BLE packet (<20 bytes), at the required high speed:

Code: Select all

void setAdvData() {
    std::string strServiceData = "";		

    strServiceData += (char)(transmission_num & 0xff);        // Lower byte of transmission number
    strServiceData += (char)((transmission_num >> 8) & 0xff); // Upper byte of transmission number
    strServiceData += (char)(temp & 0xff);                    // Lower byte of temperature
    strServiceData += (char)((temp >> 8) & 0xff);             // Upper byte of temperature
    strServiceData += (char)(humid & 0xff);                   // Lower byte of Humidity
    strServiceData += (char)((humid >> 8) & 0xff);            // Upper byte of Humidity

    myCharacteristic.notify(strServiceData);                 // Set characteristic message, and notify client
}
This works with ESP32s, but for Adafruit the Arduino compiler returns the following error:
no matching function for call to 'BLECharacteristic::notify(std::string&)'
My solution was to change strServiceData from type "std::string" to type "String". I then had to further convert it using c_str(), otherwise there would be a similar compilation error:
no matching function for call to 'BLECharacteristic::notify(String&)'

This is the resulting semi-working code:

Code: Select all

void setAdvData() {
    String strServiceData = "";			<=== Changed here

    strServiceData += (char)(transmission_num & 0xff);        // Lower byte of transmission number
    strServiceData += (char)((transmission_num >> 8) & 0xff); // Upper byte of transmission number
    strServiceData += (char)(temp & 0xff);                    // Lower byte of temperature
    strServiceData += (char)((temp >> 8) & 0xff);             // Upper byte of temperature
    strServiceData += (char)(humid & 0xff);                   // Lower byte of Humidity
    strServiceData += (char)((humid >> 8) & 0xff);            // Upper byte of Humidity

    myTestString = strServiceData.c_str();		 <=== Changed here
    myCharacteristic.notify(strServiceData);                 // Set characteristic message, and notify client
}
But, this still doesn't work, at least not correctly.

Doing this conversion now means the MTU size must be increased. This isn't an issue in itself, but the data being sent over on each packet is exactly the same each time and totally wrong.

For instance, the transmission_number, the first 2 bytes in each message are expected to be, "1, 2, 3, 4, 5..." and this is confirmed by Serial.print. Instead '4836' is received as the transmission_number for each message.

I have tried looping the BLE message 10x before each .notify() since the MTU size must now be increased, and something strange happens. To be clear, it now means the String strServiceData is 10x longer, and then a notification is sent.

In this case, the transmission number is still corrupt, but the following bytes: for temp, humidity, etc., now contain the correct data. Except, this is only true for the first 6 loops. The last 4 loops have nonsensical data, and then this repeats. The next 6 semi-work, the next 4 are nonsense. On each of these cycles the corrupt data is the same. That is the 7th, 17th, 27th, etc. BLE message has the exact same wrong data. The same is true for the 8th, 9th, and 10th message, each having their own respective repeating information.

The easiest approach to solve this I think would be to find a way to get std::string, or something of that sort, to work with the BLECharacteristic::notify() function. I think in all the conversions from String to c_str, the data is getting changed and the intended optimization is not working. I don't want to have to change this because (1) it works really well as proven by my previous boards (2) I'll have to rewrite a good part of the Android app

Any help with this would be greatly appreciated.

User avatar
LePetitRenard
 
Posts: 15
Joined: Tue Oct 25, 2022 10:24 am

Re: Bluefruit GATT "String" Characteristic Update not working as expected

Post by LePetitRenard »

I have found a workaround to this issue by using c strings and sprintf. Here is the code should it help anyone else:

Code: Select all

void setAdvData() {

char buffer[20];
  sprintf(buffer, "%c%c%c%c%c%c", 
                        (char)(trans_num & 0xff), (char)((trans_num >> 8) & 0xff), 
                        (char)(temp & 0xff), (char)((temp  >> 8) & 0xff), 
                        (char)(humid & 0xff), (char)((humid >> 8) & 0xff), 

    myCharacteristic.notify(buffer);                 // Set characteristic message, and notify client
}

Locked
Please be positive and constructive with your questions and comments.

Return to “Wireless: WiFi and Bluetooth”