This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Encode an UTF8 String into characteristic

Dear Nordic Team,

I'd like to inquiry how I am supposed to send a UTF8 string as the value of a characteristic. 

I am trying to implement the FTMS service and the part I am talking about reads as

I am encoding it like this:

static uint8_t ftms_training_status_encode(ble_ftms_t      * p_ftms,
                                     ble_ftms_training_status_t * training_status,
                                     uint8_t        * p_encoded_buffer)
{
    uint8_t len = 0;
    uint8_t out_len = 0;

    ble_srv_utf8_str_t training_status_string;
    uint8_t out_buf[32];

    *(&p_encoded_buffer[len++]) = 1 << 0; // Flags: Training Status string present: Yes, Extended String present: No
    *(&p_encoded_buffer[len++]) = *training_status; // Training Status hex value
    
    switch (*training_status)
    {
        case BLE_FTMS_TRAINING_STATUS_OTHER:
            ble_srv_ascii_to_utf8(&training_status_string, (char *) "Other");
            break;
        case BLE_FTMS_TRAINING_STATUS_IDLE:
            ble_srv_ascii_to_utf8(&training_status_string, (char *) "Idle");
            break;
        ....
        default:
            break;
    }
    
    out_len = bds_ble_srv_utf8_str_encode(&training_status_string, out_buf);
    memcpy(&p_encoded_buffer[len], out_buf, out_len);
    len += out_len;

    return len;
}

After encoding the buffer looks like this

So first byte indicates 0x1, then the type 0x0D and then the string bytes.

The question is: Am I supposed to reverse the string according to the spec? (LSB/MSB)?

Am I supposed to prefix the UTF8 string with a byte specifying the length? Whe I used "ble_srv_ascii_to_utf8(&training_status_string, (char *) "Manual");" to fill the ble_srv_utf8_str_t structure that structure consists of the length and the pointer to the string. So I wonder if, when sending a UTF8 string over BLE I am asked to prefix it with a length byte too maybe?

Thank you!

  • Hi,

    From what I can figure out, it should be a UTF-8 encoded string, without any additional metadata, and in the "normal" byte order for such a string (e.g. no reversing of the bytes.)

    I.e. the same byte ordering and formatting as the Device Name characteristic of the GAP service, which also holds a UTF-8 encoded string. The only difference being that for the Training Status characteristic there are two octets containing "Flags" and "Training Status" in addition to the string.

    Which means your characteristic value data looks correct as is, with the exception that you are printing 32 bytes and the actual contents of the characteristic should be only the first 8 of those bytes.

    I am reaching out internally, to see if I can confirm this is indeed how it is supposed to work.

    Regards,
    Terje

  • Thanks Terje, appreciate! I was confused because of the explicit mentioning of MSB/LSB order in the spec and thought I might reverse the byte order therefore. I am actually printing only 8 bytes in the end. The screenshot just shows the SES IDE where I had it print 32 bytes for an easier oversight. Looking forward to your response!

  • Hi,

    I can confirm that the byte order that you have, is the intended byte order: First one byte "flags", then one byte "training status", then n bytes UTF-8 encoded string. For increasing memory addresses. When stored as data for the characteristic.

    Other implementations, and/or byte order physically sent over the air, may differ, but apart from that: This is the byte order to use with our SDK / SoftDevice API, yes.

    Regards,
    Terje

  • Thanks for seeking clarification on this one!

Related