Sending large amount of BLE packets ( >2000 packets)

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Sending large amount of BLE packets ( >2000 packets)

Postby zazas321 » 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:

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);

    }
}
              
 
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:

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);
    }
}
And then In my BLE write event:

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.

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Re: Sending large amount of BLE packets ( >2000 packets)

Postby zazas321 » Thu Nov 11, 2021 10:45 am

I have been further experimenting with different methods and I noticed some issues when using the queue method.

Code: Select all

void BLE_with_queue(void* param){
    ble_message_s* message = (ble_message_s*)param;
    for(;;)
    {  
        for(int i = 0; i<500; i++){
            printf("packet = %u\n",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.");
            }
            vTaskDelay(10/portTICK_PERIOD_MS);
        }
        printf("all data has been sent to queue \n");
        vTaskDelete(0);
    }
}
The function above will send 500 packets 2 byte each. I have a 10ms delay. This delay is here because reading from the flash memory will take some time, so I just added it here to make it more realistic.

In the serial monitor I see the errors:

Code: Select all


packet = 0
packet = 1
packet = 2
packet = 3
packet = 4
packet = 5
packet = 6
W (15547) BT_GATT: gatt_if out of range [ = 0]
E (15547) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 7
W (15557) BT_GATT: gatt_if out of range [ = 0]
E (15557) BT_APPL: Unknown connection ID: 0 fail sending notification
W (15567) BT_GATT: gatt_if out of range [ = 0]
E (15567) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 8
packet = 9
W (15577) BT_GATT: gatt_if out of range [ = 0]
E (15577) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 10
W (15587) BT_GATT: gatt_if out of range [ = 0]
E (15587) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 11
W (15597) BT_GATT: gatt_if out of range [ = 0]
E (15607) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 12
W (15607) BT_GATT: gatt_if out of range [ = 0]
E (15617) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 13
W (15627) BT_GATT: gatt_if out of range [ = 0]
E (15627) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 14
W (15637) BT_GATT: gatt_if out of range [ = 0]
E (15647) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 15
W (15647) BT_GATT: gatt_if out of range [ = 0]
E (15657) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 16
W (15667) BT_GATT: gatt_if out of range [ = 0]
E (15667) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 17
W (15677) BT_GATT: gatt_if out of range [ = 0]
E (15687) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 18
W (15687) BT_GATT: gatt_if out of range [ = 0]
E (15697) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 19
W (15707) BT_GATT: gatt_if out of range [ = 0]
E (15707) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 20
W (15717) BT_GATT: gatt_if out of range [ = 0]
E (15727) BT_APPL: Unknown connection ID: 0 fail sending notification
packet = 21
W (15727) BT_GATT: gatt_if out of range [ = 0]
E (15737) BT_APPL: Unknown connection ID: 0 fail sending notification
W (15747) BT_GATT: gatt_if out of range [ = 0]
packet = 22
E (15747) BT_APPL: Unknown connection ID: 0 fail sending notification

It seems that after certain amount of time, I am no longer available to send any more packets. Could someone help me understand what happens and how to overcome this issue? Is that because the connection id changes for some reason? Since I pass connection id as a parameter and then use this conn id for sending all the packets. Is that a wrong way to do this?

Who is online

Users browsing this forum: No registered users and 115 guests