[closed] BluetoothLE utf encoded string in too human readable string

Dear, I m working app with bluetooth BLE where I need too send a long string with these arguments

  • serviceUuid (text) — The unique identifier of the service passed in the read or register call.
  • characteristicUuid (text) — The unique identifier of the characteristic in the read or register call.
  • utf16 (boolean) Send the string encoded as UTF-16 little endian (true) or UTF-8 (false) code points.
  • values (list) — A list of values to write to the device.

And this is what I get on the other end

void onWrite(BLECharacteristic* pCharacteristic) {
std::string value = pCharacteristic->getValue();
Serial.println(pCharacteristic->getValue().c_str());

The problem is when I print it... I not getting the whole string.

Soo what I have to do is use a loop and convert/print each byte from the .data() method of std::string.

But I cannot get it to work. Correct me if I am wrong... I have too convert the "String value" from the std:: string methode (Question: Do I not lose the rest of my string) and put it in a byte array and than somehow convert it to a readable string. Soo I went form UTF-8 string -> Bytes -> ASCII string I believe.

Can anybody help me too get started with this. It would be very much appreaciated.

post your code.

you could create a complete output string using sprintf() with \n terminator

Are there any null characters in the characteristic value? (When sending UTF-16, there definitely can be null bytes, and if the boolean utf16 flag is zero, that's a null byte too.)
If so, there are two places where it will go wrong: the std::string constructor you're using copies its value from a C-string, so it stops reading as soon as it encounters the first null byte. To include any null characters, use the constructor that takes a pointer to the string and the number of characters:

std::string value { pCharacteristic->getValue(), pCharacteristic->valueLength() };

Similarly, Serial.println() also stops after the first null byte. This is a sensible thing to do, since (IIRC) the serial monitor uses UTF-8 and doesn't expect null. If you want to send all characters, including null, you can use

Serial.write(value.c_str(), value.size());

For dealing with UTF-16, you probably want to use std::u16string, not std::string.

Other than that, you'll have to post a minimum example, leave out the BLE stuff, instead of using pCharacteristic.getValue(), store one of your packets in a character array.

I don't have they property "valueLength()", I found this...

size_t BLECharacteristic::getDataLength() {
    portENTER_CRITICAL(&m_valMux);
    size_t len = m_value.length();
    portEXIT_CRITICAL(&m_valMux);

    return len;
}

I tried it but nothing's coming out of

std::string value{ pCharacteristic->getValue(), pCharacteristic->getDataLength() };
Serial.write(value.c_str(), value.size());

Ooo. I diden't readed quit well... the Serial.write was for sending it.

Are you using an ESP32? I assumed the official ArduinoBLE library (ArduinoBLE - Arduino Reference). That shouldn't really matter though, as long as you have a way to determine the actual number of bytes stored in pCharacteristic->getValue().

You can easily check that the string constructor I referred to works correctly even if the data contains null bytes: Compiler Explorer

You'll have to be more specific than “nothing's coming out”. Please post a minimal example and including the data you're testing with.

Initially BLE was limited to 20bytes per msg. This has been increased now in the later specs but not sure what is supported by the code library you are using.
utf8 excludes nulls and so is my preferred encoding. Suggest you translate your utf16 to utf8 for transmission.
This project Arduino NANO 33 Made Easy sets up a serial UART stream connection that lets you send long strings of data while respecting a 20byte msg limit. I regularly use it to send 1Kb utf8 text strings.
The pfodParser code I use for handling menus is just tacked on top of the UART stream and can be readily omitted.
The project sets up a BLE/Wifi bridge which may be of interest.

Yes I am actually . You could not know, that why I posted the function. The "m_value is" also an std:: string.

Serial.println(pCharacteristic->getDataLength());

gives me a length of 20 of the "38" I am sending.

Serial.println(sizeof(pCharacteristic->getValue()));

Gives me 24.

The sizeof operator returns the number of bytes the object representation of a class requires, it has nothing to do with the number of characters stored in a string. You need std::string::size().

It's been a while since I've used BLE on ESP32, but IIRC, the default MTU is 23 bytes, which allows for 20 bytes of actual payload. I don't recall how to increase the MTU or how to enable long reads/writes. In fact, I don't even know if it's possible using the BLE library from the ESP32 Arduino Core, I seem to recall this was one of the limitations that caused me to switch to the native Espressif C API for BLE.

I have found out there is a way to do that by define custom callbacks and characteristics. So I could recieve the whole package and then decode it. If I am doing that this topic has no use anymore. So I will close it.

Thanks PieterP for your help.

It’s been a while since I’ve used BLE on ESP32, but IIRC, the default MTU is 23 bytes, which allows for 20 bytes of actual payload. I don’t recall how to increase the MTU or how to enable long reads/writes. In fact, I don’t even know if it’s possible using the BLE library from the ESP32 Arduino Core, I seem to recall this was one of the limitations that caused me to switch to the native Espressif C API for BLE.

PieterP, I solved by sending decimal bytes.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.