Sending large amount of BLE packets ( >2000 packets)
Posted: Thu Nov 11, 2021 6:59 am
Hello. I would like to know what is the correct way of sending large amount of BLE packets from the ESP32 to the BLE app. At the moment I use LightBlue.
When I send certain command to my ESP32 device, I want to read all the logs from the flash memory and send 20 byte packets to the BLE app. There may be well over 2000 seperate 20 byte packets.
At the moment, I can only think of 2 possible ways:
1. Handle the response by using the FreeRTOS queue
2. Handle the response without using the queue.
If I choose not to use the queue, I can do the following:
As you can see from above method, after I receive the 0x00 command, I will create a one shot task that will send 5000 BLE packet responses. At the moment I do not worry about reading from the flash memory I am just sending some test data packets 2 bytes each.
The second method using the queue would look simmilar:
I would have to create a task that would only handle the queue:
For example:
And then In my BLE write event:
As you can see from the second method, I just create a one shot task to send all the data to the queue. I would like to understand which is the correct way to handle large amount of packets? Are any of these methods correct? Any tips appreciated.
When I send certain command to my ESP32 device, I want to read all the logs from the flash memory and send 20 byte packets to the BLE app. There may be well over 2000 seperate 20 byte packets.
At the moment, I can only think of 2 possible ways:
1. Handle the response by using the FreeRTOS queue
2. Handle the response without using the queue.
If I choose not to use the queue, I can do the following:
Code: Select all
case ESP_GATTS_WRITE_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT, write value:");
esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
if (heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_DESCR] == param->write.handle && param->write.len == 2){
printf("inside if statement\n");
uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
if (descr_value == 0x0001){
ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
uint8_t notify_data[15];
for (int i = 0; i < sizeof(notify_data); ++i)
{
notify_data[i] = i % 0xff;
}
//the size of notify_data[] need less than MTU size
esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_DESCR],
sizeof(notify_data), notify_data, false);
}else if (descr_value == 0x0002){
ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
uint8_t indicate_data[15];
for (int i = 0; i < sizeof(indicate_data); ++i)
{
indicate_data[i] = i % 0xff;
}
//the size of indicate_data[] need less than MTU size
esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_DESCR],
sizeof(indicate_data), indicate_data, true);
}
else if (descr_value == 0x0000){
ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable ");
}else{
ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value");
esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
}
}
if (param->write.need_rsp){
printf("if param->write.need_rsp \n");
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
}
if(
parse_received_data(gatts_if,param->write.value,param->write.len, param->write.conn_id, param->write.trans_id);
// if command 0x00 received
if(param->write.value[0] = 0x00){
long_packet_s long_message;
long_message.conn_id = param->write.conn_id;
long_message.gatt_if = gatts_if;
xTaskCreate(BLE_no_qeueue,"BLE_long_packet_task",10000,&long_message,1,NULL); // create a one shot task
}
void BLE_no_qeueue(void* param){
long_packet_s* packet = (long_packet_s*)param;
for(;;)
{
uint8_t data[2] = {0,0};
esp_ble_gatts_send_indicate(packet->gatt_if, packet->conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_VAL],2, data, false);
for(int i = 0; i<5000; i++){
printf("test = %u\n",i);
uint8_t data2[2];
data2[0] = i >>8;
data2[1] = i & 0x00FF;
esp_ble_gatts_send_indicate(packet->gatt_if, packet->conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_VAL],2, data2, false);
vTaskDelay(10/portTICK_PERIOD_MS);
}
vTaskDelete(0);
}
}
The second method using the queue would look simmilar:
I would have to create a task that would only handle the queue:
For example:
Code: Select all
static void BLE_parser_task(void *argument)
{
ble_message_s data_received;
for(;;)
{
if (xQueueReceive(ble_parser_queue, &data_received, 0) == pdTRUE) {
esp_ble_gatts_send_indicate(data_received.gatt_if, data_received.conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_VAL],data_received.length, data_received.payload, false);
//free(data_received.payload);
}
vTaskDelay(100/portTICK_PERIOD_MS);
}
}
Code: Select all
case ESP_GATTS_WRITE_EVT:
ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_WRITE_EVT, write value:");
esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
if (heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_DESCR] == param->write.handle && param->write.len == 2){
printf("inside if statement\n");
uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
if (descr_value == 0x0001){
ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
uint8_t notify_data[15];
for (int i = 0; i < sizeof(notify_data); ++i)
{
notify_data[i] = i % 0xff;
}
//the size of notify_data[] need less than MTU size
esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_DESCR],
sizeof(notify_data), notify_data, false);
}else if (descr_value == 0x0002){
ESP_LOGI(GATTS_TABLE_TAG, "indicate enable");
uint8_t indicate_data[15];
for (int i = 0; i < sizeof(indicate_data); ++i)
{
indicate_data[i] = i % 0xff;
}
//the size of indicate_data[] need less than MTU size
esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, heart_rate_handle_table[HRS_IDX_HR_CTNL_PT_DESCR],
sizeof(indicate_data), indicate_data, true);
}
else if (descr_value == 0x0000){
ESP_LOGI(GATTS_TABLE_TAG, "notify/indicate disable ");
}else{
ESP_LOGE(GATTS_TABLE_TAG, "unknown descr value");
esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
}
}
if (param->write.need_rsp){
printf("if param->write.need_rsp \n");
esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
}
if(
parse_received_data(gatts_if,param->write.value,param->write.len, param->write.conn_id, param->write.trans_id);
// if command 0x00 received
if(param->write.value[0] = 0x00){
long_packet_s long_message;
long_message.conn_id = param->write.conn_id;
long_message.gatt_if = gatts_if;
xTaskCreate(BLE_with queue,"BLE queue task",10000,&long_message,1,NULL); // create a one shot task
}
void BLE_with_queue(void* param){
ble_message_s* message = (ble_message_s*)param;
for(;;)
{
uint8_t* ptr = (uint8_t*)malloc((2)* sizeof(uint8_t));
ptr[0] = 0 >>8;
ptr[1] = 0 & 0x00FF;
message->payload = ptr;
message->length = 2;
if (xQueueSend(ble_parser_queue,message, 10) != pdTRUE) {
printf("ERROR: Could not put item on delay queue.");
}
for(int i = 0; i<1000; i++){
uint8_t* ptr = (uint8_t*)malloc((2)* sizeof(uint8_t));
ptr[0] = i >>8;
ptr[1] = i & 0x00FF;
message->payload = ptr;
if (xQueueSend(ble_parser_queue,message, 10) != pdTRUE) {
printf("ERROR: Could not put item on delay queue.");
}
}
printf("all data has been sent to queue \n");
vTaskDelete(0);
}
}
As you can see from the second method, I just create a one shot task to send all the data to the queue. I would like to understand which is the correct way to handle large amount of packets? Are any of these methods correct? Any tips appreciated.