Dear All,
I am trying to send a bunch of data over BLE, using the notifications of a characteristic of a service. The size of the package data that I am trying to send is 16 bytes.
The way I try to do this at the moment is that once the user enables the notifications and I receive the NOTIFICATION_ENABLED in the service handler, I am reading the data that I need to transmit from the flash storage of the device, I split them in packets of 16 bytes each and then I call the send function. You can see what I am trying to do on the code snippets below:
/** This function recovers and transmits the data over BLE.
* It is called in the service handler onnce the central device enables notifications.
*/
static void transmit_data(void)
{
NRF_LOG_INFO("Start transmiting data");
uint8_t retrieve_data_buf[1600] = { 0 };
int32_t bytes_to_be_sent = retrieve_data_history((uint8_t*)&retrieve_data_buf, sizeof(retrieve_data_buf));
if (bytes_to_be_sent > 0) {
uint32_t packets_to_be_sent = bytes_to_be_sent / PACKET_SIZE;
if (bytes_to_be_sent % PACKET_SIZE) {
packets_to_be_sent++;
}
NRF_LOG_INFO("Packets to be sent: %u", packets_to_be_sent);
uint32_t err_code;
for (uint32_t i = 0; i < packets_to_be_sent;) {
wdt_feed();
err_code = ble_shs_data_send(&m_shs, &retrieve_data_buf[i * SHOWER_PACKET_SIZE]);
if (err_code == NRF_ERROR_RESOURCES) {
do {
err_code = ble_shs_data_send(&m_shs, &retrieve_data_buf[i * SHOWER_PACKET_SIZE]);
wdt_feed();
idle_state_handle();
} while (err_code != NRF_SUCCESS);
}
i++;
}
}
else {
NRF_LOG_INFO("No data to be sent");
}
}The next snippet belongs to my service and it is used to effectively notify the device for the new data:
uint32_t ble_shs_data_send(ble_shs_t* p_shs, uint8_t* history_buffer)
{
if (p_shs == NULL) {
return NRF_ERROR_NULL;
}
uint32_t err_code = NRF_SUCCESS;
ble_gatts_value_t gatts_value;
// Initialize value struct.
memset(&gatts_value, 0, sizeof(gatts_value));
gatts_value.len = PACKET_SIZE;
gatts_value.offset = 0;
gatts_value.p_value = history_buffer;
// Update database.
err_code = sd_ble_gatts_value_set(p_shs->conn_handle,
p_shs->data_value_handles.value_handle,
&gatts_value);
if (err_code != NRF_SUCCESS) {
return err_code;
}
// Send value if connected and notifying.
if ((p_shs->conn_handle != BLE_CONN_HANDLE_INVALID)) {
ble_gatts_hvx_params_t hvx_params;
memset(&hvx_params, 0, sizeof(hvx_params));
hvx_params.handle = p_shs->data_handles.value_handle;
hvx_params.type = BLE_GATT_HVX_NOTIFICATION;
hvx_params.offset = gatts_value.offset;
hvx_params.p_len = &gatts_value.len;
hvx_params.p_data = gatts_value.p_value;
err_code = sd_ble_gatts_hvx(p_shs->conn_handle, &hvx_params);
}
return err_code;
}What I have seen is that in this way the device will transmit some packets (between 3 and 5) and then it will get stuck.
My service has a priority level set to 2.
What I also tried is instead of calling for the ble_shs_data_send and expect to return with NRF_SUCCESS , after the first failure, to use a bool and when, the ble_shs_data_send wait until the BLE_GATTS_EVT_HVN_TX_COMPLETE occurs and then try to send again a package. Weirdly, I never see this event being triggered.
Any ideas?