esp32-S3专题三:外设2之蓝牙使用

esp32-S3专题三:外设2之蓝牙使用

一、介绍

物联网设备中,蓝牙功能的经常搭配wifi使用。在设备首次使用阶段中,给无网络连接状态下的设备,传输wifi的连接信息和相关证书等。而s3模块就搭配了蓝牙模块,并且内置了蓝牙协议栈。

二、BluFi 简介

官网有详细的蓝牙协议的讲解,这里就不做铺开讲解。可以看看

https://docs.espressif.com/projects/esp-idf/zh_CN/release-v4.4/esp32s3/api-guides/blufi.html

本次教程参考例程的是 gatt_server,结合此例程做快速的配置和解析。蓝牙协议交互流程如下(图片引用esp官网)

三、例程解析

(一)蓝牙名称和UUID初始化

1.注销默认值service uuid 和 device name

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'

// 0x15, 0x09, 'X','W','_','H','_','X', '_', '2','2','0','4','2','0','_','0','0','0','0','0','2'

};

static uint8_t raw_scan_rsp_data[] = {

/* flags */

0x02, 0x01, 0x06,

/* tx power */

0x02, 0x0a, 0xeb,

/* service uuid */

// 0x03, 0x03, 0xFF,0x00

};

1.UUID设置(例程实现)

//默认值

static esp_bt_uuid_t service_uuid_main = {

.len = ESP_UUID_LEN_128,

.uuid = {.uuid128 ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xBB, 0x23, 0xB1, 0x00, 0x63, 0x01, 0x00, 0x40, 0x6E},},

};

static esp_bt_uuid_t service_uuid_rx = {

.len = ESP_UUID_LEN_128,

.uuid = {.uuid128 ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xBB, 0x23, 0xB1, 0x00, 0x63, 0x02, 0x00, 0x40, 0x6E},},

};

static esp_bt_uuid_t service_uuid_tx = {

.len = ESP_UUID_LEN_128,

.uuid = {.uuid128 ={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x23, 0xBB, 0x23, 0xB1, 0x00, 0x63, 0x03, 0x00, 0x40, 0x6E},},

};

2.设置UUID的函数

void set_ble_udid(){

uint8_t baseMac[6]={0};

esp_read_mac(baseMac, ESP_MAC_WIFI_STA);//将wifi的mac设置给蓝牙,也可以自行构造

for(int i=0;i<6;i++){

service_uuid_main.uuid.uuid128[i]=mmac[i];

service_uuid_rx.uuid.uuid128[i]=mmac[i];

service_uuid_tx.uuid.uuid128[i]=mmac[i];

}

}

3.uuid和特征值生效代码(例程实现)

//

//特征值使用默认设置

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_READ | ESP_GATT_CHAR_PROP_BIT_WRITE;

static const uint8_t char_prop_notify = 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 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,

ESP_UUID_LEN_128, ESP_UUID_LEN_128, (uint8_t *)service_uuid_main.uuid.uuid128}},

/* 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_write}},

/* Characteristic Value */

[IDX_CHAR_VAL_B] =

{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, (uint8_t *)service_uuid_rx.uuid.uuid128, 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_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_notify}},

/* Characteristic Value */

[IDX_CHAR_VAL_A] =

{{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_128, (uint8_t *)&service_uuid_tx.uuid.uuid128, 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}},

};

4.设置蓝牙名称后传入gatts_profile_event_handler

static char ble_name[16] = {0};

void set_ble_name(){

char ble_name[16] = "test_ble";

memcpy(ble_name,ble_name,strlen(ble_name));

}

//此次代码不全,具体参考例程

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 raw_adv_ret = esp_ble_gap_config_adv_data_raw(ble_name, strlen(ble_name)+1);

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;

..........................

}

(二)蓝牙功能初始化

直接参考例程,设置相关模式,并打开蓝牙

void ble_init(){

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

}

/* set the security iocap & auth_req & key size & init key response key parameters to the stack*/

esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND; //bonding with peer device after authentication

esp_ble_io_cap_t iocap = ESP_IO_CAP_NONE; //set the IO capability to No output No input

uint8_t key_size = 16; //the key size should be 7~16 bytes

uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;

uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;

uint8_t oob_support = ESP_BLE_OOB_DISABLE;

esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));

esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));

esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));

esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t));

/* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribute to you,

and the response key means which key you can distribute to the Master;

If your BLE device act as a master, the response key means you hope which types of key of the slave should distribute to you,

and the init key means which key you can distribute to the slave. */

esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));

esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));

}

(三)蓝牙消息发送函数

//参数在蓝牙连接成功后,在gatts_event_handler回调函数里更新

static esp_gatt_if_t ble_gatts_if = 0;

static uint16_t ble_conn_id=0xFF;//本次代码只采用notify方式发送消息

static uint16_t ble_attr_handle;

nt ble_send_msg(char *send_buf){

esp_ble_gatts_send_indicate(ble_gatts_if, ble_conn_id, ble_attr_handle,strlen(send_buf)+1, send_buf, false);

}

(四)蓝牙消息接收函数

static char ble_rec_buf[256] = {0};

static void ble_data_rec(uint8_t* data,int len){

ESP_LOGI(GATTS_TABLE_TAG,"ble_data_cb %s",data);

memcpy(ble_rec_buf,data,len);

}

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

..............................

..............................

..............................

case ESP_GATTS_WRITE_EVT:

if (!param->write.is_prep){

..........

if (heart_rate_handle_table[IDX_CHAR_CFG_A] == param->write.handle && param->write.len == 2){

uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];

if (descr_value == 0x0001){ // notify 建立连接,并更新连接值

ESP_LOGI(GATTS_TABLE_TAG, "notify enable");

ble_gatts_if = gatts_if;

ble_conn_id = param->write.conn_id;

ble_attr_handle = heart_rate_handle_table[IDX_CHAR_VAL_A];

}

........

}else{

ble_data_rec(param->write.value,param->write.len); //接收回调

}

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

}

}

.........................

.........................

.........................

}

(五)关闭蓝牙使用

void bledeInit()

{

esp_ble_gatts_app_unregister(ESP_APP_ID);

esp_bluedroid_disable();

esp_bluedroid_deinit();

esp_bt_controller_disable();

esp_bt_controller_deinit();

}

四、总结

以上是esp32的ble简单使用,如果是传输证书等机密信息,esp32官方还提高ble信息加密传输,有兴趣可以去官方了解一下,纯项目技术分享,更新不易,如有帮助,点赞一下。

相关星际资讯

手机解压游戏怎么安装
bat365入口

手机解压游戏怎么安装

🕒 06-28 👁️ 4137
苹果海战游戏有哪些(ios海战类型游戏)
365体育手机版app下载

苹果海战游戏有哪些(ios海战类型游戏)

🕒 06-30 👁️ 4037
买完机票多长时间能收到出票信息,没有出票信息影响乘坐飞机吗