• ESP32下的ble数据notify收发(支持ESP-IDF4.4\ESPIDF5.1)


    绪论

    实现效果

    gatt_server_service_table为模板,实现ESP32-S3与手机端蓝牙调试助手主机进行通信,实现数据的收发功能:

    ESP32接收

    蓝牙调试助手发送数据控制esp32开发板,开发板将数据打印出来

    ESP32 notify 发送

    esp32将在任务中,循环发一串字符串给蓝牙调试助手,实现数据无线传输。

    工程

    建工程

    打开Vscode,并保证esp-idf 插件安装完成并能正常使用。之后按F1,输入esp-idf 选择历程进入。
    在这里插入图片描述

    增加属性表特征

    增加属性表配置特征值用来描述 的相关信息:(可仿照特征A来写),同时将相关的宏定义和相关的变量进行定义完善。

    UUID定义

    在这里插入图片描述

    属性声明(枚举)

    在这里插入图片描述### 增加配置属性
    在这里插入图片描述

    变量值声明

    在这里插入图片描述

    数据接收

    在这里插入图片描述

    数据发送

    在这里插入图片描述

    实验结果

    在这里插入图片描述

    程序demo

    主程序代码

    /*
     * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
     *
     * SPDX-License-Identifier: Unlicense OR CC0-1.0
     */
    
    /****************************************************************************
    *
    * This demo showcases creating a GATT database using a predefined attribute table.
    * It acts as a GATT server and can send adv data, be connected by client.
    * Run the gatt_client demo, the client demo will automatically connect to the gatt_server_service_table demo.
    * Client demo will enable GATT server's notify after connection. The two devices will then exchange
    * data.
    *
    ****************************************************************************/
    
    
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "freertos/event_groups.h"
    #include "esp_system.h"
    #include "esp_log.h"
    #include "nvs_flash.h"
    #include "esp_bt.h"
    
    #include "esp_gap_ble_api.h"
    #include "esp_gatts_api.h"
    #include "esp_bt_main.h"
    #include "gatts_table_creat_demo.h"
    
    
    #include "esp_gatt_common_api.h"
    
    #define GATTS_TABLE_TAG "GATTS_TABLE_DEMO"
    
    #define PROFILE_NUM                 1
    #define PROFILE_APP_IDX             0
    #define ESP_APP_ID                  0x55
    #define SAMPLE_DEVICE_NAME          "TPMS_"
    #define SVC_INST_ID                 0
    
    /* The max length of characteristic value. When the GATT client performs a write or prepare write operation,
    *  the data length must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
    */
    #define GATTS_DEMO_CHAR_VAL_LEN_MAX 500
    #define PREPARE_BUF_MAX_SIZE        1024
    #define CHAR_DECLARATION_SIZE       (sizeof(uint8_t))
    
    #define ADV_CONFIG_FLAG             (1 << 0)
    #define SCAN_RSP_CONFIG_FLAG        (1 << 1)
    
    static uint8_t adv_config_done       = 0;
    
    uint16_t heart_rate_handle_table[HRS_IDX_NB];
    
    typedef struct {
        uint8_t                 *prepare_buf;
        int                     prepare_len;
    } prepare_type_env_t;
    
    static prepare_type_env_t prepare_write_env;
    
    //#define CONFIG_SET_RAW_ADV_DATA
    #ifdef CONFIG_SET_RAW_ADV_DATA
    static uint8_t raw_adv_data[] = {
            /* flags */
            0x02, 0x01, 0x06,
            /* tx power*/
            0x02, 0x0a, 0xeb,
            /* service uuid */
            0x03, 0x03, 0xFF, 0x00,
            /* device name */
            0x0f, 0x09, 'E', 'S', 'P', '_', 'G', 'A', 'T', 'T', 'S', '_', 'D','E', 'M', 'O'
    };
    static uint8_t raw_scan_rsp_data[] = {
            /* flags */
            0x02, 0x01, 0x06,
            /* tx power */
            0x02, 0x0a, 0xeb,
            /* service uuid */
            0x03, 0x03, 0xFF,0x00
    };
    
    #else
    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, 0xFF, 0x00, 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        = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec
        .max_interval        = 0x0010, //slave connection max interval, Time = max_interval * 1.25 msec
        .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        = 0x0006,
        .max_interval        = 0x0010,
        .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),
    };
    #endif /* CONFIG_SET_RAW_ADV_DATA */
    
    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,
    };
    
    struct gatts_profile_inst {
        esp_gatts_cb_t gatts_cb;
        uint16_t gatts_if;
        uint16_t app_id;
        uint16_t conn_id;
        uint16_t service_handle;
        esp_gatt_srvc_id_t service_id;
        uint16_t char_handle;
        esp_bt_uuid_t char_uuid;
        esp_gatt_perm_t perm;
        esp_gatt_char_prop_t property;
        uint16_t descr_handle;
        esp_bt_uuid_t descr_uuid;
    };
    
    static void gatts_profile_event_handler(esp_gatts_cb_event_t event,
    					esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);
    
    /* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
    static struct gatts_profile_inst heart_rate_profile_tab[PROFILE_NUM] = {
        [PROFILE_APP_IDX] = {
            .gatts_cb = gatts_profile_event_handler,
            .gatts_if = ESP_GATT_IF_NONE,       /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
        },
    };
    
    /* Service */
    static const uint16_t GATTS_SERVICE_UUID_TEST      = 0x00FF;
    static const uint16_t GATTS_CHAR_UUID_TEST_A       = 0xFF01;
    static const uint16_t GATTS_CHAR_UUID_TEST_B       = 0xFF02;
    static const uint16_t GATTS_CHAR_UUID_TEST_C       = 0xFF03;
    
    static const uint16_t GATTS_CHAR_UUID_TEST_TPMS_OUT        = 0xFF04; //APP 输出
    static const uint16_t GATTS_CHAR_UUID_TEST_TPMS_IN        = 0xFF05;    //APP接收
    
    
    static const uint16_t primary_service_uuid         = ESP_GATT_UUID_PRI_SERVICE;
    static const uint16_t character_declaration_uuid   = ESP_GATT_UUID_CHAR_DECLARE;
    static const uint16_t character_client_config_uuid = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
    static const uint8_t char_prop_read                =  ESP_GATT_CHAR_PROP_BIT_READ;
    static const uint8_t char_prop_write               = ESP_GATT_CHAR_PROP_BIT_WRITE;
    static const uint8_t char_prop_read_write_notify   = ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
    static const uint8_t heart_measurement_ccc[2]      = {0x00, 0x00};
    static const uint8_t char_value[4]                 = {0x11, 0x22, 0x33, 0x44};
    
    
    
    static const uint8_t tpms_out_value[20]                 = {0};
    static const uint8_t tpms_IN_value[20]                 = {0};
    
    
    
    /* Full Database Description - Used to add attributes into the database */
    static const esp_gatts_attr_db_t gatt_db[HRS_IDX_NB] =
    {
        // Service Declaration
        [IDX_SVC]        =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&primary_service_uuid, ESP_GATT_PERM_READ,
          sizeof(uint16_t), sizeof(GATTS_SERVICE_UUID_TEST), (uint8_t *)&GATTS_SERVICE_UUID_TEST}},
    
        /* Characteristic Declaration */
        [IDX_CHAR_A]     =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
          CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
    
        /* Characteristic Value */
        [IDX_CHAR_VAL_A] =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_A, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
    
        /* Client Characteristic Configuration Descriptor */
        [IDX_CHAR_CFG_A]  =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
    
    
    
        /* Characteristic Declaration */
        [IDX_CHAR_B]      =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
          CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}},
        /* Characteristic Value */
        [IDX_CHAR_VAL_B]  =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_B, ESP_GATT_PERM_READ ,
          GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
    //-------------------------- 自定义   -----------------------------------------------------------------------------------
        /* Characteristic Declaration */
        [IDX_CHAR_TPMS_OUT]      =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
          CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
    
        /* Characteristic Value */
        [IDX_CHAR_VAL_TPMS_OUT]  =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_TPMS_OUT, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(tpms_out_value), (uint8_t *)tpms_out_value}},
    //-------------------------- 自定义  -----------------------------------------------------------------------------------
        /* Characteristic Declaration */
        [IDX_CHAR_TPMS_IN]     =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
          CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_notify}},
    
        /* Characteristic Value */
        [IDX_CHAR_VAL_TPMS_IN] =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_TPMS_IN, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(tpms_IN_value), (uint8_t *)tpms_IN_value}},
    
        /* Client Characteristic Configuration Descriptor */
        [IDX_CHAR_CFG_TPMS_IN]  =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          sizeof(uint16_t), sizeof(heart_measurement_ccc), (uint8_t *)heart_measurement_ccc}},
    //-------------------------------------------------------------------------------------------------------------
    
    
    
    
        /* Characteristic Declaration */
        [IDX_CHAR_B]      =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
          CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read}},
    
        /* Characteristic Value */
        [IDX_CHAR_VAL_B]  =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_B, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
    
        /* Characteristic Declaration */
        [IDX_CHAR_C]      =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ,
          CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_write}},
    
        /* Characteristic Value */
        [IDX_CHAR_VAL_C]  =
        {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&GATTS_CHAR_UUID_TEST_C, ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
          GATTS_DEMO_CHAR_VAL_LEN_MAX, sizeof(char_value), (uint8_t *)char_value}},
    
    };
    
    static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
    {
        switch (event) {
        #ifdef CONFIG_SET_RAW_ADV_DATA
            case ESP_GAP_BLE_ADV_DATA_RAW_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_RAW_SET_COMPLETE_EVT:
                adv_config_done &= (~SCAN_RSP_CONFIG_FLAG);
                if (adv_config_done == 0){
                    esp_ble_gap_start_advertising(&adv_params);
                }
                break;
        #else
            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;
        #endif
            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(GATTS_TABLE_TAG, "advertising start failed");
                }else{
                    ESP_LOGI(GATTS_TABLE_TAG, "advertising start successfully");
                }
                break;
            case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
                if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
                    ESP_LOGE(GATTS_TABLE_TAG, "Advertising stop failed");
                }
                else {
                    ESP_LOGI(GATTS_TABLE_TAG, "Stop adv successfully\n");
                }
                break;
            case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
                ESP_LOGI(GATTS_TABLE_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;
            default:
                break;
        }
    }
    
    void example_prepare_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param)
    {
        ESP_LOGI(GATTS_TABLE_TAG, "prepare write, handle = %d, value len = %d", param->write.handle, param->write.len);
        esp_gatt_status_t status = ESP_GATT_OK;
        if (prepare_write_env->prepare_buf == NULL) {
            prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t));
            prepare_write_env->prepare_len = 0;
            if (prepare_write_env->prepare_buf == NULL) {
                ESP_LOGE(GATTS_TABLE_TAG, "%s, Gatt_server prep no mem", __func__);
                status = ESP_GATT_NO_RESOURCES;
            }
        } else {
            if(param->write.offset > PREPARE_BUF_MAX_SIZE) {
                status = ESP_GATT_INVALID_OFFSET;
            } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
                status = ESP_GATT_INVALID_ATTR_LEN;
            }
        }
        /*send response when param->write.need_rsp is true */
        if (param->write.need_rsp){
            esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t));
            if (gatt_rsp != NULL){
                gatt_rsp->attr_value.len = param->write.len;
                gatt_rsp->attr_value.handle = param->write.handle;
                gatt_rsp->attr_value.offset = param->write.offset;
                gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
                memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len);
                esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp);
                if (response_err != ESP_OK){
                   ESP_LOGE(GATTS_TABLE_TAG, "Send response error");
                }
                free(gatt_rsp);
            }else{
                ESP_LOGE(GATTS_TABLE_TAG, "%s, malloc failed", __func__);
            }
        }
        if (status != ESP_GATT_OK){
            return;
        }
        memcpy(prepare_write_env->prepare_buf + param->write.offset,
               param->write.value,
               param->write.len);
        prepare_write_env->prepare_len += param->write.len;
    
    }
    
    void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
        if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_EXEC && prepare_write_env->prepare_buf){
            esp_log_buffer_hex(GATTS_TABLE_TAG, prepare_write_env->prepare_buf, prepare_write_env->prepare_len);
        }else{
            ESP_LOGI(GATTS_TABLE_TAG,"ESP_GATT_PREP_WRITE_CANCEL");
        }
        if (prepare_write_env->prepare_buf) {
            free(prepare_write_env->prepare_buf);
            prepare_write_env->prepare_buf = NULL;
        }
        prepare_write_env->prepare_len = 0;
    }
    
    
    
    TaskHandle_t *pTask = NULL;
    volatile bool notify_flag = false;
    
    
    static void get_TPMS_IN(void *arg)
    {
        uint8_t buff[20] = {0};
        
        while (1)
        {
            if (notify_flag == true)
            {
    
              for (size_t i = 0; i < 19; i++)
              {
                 buff[i] = 'A'+i;
              }
              
                esp_ble_gatts_set_attr_value(heart_rate_handle_table[IDX_CHAR_TPMS_IN], 19, buff);
                esp_ble_gatts_send_indicate(heart_rate_profile_tab[0].gatts_if, heart_rate_profile_tab[0].conn_id,
                                                            heart_rate_handle_table[IDX_CHAR_VAL_TPMS_IN], 19,buff, false);
            }else{
                vTaskDelete(NULL);
            }
            vTaskDelay(pdMS_TO_TICKS(2000));
        }
    }
    
    
    
    static void gatts_profile_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(SAMPLE_DEVICE_NAME);
                if (set_dev_name_ret){
                    ESP_LOGE(GATTS_TABLE_TAG, "set device name failed, error code = %x", set_dev_name_ret);
                }
        #ifdef CONFIG_SET_RAW_ADV_DATA
                esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data));
                if (raw_adv_ret){
                    ESP_LOGE(GATTS_TABLE_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret);
                }
                adv_config_done |= ADV_CONFIG_FLAG;
                esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_scan_rsp_data, sizeof(raw_scan_rsp_data));
                if (raw_scan_ret){
                    ESP_LOGE(GATTS_TABLE_TAG, "config raw scan rsp data failed, error code = %x", raw_scan_ret);
                }
                adv_config_done |= SCAN_RSP_CONFIG_FLAG;
        #else
                //config adv data
                esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);
                if (ret){
                    ESP_LOGE(GATTS_TABLE_TAG, "config adv data failed, error code = %x", ret);
                }
                adv_config_done |= ADV_CONFIG_FLAG;
                //config scan response data
                ret = esp_ble_gap_config_adv_data(&scan_rsp_data);
                if (ret){
                    ESP_LOGE(GATTS_TABLE_TAG, "config scan response data failed, error code = %x", ret);
                }
                adv_config_done |= SCAN_RSP_CONFIG_FLAG;
        #endif
                esp_err_t create_attr_ret = esp_ble_gatts_create_attr_tab(gatt_db, gatts_if, HRS_IDX_NB, SVC_INST_ID);
                if (create_attr_ret){
                    ESP_LOGE(GATTS_TABLE_TAG, "create attr table failed, error code = %x", create_attr_ret);
                }
            }
           	    break;
            case ESP_GATTS_READ_EVT:
                ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_READ_EVT");
    
    
           	    break;
            case ESP_GATTS_WRITE_EVT:
                if (!param->write.is_prep){
                    // the data length of gattc write  must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
                    ESP_LOGI(GATTS_TABLE_TAG, "GATT_WRITE_EVT, handle = %d, value len = %d, value :", param->write.handle, param->write.len);
                    esp_log_buffer_hex(GATTS_TABLE_TAG, param->write.value, param->write.len);
                    if (heart_rate_handle_table[IDX_CHAR_CFG_A] == param->write.handle && param->write.len == 2){
    
                    }else if(heart_rate_handle_table[IDX_CHAR_VAL_TPMS_OUT] == param->write.handle){
    
                        esp_log_buffer_hex(GATTS_TABLE_TAG,param->write.value,param->write.len);
    
    
                    }else if(heart_rate_handle_table[IDX_CHAR_CFG_TPMS_IN] == param->write.handle){
    
                        esp_log_buffer_hex(GATTS_TABLE_TAG,param->write.value,param->write.len);
                        notify_flag = true ;
                        ESP_LOGI(GATTS_TABLE_TAG, "notify enable");
                        xTaskCreate(get_TPMS_IN, "get temp", 8192, NULL, 10, pTask);
    
                    }
    
                    /* send response when param->write.need_rsp is true*/
                    if (param->write.need_rsp){
                        esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
                    }
                }else{
                    /* handle prepare write */
                    example_prepare_write_event_env(gatts_if, &prepare_write_env, param);
                }
          	    break;
            case ESP_GATTS_EXEC_WRITE_EVT:
                // the length of gattc prepare write data must be less than GATTS_DEMO_CHAR_VAL_LEN_MAX.
                ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_EXEC_WRITE_EVT");
                example_exec_write_event_env(&prepare_write_env, param);
                break;
            case ESP_GATTS_MTU_EVT:
                ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);
                break;
            case ESP_GATTS_CONF_EVT:
                ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONF_EVT, status = %d, attr_handle %d", param->conf.status, param->conf.handle);
                break;
            case ESP_GATTS_START_EVT:
                ESP_LOGI(GATTS_TABLE_TAG, "SERVICE_START_EVT, status %d, service_handle %d", param->start.status, param->start.service_handle);
                break;
            case ESP_GATTS_CONNECT_EVT:
                ESP_LOGI(GATTS_TABLE_TAG, "ESP_GATTS_CONNECT_EVT, conn_id = %d", param->connect.conn_id);
                esp_log_buffer_hex(GATTS_TABLE_TAG, 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 refer to 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(GATTS_TABLE_TAG, "ESP_GATTS_DISCONNECT_EVT, reason = 0x%x", param->disconnect.reason);
                esp_ble_gap_start_advertising(&adv_params);
    
                notify_flag = false;
                break;
            case ESP_GATTS_CREAT_ATTR_TAB_EVT:{
                if (param->add_attr_tab.status != ESP_GATT_OK){
                    ESP_LOGE(GATTS_TABLE_TAG, "create attribute table failed, error code=0x%x", param->add_attr_tab.status);
                }
                else if (param->add_attr_tab.num_handle != HRS_IDX_NB){
                    ESP_LOGE(GATTS_TABLE_TAG, "create attribute table abnormally, num_handle (%d) \
                            doesn't equal to HRS_IDX_NB(%d)", param->add_attr_tab.num_handle, HRS_IDX_NB);
                }
                else {
                    ESP_LOGI(GATTS_TABLE_TAG, "create attribute table successfully, the number handle = %d\n",param->add_attr_tab.num_handle);
                    memcpy(heart_rate_handle_table, param->add_attr_tab.handles, sizeof(heart_rate_handle_table));
                    esp_ble_gatts_start_service(heart_rate_handle_table[IDX_SVC]);
                }
                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;
        }
    }
    
    
    static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
    {
    
        /* 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) {
                heart_rate_profile_tab[PROFILE_APP_IDX].gatts_if = gatts_if;
            } else {
                ESP_LOGE(GATTS_TABLE_TAG, "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 == heart_rate_profile_tab[idx].gatts_if) {
                    if (heart_rate_profile_tab[idx].gatts_cb) {
                        heart_rate_profile_tab[idx].gatts_cb(event, gatts_if, param);
                    }
                }
            }
        } while (0);
    }
    
    void app_main(void)
    {
        esp_err_t ret;
    
        /* Initialize NVS. */
        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(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
            return;
        }
    
        ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
        if (ret) {
            ESP_LOGE(GATTS_TABLE_TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
            return;
        }
    
        ret = esp_bluedroid_init();
        if (ret) {
            ESP_LOGE(GATTS_TABLE_TAG, "%s init bluetooth failed: %s", __func__, esp_err_to_name(ret));
            return;
        }
    
        ret = esp_bluedroid_enable();
        if (ret) {
            ESP_LOGE(GATTS_TABLE_TAG, "%s enable bluetooth failed: %s", __func__, esp_err_to_name(ret));
            return;
        }
    
        ret = esp_ble_gatts_register_callback(gatts_event_handler);
        if (ret){
            ESP_LOGE(GATTS_TABLE_TAG, "gatts register error, error code = %x", ret);
            return;
        }
    
        ret = esp_ble_gap_register_callback(gap_event_handler);
        if (ret){
            ESP_LOGE(GATTS_TABLE_TAG, "gap register error, error code = %x", ret);
            return;
        }
    
        ret = esp_ble_gatts_app_register(ESP_APP_ID);
        if (ret){
            ESP_LOGE(GATTS_TABLE_TAG, "gatts app register error, error code = %x", ret);
            return;
        }
    
        esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(500);
        if (local_mtu_ret){
            ESP_LOGE(GATTS_TABLE_TAG, "set local  MTU failed, error code = %x", local_mtu_ret);
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648

    声明

    /*
     * SPDX-FileCopyrightText: 2021 Espressif Systems (Shanghai) CO LTD
     *
     * SPDX-License-Identifier: Unlicense OR CC0-1.0
     */
    
    
    #include 
    #include 
    #include 
    
    
    /* Attributes State Machine */
    enum
    {
        IDX_SVC,
        IDX_CHAR_A,
        IDX_CHAR_VAL_A,
        IDX_CHAR_CFG_A,
        // 自定义属性1
        IDX_CHAR_TPMS_OUT,
        IDX_CHAR_VAL_TPMS_OUT, 
        // 自定义属性2
        IDX_CHAR_TPMS_IN,
        IDX_CHAR_VAL_TPMS_IN,
        IDX_CHAR_CFG_TPMS_IN,
    
    
        IDX_CHAR_B,
        IDX_CHAR_VAL_B,
    
        IDX_CHAR_C,
        IDX_CHAR_VAL_C,
    
        HRS_IDX_NB,
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    C++ Reference: Standard C++ Library reference: C Library: cstring: strcpy
    重温C#中的值类型和引用类型
    Leo赠书活动-08期 【程序员到架构师演变】文末送书
    视图、存储过程、触发器
    q-learning强化学习使用基础
    支持国密ssl的curl编译和测试验证(上)
    第54节—— redux-toolkit中的configureStore
    JavaScript基础---JavaScript对象---10.19
    动手学深度学习_个人笔记_李沐(更新中......)
    如何使用 MySQL 做全文检索这件事
  • 原文地址:https://blog.csdn.net/qq_43940227/article/details/132721717