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

Cannot Send 'Extended ASCII' or any 8-bit data >127 Over BLE

I have a codebase that takes from many different sample applications and uses S140. I am interested in using a Characteristic from an iOS Swift Central that sends String data as 8-bit uint8_t data arrays. I can send ASCII characters correctly via sd_ble_gatts_hvx(), but I cannot send data with values > 127. My array is uint8_t, so I should have 0-255 available to me and when debugging or writing to the console I can see values higher than 128. This might make sense if the variable was a signed char, but it's not.

Whenever I send data via sd_ble_gatts_hvx() that has any values > 127, it does not work. An Error Code of 0 is reported, but nothing happens. "Extended ASCII" or ISO-8859-1 should be allowable in uint8_t and I see uint8_t variable types in the code / samples, not signed chars. Can someone help me send full 8-bit data? Thanks!

// Get the 8-bit Data
uint8_t output[ BLE_MAX_DATA_LEN ] = { '\0' }; // 244 with iOS
output[ 0 ] = 'E';
output[ 1 ] = 128; // This is enough to break everything uint16_t status = getData( output, BLE_MAX_DATA_LEN );

// Send BLE uint16_t output_length = strlen( output );
ret_code_t err_code = ble_send_data( output, &output_length );

// Function Definition
uint32_t ble_send_data(uint8_t *p_data, uint16_t *p_length) { hvx_ready = false; return val_update(&m_sem, p_data, p_length, m_conn_handle); }

// Function Definition
uint32_t val_update( ble_sem_t * p_sem, uint8_t * p_data, uint16_t * p_length, uint16_t conn_handle) { ret_code_t err_code; ble_gatts_hvx_params_t hvx_params; ble_sem_client_context_t * p_client; VERIFY_PARAM_NOT_NULL(p_sem); err_code = blcm_link_ctx_get(p_sem->p_link_ctx_storage, conn_handle, (void *) &p_client); VERIFY_SUCCESS(err_code); if (token != BLE_TOKEN_OP) return NRF_ERROR_NOT_SUPPORTED; if ((conn_handle == BLE_CONN_HANDLE_INVALID) || (p_client == NULL)) { return NRF_ERROR_NOT_FOUND; } if (*p_length > BLE_MAX_DATA_LEN) { return NRF_ERROR_INVALID_PARAM; } memset(&hvx_params, 0, sizeof(hvx_params)); hvx_params.handle = p_sem->char_handles.value_handle; hvx_params.p_data = p_data; hvx_params.p_len = p_length; hvx_params.type = BLE_GATT_HVX_NOTIFICATION; return sd_ble_gatts_hvx(conn_handle, &hvx_params); }
Parents
  • Hi 

    The SoftDevice has no limit on the type of data that you can send in a notification, so I am tempted to believe that the problem is somehow happening on the receiving end. 

    You mention that nothing happens when you set the first byte to 128. Can you give me a bit more information about what will happen when you send values below 128, and how you receive and process the data on the client side?

    The length parameter is a pointer, and the SoftDevice will write the number of bytes actually sent to the variable address by this pointer. Can you try to check the status of the length variable after sending the notification to make sure that the entire packet is actually sent?

    Alternatively the issue can be in the call to strlen( output ). 

    If you set the first byte of the array to 128 then there is no guarantee that your string contains any 0 characters, and the length of the string might be set to some random value.
    Try setting output[1] or output[BLE_MAX_DATA_LEN - 1] = 0 and try again, this might solve the issue. 

    Best regards
    Torbjørn

  • The first byte is an alpha character code, so it has been 'E' / 69 in all of my testing. Setting the first bit to 128 was confusing, my apologies, but I was trying to demonstrate that any value over 127 creates an issue. I'll edit it.

    I have a Central running on iOS 12.1.4 on an iPad Mini 2. I am debugging the iOS code at 'didUpdateValueFor()' [func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?)] I initially check for nil values in Characteristic.value and I see all packets arriving when I limit the data to 1-127. When any value over 127 is sent, I do not see any activity on the Central. I encode all data in didUpdateValueFor() with both isoLatin1 and UTF-8 for testing purposes. I am validating that no zeros are sent in the string in case they would confused with null characters.

    I originally hardcoded the length to BLE_MAX_DATA_LEN, but this was a test using strlen(). I will switch it back. I was outputting the length parameter after writing. I just looked back at my testing and it was always 243 after calling ble_send_data(). I will try setting output[BLE_MAX_DATA_LEN - 1] = 0 now and let you know how it goes.

    I have also tested this without success in seeing it on the Central:

            output_length = 3;
            uint8_t test_output[ 3 ] = { '\0' };
            test_output[ 0 ] = 'E';
            test_output[ 1 ] = 128;     // Can't send Extended ASCII, e.g. > 127
            err_code = ble_send_data( test_output, &output_length );

    Thanks for your help, Torbjørn!

  • Torbjørn was right. The receiver was the problem. Apparently iOS considers a non-UTF-8 encoded String as satisfying the == condition of nil. I inspected the value and it had the number of bytes I was looking for. I modified the == inspection to also have to be nil when decoded as isoLatin1 (8859-1).

    Thanks for the help! You can close this.

  • Good to hear you found the issue, I will close this ticket then Slight smile

Reply Children
No Data
Related