首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ESP-IDF-3.0蓝牙网关服务器示例还是帮助使用多个服务?

ESP-IDF-3.0蓝牙网关服务器示例还是帮助使用多个服务?
EN

Stack Overflow用户
提问于 2018-02-24 18:43:53
回答 1查看 2.9K关注 0票数 0

我目前正在进行一个固件项目,我需要设备来广播多个蓝牙服务,如设备信息服务、电池服务等。我已经梳理了esp以色列国防军的GitHub和readthedocs站点,所有用于GATT服务器的示例似乎只有一个服务。到目前为止,我已经有了广告工作和1项服务的全部功能,但我完全不知道如何使第二个工作。如果有人有任何的例子或建议,这将是非常感谢!

我在这里的example服务表示例中大部分都是基于这个示例的:table

我正在像这样初始化蓝牙库(在我的代码中,为了可读性,我删除了很多日志和错误处理.功能相同):

代码语言:javascript
复制
esp_err_t Bluetooth_Interface_Init(void)
{
    esp_err_t err;

    Bluetooth_Driver_Init(); //Takes care of bt hardware inits

    err = esp_ble_gatts_register_callback(gatts_event_handler);
    err = esp_ble_gap_register_callback(gap_event_handler);

    err = esp_ble_gatts_app_register(ESP_APP_ID);
    err = esp_ble_gatt_set_local_mtu(500);

    return err;
}

我的广告资料如下:

代码语言:javascript
复制
static uint8_t service_uuid[16] =
{
    /* LSB <--------------------------------------------------------------------------------> MSB */
    //first uuid, 16bit, [12],[13] is the value
    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x18, 0x0D, 0x00, 0x00,
};

/* The length of adv data must be less than 31 bytes */
static esp_ble_adv_data_t adv_data = {
    .set_scan_rsp        = false,
    .include_name        = true,
    .include_txpower     = true,
    .min_interval        = 0x20,
    .max_interval        = 0x40,
    .appearance          = 0x00,
    .manufacturer_len    = 0,    //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data = NULL, //test_manufacturer,
    .service_data_len    = 0,
    .p_service_data      = NULL,
    .service_uuid_len    = sizeof(service_uuid),
    .p_service_uuid      = service_uuid,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

// scan response data
static esp_ble_adv_data_t scan_rsp_data = {
    .set_scan_rsp        = true,
    .include_name        = true,
    .include_txpower     = true,
    .min_interval        = 0x20,
    .max_interval        = 0x40,
    .appearance          = 0x00,
    .manufacturer_len    = 0, //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data = NULL, //&test_manufacturer[0],
    .service_data_len    = 0,
    .p_service_data      = NULL,
    .service_uuid_len    = sizeof(service_uuid),
    .p_service_uuid      = service_uuid,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

static esp_ble_adv_params_t adv_params = {
    .adv_int_min         = 0x20,
    .adv_int_max         = 0x40,
    .adv_type            = ADV_TYPE_IND,
    .own_addr_type       = BLE_ADDR_TYPE_PUBLIC,
    .channel_map         = ADV_CHNL_ALL,
    .adv_filter_policy   = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};

我的GAP事件处理程序:

代码语言:javascript
复制
   static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
    {
        switch (event) {
            case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
                adv_config_done &= (~ADV_CONFIG_FLAG);
                if (adv_config_done == 0){
                    esp_ble_gap_start_advertising(&adv_params);
                }
                break;
            case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
                adv_config_done &= (~SCAN_RSP_CONFIG_FLAG);
                if (adv_config_done == 0){
                    esp_ble_gap_start_advertising(&adv_params);
                }
                break;

            case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
                /* advertising start complete event to indicate advertising start successfully or failed */
                if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                    ESP_LOGE(TAG_IBLUETOOTH, "advertising start failed");
                }else{
                    ESP_LOGI(TAG_IBLUETOOTH, "advertising start successfully");
                }
                break;
            case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
                if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                    ESP_LOGE(TAG_IBLUETOOTH, "Advertising stop failed");
                }
                else {
                    ESP_LOGI(TAG_IBLUETOOTH, "Stop adv successfully\n");
                }
                break;
            case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
                ESP_LOGI(TAG_IBLUETOOTH, "update connetion 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;
            default:
                break;
        }
    }

我的盖茨事件处理程序:

代码语言:javascript
复制
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
#ifdef IBLUETOOTH_DEBUG
    ESP_LOGI(TAG_IBLUETOOTH, "gatts event handler: %d", event);
#endif
    /* If event is register event, store the gatts_if for each profile */
    if (event == ESP_GATTS_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {


            bt_profile_tab[INFO_IDX].gatts_if = gatts_if; //This is all that works... It registers the info profile 
            //bt_profile_tab[param->reg.app_id].gatts_if = gatts_if; //Nothing gets registered when doing this
            //bt_profile_tab[WIFI_IDX].gatts_if = gatts_if; //Doing this always fails to register both.. Info Service is all that gets registered
        } else {
            ESP_LOGE(TAG_IBLUETOOTH, "reg app failed, app_id %04x, status %d", param->reg.app_id, param->reg.status);
            return;
        }
    }
    do {
        int idx;
        for (idx = 0; idx < PROFILE_NUM; idx++) {
            /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
            if (gatts_if == ESP_GATT_IF_NONE || gatts_if == bt_profile_tab[idx].gatts_if) {
                if (bt_profile_tab[idx].gatts_cb) {
                    bt_profile_tab[idx].gatts_cb(event, gatts_if, param);
                }
            }
        }
    } while (0);
}

服务事件处理程序之一的示例:

代码语言:javascript
复制
static const uint16_t INFO_SERV_uuid                = ESP_GATT_UUID_DEVICE_INFO_SVC;  //0x180A
static const uint16_t INFO_SERV_char_sysid_uuid         = ...;
static const uint16_t INFO_SERV_char_model_uuid         = ...;
static const uint16_t INFO_SERV_char_serial_uuid        = ...;
static const uint16_t INFO_SERV_char_fw_uuid        = ...;
static const uint16_t INFO_SERV_char_protocol_uuid  = ...;

static const uint8_t INFO_SERV_char_sysid_descr[]       = ...;
static const uint8_t INFO_SERV_char_model_descr[]       = ...;
static const uint8_t INFO_SERV_char_serial_descr[]      = ...;
static const uint8_t INFO_SERV_char_fw_descr[]      = ...;
static const uint8_t INFO_SERV_char_protocol_descr[]        = ...;

static const esp_gatts_attr_db_t info_serv_gatt_db[INFO_NB] =
{
    [INFO_SERV] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *) &primary_service_uuid, ESP_GATT_PERM_READ, sizeof(uint16_t), sizeof(INFO_SERV_uuid), (uint8_t *)&INFO_SERV_uuid}},
...
 };

static void info_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
    switch (event) {
        case ESP_GATTS_REG_EVT:{
            esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(DEVICE_NAME);

            //config adv data
            esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);
            adv_config_done |= ADV_CONFIG_FLAG;

            //config scan response data
            ret = esp_ble_gap_config_adv_data(&scan_rsp_data);
            adv_config_done |= SCAN_RSP_CONFIG_FLAG;

            esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(info_serv_gatt_db, gatts_if, INFO_NB, SVC_INST_ID);
        }
            break;
        case ESP_GATTS_READ_EVT:

..。案例ESP_GATTS_EXEC_WRITE_EVT:..。

代码语言:javascript
复制
         case ESP\_GATTS\_MTU\_EVT:                 ESP\_LOGI(TAG\_IBLUETOOTH, "ESP\_GATTS\_MTU\_EVT, MTU %d", param->mtu.mtu);                 break;
代码语言:javascript
复制
        case ESP_GATTS_CONF_EVT:
            ESP_LOGI(TAG_IBLUETOOTH, "ESP_GATTS_CONF_EVT, status = %d", param->conf.status);
            break;

        case ESP_GATTS_START_EVT:
            ESP_LOGI(TAG_IBLUETOOTH, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle);
            break;

        case ESP_GATTS_CONNECT_EVT:
            ESP_LOGI(TAG_IBLUETOOTH, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
            esp_log_buffer_hex(TAG_IBLUETOOTH, param->connect.remote_bda, 6);
            esp_ble_conn_update_params_t conn_params = {0};
            memcpy(conn_params.bda, param->connect.remote_bda, sizeof(esp_bd_addr_t));
            /* For the IOS system, please reference the apple official documents about the ble connection parameters restrictions. */
            conn_params.latency = 0;
            conn_params.max_int = 0x20;    // max_int = 0x20*1.25ms = 40ms
            conn_params.min_int = 0x10;    // min_int = 0x10*1.25ms = 20ms
            conn_params.timeout = 400;    // timeout = 400*10ms = 4000ms
            //start sent the update connection parameters to the peer device.
            esp_ble_gap_update_conn_params(&conn_params);
            break;
        case ESP_GATTS_DISCONNECT_EVT:
            ESP_LOGI(TAG_IBLUETOOTH, "ESP_GATTS_DISCONNECT_EVT, reason = %d", param->disconnect.reason);
            esp_ble_gap_start_advertising(&adv_params);
            break;

        case ESP_GATTS_CREAT_ATTR_TAB_EVT:
            if (param->add_attr_tab.status != ESP_GATT_OK){
                ESP_LOGE(TAG_IBLUETOOTH, "create attribute table failed, error code=0x%x", param->add_attr_tab.status);
            }
            else if (param->add_attr_tab.num_handle != INFO_NB){
                ESP_LOGE(TAG_IBLUETOOTH, "create attribute table abnormally, num_handle (%d) doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, INFO_NB);
            }
            else {
                ESP_LOGI(TAG_IBLUETOOTH, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle);
                memcpy(info_handle_table, param->add_attr_tab.handles, sizeof(info_handle_table));
                esp_ble_gatts_start_service(info_handle_table[INFO_SERV]);
            }
            break;

        case ESP_GATTS_STOP_EVT:
        case ESP_GATTS_OPEN_EVT:
        case ESP_GATTS_CANCEL_OPEN_EVT:
        case ESP_GATTS_CLOSE_EVT:
        case ESP_GATTS_LISTEN_EVT:
        case ESP_GATTS_CONGEST_EVT:
        case ESP_GATTS_UNREG_EVT:
        case ESP_GATTS_DELETE_EVT:
        default:
            break;
    }
}

我有种感觉我做了一件很明显的错事.但任何反馈的过程中,这样做,例子或建议将是非常感谢的!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-08-02 14:03:18

对于那些一直在寻找答案的人,我很抱歉。我已经设置了一个GitHub回购,在这里我已经模块化了示例。该项目将ESP-以色列国防军蓝牙分解为一个接口、GAP、GATT Server和服务.它的好处是,服务被分解成单独的文件,因此在提供的模板基础上添加新服务是快速和容易的。这仍然是一个粗略的工作正在进行中,但希望它将帮助任何人谁是困惑的电子国防军蓝牙的例子。

Multi-Service

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48966373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档