Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gattc_multi_connect The number of connections can only be five (IDFGH-12799) #13776

Open
3 tasks done
laopi333 opened this issue May 11, 2024 · 9 comments
Open
3 tasks done
Assignees
Labels
Status: Opened Issue is new Type: Bug bugs in IDF

Comments

@laopi333
Copy link

laopi333 commented May 11, 2024

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

IDF version.

ESP-IDF v5.1.2-1-g2bbd2ec531

Espressif SoC revision.

esp32s3

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

ESP32-S3-WROOM-1

Power Supply used.

USB

What is the expected behavior?

我尝试使用开发板gattc连接最大数量的蓝牙设备,在menuconfig里面设置了 (9) BT/BLE MAX ACL CONNECTIONS(1~9)

What is the actual behavior?

我期待最大能连接到9个或者7个设备,但是只能连接到5个,当连接第6个设备的时候,在 ESP_GATTC_OPEN_EVT 中产生了这样的错误:
W (290423) BT_L2CAP: L2CA_CancelBleConnectReq - no connection pending E (290423) GATTC_MULTIPLE_DEMO: connect device failed, status 133
开发板一直在尝试连接第6个设备,但是一直打印这样的错误,我找不到原因

Steps to reproduce.

修改 gattc_multi_connect demo,将连接的数量和相关参数增大

Debug Logs.

W (49023) BT_L2CAP: L2CA_CancelBleConnectReq - no connection pending
E (49033) GATTC_MULTIPLE_DEMO: connect device failed, status 133

More Information.

#include <stdint.h>
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include "nvs.h"
#include "nvs_flash.h"

#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gattc_api.h"
#include "esp_gatt_defs.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

#define GATTC_TAG "GATTC_MULTIPLE_DEMO"
#define REMOTE_SERVICE_UUID 0x00FF
#define REMOTE_NOTIFY_CHAR_UUID 0xFF01

#define MAX_CONN_NUM 10

/* register three profiles, each profile corresponds to one connection,
which makes it easy to handle each connection event */
#define PROFILE_NUM 1
#define PROFILE_A_APP_ID 0
#define PROFILE_B_APP_ID 1
#define PROFILE_C_APP_ID 2
#define INVALID_HANDLE 0

/* Declare static functions */
static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param);
static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);
static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param);

static esp_bt_uuid_t remote_filter_service_uuid = {
.len = ESP_UUID_LEN_16,
.uuid = {.uuid16 = REMOTE_SERVICE_UUID,},
};

static esp_bt_uuid_t remote_filter_char_uuid = {
.len = ESP_UUID_LEN_16,
.uuid = {.uuid16 = REMOTE_NOTIFY_CHAR_UUID,},
};

static esp_bt_uuid_t notify_descr_uuid = {
.len = ESP_UUID_LEN_16,
.uuid = {.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG,},
};

static int conn_device_num = 0;
static bool get_service_a = false;
static bool Isconnecting = false;
static bool stop_scan_done = false;

static esp_gattc_char_elem_t *char_elem_result_a = NULL;
static esp_gattc_descr_elem_t *descr_elem_result_a = NULL;

static const char remote_device_name[] = "GL_BOARD";

static esp_ble_scan_params_t ble_scan_params = {
.scan_type = BLE_SCAN_TYPE_ACTIVE,
.own_addr_type = BLE_ADDR_TYPE_PUBLIC,
.scan_filter_policy = BLE_SCAN_FILTER_ALLOW_ALL,
.scan_interval = 0x50,
.scan_window = 0x30,
.scan_duplicate = BLE_SCAN_DUPLICATE_DISABLE
};

struct gattc_profile_inst {
esp_gattc_cb_t gattc_cb;
uint16_t gattc_if;
uint16_t app_id;
uint16_t conn_id[MAX_CONN_NUM];
uint16_t service_start_handle;
uint16_t service_end_handle;
uint16_t char_handle;
esp_bd_addr_t remote_bda;
};

/* One gatt-based profile one app_id and one gattc_if, this array will store the gattc_if returned by ESP_GATTS_REG_EVT /
static struct gattc_profile_inst gl_profile_tab[PROFILE_NUM] = {
[PROFILE_A_APP_ID] = {
.gattc_cb = gattc_profile_a_event_handler,
.gattc_if = ESP_GATT_IF_NONE, /
Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
},
};

static void start_scan(void)
{
stop_scan_done = false;
Isconnecting = false;
uint32_t duration = 0;
esp_ble_gap_start_scanning(duration);
}
static void gattc_profile_a_event_handler(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
{

esp_ble_gattc_cb_param_t *p_data = (esp_ble_gattc_cb_param_t *)param;

switch (event) {
case ESP_GATTC_REG_EVT:
    ESP_LOGI(GATTC_TAG, "REG_EVT");
    esp_err_t scan_ret = esp_ble_gap_set_scan_params(&ble_scan_params);
    if (scan_ret){
        ESP_LOGE(GATTC_TAG, "set scan params error, error code = %x", scan_ret);
    }
    break;
/* one device connect successfully, all profiles callback function will get the ESP_GATTC_CONNECT_EVT,
 so must compare the mac address to check which device is connected, so it is a good choice to use ESP_GATTC_OPEN_EVT. */
case ESP_GATTC_CONNECT_EVT:
    break;
case ESP_GATTC_OPEN_EVT:
    if (p_data->open.status != ESP_GATT_OK){
        //open failed, ignore the first device, connect the second device
        ESP_LOGE(GATTC_TAG, "connect device failed, status %d", p_data->open.status);
        //start_scan();
        break;
    }
    conn_device_num++;
    memcpy(gl_profile_tab[PROFILE_A_APP_ID].remote_bda, p_data->open.remote_bda, 6);
    gl_profile_tab[PROFILE_A_APP_ID].conn_id[conn_device_num] = p_data->open.conn_id;
    ESP_LOGI(GATTC_TAG, "ESP_GATTC_OPEN_EVT conn_id %d, if %d, status %d, mtu %d", p_data->open.conn_id, gattc_if, p_data->open.status, p_data->open.mtu);
    ESP_LOGI(GATTC_TAG, "REMOTE BDA:");
    esp_log_buffer_hex(GATTC_TAG, p_data->open.remote_bda, sizeof(esp_bd_addr_t));
    esp_err_t mtu_ret = esp_ble_gattc_send_mtu_req (gattc_if, p_data->open.conn_id);
    if (mtu_ret){
        ESP_LOGE(GATTC_TAG, "config MTU error, error code = %x", mtu_ret);
    }
    break;
case ESP_GATTC_CFG_MTU_EVT:
    if (param->cfg_mtu.status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG,"Config mtu failed");
    }
    ESP_LOGI(GATTC_TAG, "Status %d, MTU %d, conn_id %d", param->cfg_mtu.status, param->cfg_mtu.mtu, param->cfg_mtu.conn_id);
    esp_ble_gattc_search_service(gattc_if, param->cfg_mtu.conn_id, NULL);
    break;
case ESP_GATTC_SEARCH_RES_EVT: {
    ESP_LOGI(GATTC_TAG, "SEARCH RES: conn_id = %x is primary service %d", p_data->search_res.conn_id, p_data->search_res.is_primary);
    ESP_LOGI(GATTC_TAG, "start handle %d end handle %d current handle value %d", p_data->search_res.start_handle, p_data->search_res.end_handle, p_data->search_res.srvc_id.inst_id);
    if (p_data->search_res.srvc_id.uuid.len == ESP_UUID_LEN_16) {
        ESP_LOGI(GATTC_TAG, "UUID16: %x", p_data->search_res.srvc_id.uuid.uuid.uuid16);
        get_service_a = true;
        gl_profile_tab[PROFILE_A_APP_ID].service_start_handle = p_data->search_res.start_handle;
        gl_profile_tab[PROFILE_A_APP_ID].service_end_handle = p_data->search_res.end_handle;
    }
    break;
}
case ESP_GATTC_SEARCH_CMPL_EVT:
    if (p_data->search_cmpl.status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG, "search service failed, error status = %x", p_data->search_cmpl.status);
        break;
    }
    if (get_service_a){
        uint16_t count = 0;
        esp_gatt_status_t status = esp_ble_gattc_get_attr_count( gattc_if,
                                                                 p_data->search_cmpl.conn_id,
                                                                 ESP_GATT_DB_CHARACTERISTIC,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
                                                                 INVALID_HANDLE,
                                                                 &count);
        if (status != ESP_GATT_OK){
            ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
        }
        if (count > 0) {
            char_elem_result_a = (esp_gattc_char_elem_t *)malloc(sizeof(esp_gattc_char_elem_t) * count);
            if (!char_elem_result_a){
                ESP_LOGE(GATTC_TAG, "gattc no mem");
            }else {
                status = esp_ble_gattc_get_char_by_uuid( gattc_if,
                                                         p_data->search_cmpl.conn_id,
                                                         gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
                                                         gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
                                                         remote_filter_char_uuid,
                                                         char_elem_result_a,
                                                         &count);
                if (status != ESP_GATT_OK){
                    ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_char_by_uuid error");
                }

                /*  Every service have only one char in our 'ESP_GATTS_DEMO' demo, so we used first 'char_elem_result' */
                if (count > 0 && (char_elem_result_a[0].properties & ESP_GATT_CHAR_PROP_BIT_NOTIFY)){
                    gl_profile_tab[PROFILE_A_APP_ID].char_handle = char_elem_result_a[0].char_handle;
                    esp_ble_gattc_register_for_notify (gattc_if, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, char_elem_result_a[0].char_handle);
                }
            }
            /* free char_elem_result */
            free(char_elem_result_a);
        }else {
            ESP_LOGE(GATTC_TAG, "no char found");
        }

        printf("conn done .............................\n");
        start_scan();
    }
    break;
case ESP_GATTC_REG_FOR_NOTIFY_EVT: {
    if (p_data->reg_for_notify.status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG, "reg notify failed, error status =%x", p_data->reg_for_notify.status);
        break;
    }
    uint16_t count = 0;
    uint16_t notify_en = 1;
    esp_gatt_status_t ret_status = esp_ble_gattc_get_attr_count( gattc_if,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].conn_id[conn_device_num],
                                                                 ESP_GATT_DB_DESCRIPTOR,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].service_start_handle,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].service_end_handle,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                                 &count);
    if (ret_status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_attr_count error");
    }
    if (count > 0){
        descr_elem_result_a = (esp_gattc_descr_elem_t *)malloc(sizeof(esp_gattc_descr_elem_t) * count);
        if (!descr_elem_result_a){
            ESP_LOGE(GATTC_TAG, "malloc error, gattc no mem");
        }else{
            ret_status = esp_ble_gattc_get_descr_by_char_handle( gattc_if,
                                                                 gl_profile_tab[PROFILE_A_APP_ID].conn_id[conn_device_num],
                                                                 p_data->reg_for_notify.handle,
                                                                 notify_descr_uuid,
                                                                 descr_elem_result_a,
                                                                 &count);
            if (ret_status != ESP_GATT_OK){
                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_get_descr_by_char_handle error");
            }

            /* Every char has only one descriptor in our 'ESP_GATTS_DEMO' demo, so we used first 'descr_elem_result' */
            if (count > 0 && descr_elem_result_a[0].uuid.len == ESP_UUID_LEN_16 && descr_elem_result_a[0].uuid.uuid.uuid16 == ESP_GATT_UUID_CHAR_CLIENT_CONFIG){
                ret_status = esp_ble_gattc_write_char_descr( gattc_if,
                                                             gl_profile_tab[PROFILE_A_APP_ID].conn_id[conn_device_num],
                                                             descr_elem_result_a[0].handle,
                                                             sizeof(notify_en),
                                                             (uint8_t *)&notify_en,
                                                             ESP_GATT_WRITE_TYPE_RSP,
                                                             ESP_GATT_AUTH_REQ_NONE);
            }

            if (ret_status != ESP_GATT_OK){
                ESP_LOGE(GATTC_TAG, "esp_ble_gattc_write_char_descr error");
            }

            /* free descr_elem_result */
            free(descr_elem_result_a);
        }
    }
    else{
        ESP_LOGE(GATTC_TAG, "decsr not found");
    }

    break;
}
case ESP_GATTC_NOTIFY_EVT:
    ESP_LOGI(GATTC_TAG, "ESP_GATTC_NOTIFY_EVT, Receive notify value:");
    esp_log_buffer_hex(GATTC_TAG, p_data->notify.value, p_data->notify.value_len);
    break;
case ESP_GATTC_WRITE_DESCR_EVT:
    if (p_data->write.status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG, "write descr failed, error status = %x", p_data->write.status);
        break;
    }
    ESP_LOGI(GATTC_TAG, "write descr success");
    break;
case ESP_GATTC_WRITE_CHAR_EVT:
    if (p_data->write.status != ESP_GATT_OK){
        ESP_LOGE(GATTC_TAG, "write char failed, error status = %x", p_data->write.status);
    }else{
        ESP_LOGI(GATTC_TAG, "write char success");
    }
    start_scan();
    break;
case ESP_GATTC_SRVC_CHG_EVT: {
    esp_bd_addr_t bda;
    memcpy(bda, p_data->srvc_chg.remote_bda, sizeof(esp_bd_addr_t));
    ESP_LOGI(GATTC_TAG, "ESP_GATTC_SRVC_CHG_EVT, bd_addr:%08x%04x",(bda[0] << 24) + (bda[1] << 16) + (bda[2] << 8) + bda[3],
             (bda[4] << 8) + bda[5]);
    break;
}
case ESP_GATTC_DISCONNECT_EVT:
    //Start scanning again
    start_scan();
    if (memcmp(p_data->disconnect.remote_bda, gl_profile_tab[PROFILE_A_APP_ID].remote_bda, 6) == 0){
        ESP_LOGI(GATTC_TAG, "device a disconnect");
        conn_device_num--;
        get_service_a = false;
    }
    break;
default:
    break;
}

}

static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
uint8_t *adv_name = NULL;
uint8_t adv_name_len = 0;
switch (event) {
case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
ESP_LOGI(GATTC_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
param->update_conn_params.status,
param->update_conn_params.min_int,
param->update_conn_params.max_int,
param->update_conn_params.conn_int,
param->update_conn_params.latency,
param->update_conn_params.timeout);
break;
case ESP_GAP_BLE_SCAN_PARAM_SET_COMPLETE_EVT: {
//the unit of the duration is second
uint32_t duration = 0;
esp_ble_gap_start_scanning(duration);
break;
}
case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT:
//scan start complete event to indicate scan start successfully or failed
if (param->scan_start_cmpl.status == ESP_BT_STATUS_SUCCESS) {
// ESP_LOGI(GATTC_TAG, "Scan start success");
}else{
// ESP_LOGE(GATTC_TAG, "Scan start failed");
}
break;
case ESP_GAP_BLE_SCAN_RESULT_EVT: {
esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param;
switch (scan_result->scan_rst.search_evt) {
case ESP_GAP_SEARCH_INQ_RES_EVT:
// esp_log_buffer_hex(GATTC_TAG, scan_result->scan_rst.bda, 6);
// ESP_LOGI(GATTC_TAG, "Searched Adv Data Len %d, Scan Response Len %d", scan_result->scan_rst.adv_data_len, scan_result->scan_rst.scan_rsp_len);
adv_name = esp_ble_resolve_adv_data(scan_result->scan_rst.ble_adv,
ESP_BLE_AD_TYPE_NAME_CMPL, &adv_name_len);
// ESP_LOGI(GATTC_TAG, "Searched Device Name Len %d", adv_name_len);
// esp_log_buffer_char(GATTC_TAG, adv_name, adv_name_len);
// ESP_LOGI(GATTC_TAG, "\n");
if (Isconnecting){
break;
}

        if (adv_name != NULL) {
            if (strncmp((char *)adv_name, remote_device_name, strlen(remote_device_name)) == 0) {
                ESP_LOGI(GATTC_TAG, "Searched device %s", adv_name);
                esp_ble_gap_stop_scanning();
                esp_ble_gattc_open(gl_profile_tab[PROFILE_A_APP_ID].gattc_if, scan_result->scan_rst.bda, scan_result->scan_rst.ble_addr_type, true);
                Isconnecting = true;
                } 
            }
        break;
    case ESP_GAP_SEARCH_INQ_CMPL_EVT:
        break;
    default:
        break;
    }
    break;
}

case ESP_GAP_BLE_SCAN_STOP_COMPLETE_EVT:
    if (param->scan_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
        ESP_LOGE(GATTC_TAG, "Scan stop failed");
        break;
    }
    ESP_LOGI(GATTC_TAG, "Stop scan successfully");

    break;

case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
    if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS){
        ESP_LOGE(GATTC_TAG, "Adv stop failed");
        break;
    }
    ESP_LOGI(GATTC_TAG, "Stop adv successfully");
    break;

default:
    break;
}

}

static void esp_gattc_cb(esp_gattc_cb_event_t event, esp_gatt_if_t gattc_if, esp_ble_gattc_cb_param_t *param)
{
//ESP_LOGI(GATTC_TAG, "EVT %d, gattc if %d, app_id %d", event, gattc_if, param->reg.app_id);

/* If event is register event, store the gattc_if for each profile */
if (event == ESP_GATTC_REG_EVT) {
    if (param->reg.status == ESP_GATT_OK) {
        gl_profile_tab[param->reg.app_id].gattc_if = gattc_if;
    } else {
        ESP_LOGI(GATTC_TAG, "Reg app failed, app_id %04x, status %d",
                param->reg.app_id,
                param->reg.status);
        return;
    }
}

/* If the gattc_if equal to profile A, call profile A cb handler,
 * so here call each profile's callback */
do {
    int idx;
    for (idx = 0; idx < PROFILE_NUM; idx++) {
        if (gattc_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
                gattc_if == gl_profile_tab[idx].gattc_if) {
            if (gl_profile_tab[idx].gattc_cb) {
                gl_profile_tab[idx].gattc_cb(event, gattc_if, param);
            }
        }
    }
} while (0);

}

void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK( ret );

ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));

esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
    ESP_LOGE(GATTC_TAG, "%s initialize controller failed: %s\n", __func__, esp_err_to_name(ret));
    return;
}

ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (ret) {
    ESP_LOGE(GATTC_TAG, "%s enable controller failed: %s\n", __func__, esp_err_to_name(ret));
    return;
}

ret = esp_bluedroid_init();
if (ret) {
    ESP_LOGE(GATTC_TAG, "%s init bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
    return;
}

ret = esp_bluedroid_enable();
if (ret) {
    ESP_LOGE(GATTC_TAG, "%s enable bluetooth failed: %s\n", __func__, esp_err_to_name(ret));
    return;
}

//register the  callback function to the gap module
ret = esp_ble_gap_register_callback(esp_gap_cb);
if (ret){
    ESP_LOGE(GATTC_TAG, "gap register error, error code = %x", ret);
    return;
}

//register the callback function to the gattc module
ret = esp_ble_gattc_register_callback(esp_gattc_cb);
if(ret){
    ESP_LOGE(GATTC_TAG, "gattc register error, error code = %x", ret);
    return;
}

ret = esp_ble_gattc_app_register(PROFILE_A_APP_ID);
if (ret){
    ESP_LOGE(GATTC_TAG, "gattc app register error, error code = %x", ret);
    return;
}

ret = esp_ble_gatt_set_local_mtu(500);
if (ret){
    ESP_LOGE(GATTC_TAG, "set local  MTU failed, error code = %x", ret);
}


for(;;)
{
    printf("conn_device_num:%d\n",conn_device_num);
    vTaskDelay(3000 / portTICK_PERIOD_MS);
}

}

@laopi333 laopi333 added the Type: Bug bugs in IDF label May 11, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label May 11, 2024
@github-actions github-actions bot changed the title gattc_multi_connect The number of connections can only be five gattc_multi_connect The number of connections can only be five (IDFGH-12799) May 11, 2024
@esp-cjh
Copy link
Contributor

esp-cjh commented May 17, 2024

@laopi333
把 CONFIG_BT_CTRL_BLE_MAX_ACT 设置为 10 再试一下。
image

@laopi333
Copy link
Author

@esp-cjh 非常感谢你的回复,这解决了我的问题。另外我还有一个问题,我不太清楚 BT_BTC_TASK_STACK_SIZE 和 BT_BTU_TASK_STACK_SIZE 这两个栈空间有什么区别,如果我想提升蓝牙多连接的稳定性,增大这两个栈空间会有帮助嘛,如果能回答我会非常感谢。

@esp-cjh
Copy link
Contributor

esp-cjh commented May 21, 2024

@laopi333
BT_BTC_TASK_STACK_SIZE 和 BT_BTU_TASK_STACK_SIZE 分别代表 Bluedroid 协议栈的 BTC task 和 BTU task 的栈空间大小。BTC task 主要用于处理上层应用消息和事件,BTU task 主要用于处理蓝牙协议(Host 部分)。你在测试多连接过程中有遇到过这两个栈溢出的情况吗?如果没有的话增大栈空间可能作用不大。
关于蓝牙多连接稳定性,你主要遇到哪些问题呢?是连接断开还是其他问题?

@laopi333
Copy link
Author

@esp-cjh 谢谢回复,我遇到的问题主要是在gatt客户端连接超过4个以上设备的时候,连接会不稳定,有时候会出现断开连接的现象,出现了这样的警告
W (95703) BT_APPL: gattc_conn_cb: if=1 st=0 id=1 rsn=0x8 W (95703) BT_HCI: hcif disc complete: hdl 0x1, rsn 0x8 ,同样的连接多个设备后有时候断开连接的问题我在使用nimble协议栈进行蓝牙多连接时也产生了,我不知道是因为资源受限还是怎样的原因,因为在连接数量较少时候是很难产生断开连接的问题,所以我觉得应该不是我的gatt服务器产生的问题。

@esp-cjh
Copy link
Contributor

esp-cjh commented May 22, 2024

@laopi333 GATT 服务器端用的是哪款芯片?连接上之后双方会不会进行数据交互?大概多久会出现连接断开的问题?我这边会尝试复现并找到问题原因。

@laopi333
Copy link
Author

@esp-cjh gatt客户端用的是ESP32-S3,gatt服务端用的都是NRF52840开发板,测试中连接后没有进行数据交互,但是我想要在确保连接稳定性的情况下进行数据交互。连接数量超过4个后,可能5分钟之内就会出现断连现象,连接数量越多出现的频率越高。
这是我用gattc_multi_connect demo简单修改后的测试代码:
ble_multi_conn_problem.zip
非常感谢您的热心帮助。

@esp-cjh
Copy link
Contributor

esp-cjh commented May 22, 2024

@laopi333 我使用 ESP32-S3 作为 client,连接 7 个 ESP32-C3(作为 server,使用 gatt_server example),测试了一个晚上,没有出现连接断开的问题。

所以我这边还需要再确认以下问题:
1 NRF52840 作为 server 时是否发起了连接参数更新?
请在 example 中添加以下代码然后复现,并提供出现问题时的完整 log 文件。
image
2 NRF52840 和 ESP32-S3 之间的距离大概多远?

@laopi333
Copy link
Author

@esp-cjh 非常感谢你的测试,首先:1.nrf52840在连接的时候发起了连接参数更新,这是我复现的日志:
ble_multi_conn_log.txt
2.我的s3和nrf52840都距离在1m内,不过我测试的环境中周围2.4g干扰较多,可能是有对这个连接测试产生影响

@esp-cjh
Copy link
Contributor

esp-cjh commented May 23, 2024

@laopi333 我查看了 log,你当前使用的连接参数是 interval = 50ms,timeout = 420ms,这导致如果连续 8 个连接事件都收不到包或者收错包就会导致超时断开。对于多连接和复杂环境下,这个 timeout 太小了,建议至少设置为 500(即 5 秒)。
image

我本地测试了一下,使用你这一组连接参数确实比较容易发生连接超时断开,使用我推荐的参数的话我测试过是很难发生超时断开的,你可以测试一下。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

4 participants