别再乱用通配符了!SpringBoot3中PathPattern的精确匹配到底强在哪?
2026/6/2 5:07:01
ESP8684是乐鑫推出的一款低功耗Wi-Fi+蓝牙双模SoC,基于ESP8684芯片设计,集成了完整的Wi-Fi 4和蓝牙5.0 BR/EDR + BLE功能。本文将详细介绍如何基于ESP32C2芯片上使用Arduino和ESP-IDF开发框架进行蓝牙通信协议的开发,包括经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)两种模式。
NimBLE库创建服务与特征,示例代码:数据发送与接收回调。idf.py monitor与Wireshark抓包。注:实际开发需结合具体硬件型号(如ESP32-C3与ESP32-C2差异)调整代码实现。
ESP32C2的蓝牙子系统采用了分层架构:
安装Arduino IDE:下载并安装最新版本的Arduino IDE
添加ESP32开发板支持:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json选择开发板:
经典蓝牙主要用于传输音频、文件等大数据量应用,支持SPP(串行端口协议)、A2DP(音频传输)、HFP(免提协议)等 profile。
以下是一个简单的SPP服务示例,实现蓝牙串口通信:
#include<BluetoothSerial.h>BluetoothSerial SerialBT;voidsetup(){Serial.begin(115200);SerialBT.begin("ESP8684_SPP");// 设置蓝牙设备名称Serial.println("蓝牙串口服务已启动,等待连接...");}voidloop(){if(Serial.available()){SerialBT.write(Serial.read());}if(SerialBT.available()){Serial.write(SerialBT.read());}delay(20);}BluetoothSerial.h库,提供经典蓝牙功能BluetoothSerial SerialBT创建蓝牙串口对象SerialBT.begin("ESP8684_SPP")初始化蓝牙服务,设置设备名称Serial和SerialBT之间的数据转发实现串口透传功能BLE(Bluetooth Low Energy)低功耗蓝牙,主要用于低功耗、小数据量的应用场景,采用GATT(通用属性协议)架构。
BLE的核心概念:
#include<BLEDevice.h>#include<BLEServer.h>#include<BLEUtils.h>#include<BLE2902.h>// 定义服务和特征UUID#defineSERVICE_UUID"4fafc201-1fb5-459e-8fcc-c5c9c331914b"#defineCHARACTERISTIC_UUID"beb5483e-36e1-4688-b7f5-ea07361b26a8"BLEServer*pServer=NULL;BLECharacteristic*pCharacteristic=NULL;booldeviceConnected=false;uint32_tvalue=0;classMyServerCallbacks:publicBLEServerCallbacks{voidonConnect(BLEServer*pServer){deviceConnected=true;Serial.println("设备已连接");};voidonDisconnect(BLEServer*pServer){deviceConnected=false;Serial.println("设备已断开连接");// 重启广告以便重新连接BLEAdvertising*pAdvertising=pServer->getAdvertising();pAdvertising->start();}};classMyCallbacks:publicBLECharacteristicCallbacks{voidonWrite(BLECharacteristic*pCharacteristic){std::string value=pCharacteristic->getValue();if(value.length()>0){Serial.println("收到数据:");for(inti=0;i<value.length();i++){Serial.print(value[i]);}Serial.println();}}};voidsetup(){Serial.begin(115200);Serial.println("初始化BLE服务...");// 创建BLE设备BLEDevice::init("ESP8684_BLE");// 创建BLE服务器pServer=BLEDevice::createServer();pServer->setCallbacks(newMyServerCallbacks());// 创建BLE服务BLEService*pService=pServer->createService(SERVICE_UUID);// 创建BLE特征pCharacteristic=pService->createCharacteristic(CHARACTERISTIC_UUID,BLECharacteristic::PROPERTY_READ|BLECharacteristic::PROPERTY_WRITE|BLECharacteristic::PROPERTY_NOTIFY|BLECharacteristic::PROPERTY_INDICATE);// 添加描述符pCharacteristic->addDescriptor(newBLE2902());pCharacteristic->setCallbacks(newMyCallbacks());// 设置初始值pCharacteristic->setValue("Hello BLE");// 启动服务pService->start();// 启动广告BLEAdvertising*pAdvertising=BLEDevice::getAdvertising();pAdvertising->addServiceUUID(SERVICE_UUID);pAdvertising->setScanResponse(true);pAdvertising->setMinPreferred(0x06);// 功率级别pAdvertising->setMinPreferred(0x12);BLEDevice::startAdvertising();Serial.println("BLE服务已启动,等待连接...");}voidloop(){if(deviceConnected){// 更新特征值并发送通知pCharacteristic->setValue((uint8_t*)&value,4);pCharacteristic->notify();value++;delay(1000);}}idf.py menuconfig在menuconfig中配置:
Component config->Bluetooth-> 启用Classic BluetoothComponent config->Bluetooth Serial Port Profile (SPP)-> 启用SPP服务#include<stdio.h>#include"freertos/FreeRTOS.h"#include"freertos/task.h"#include"esp_system.h"#include"esp_log.h"#include"nvs_flash.h"#include"bt.h"#include"bta_api.h"#include"esp_spp_api.h"staticconstcharTAG[]="ESP_SPP_EXAMPLE";#defineSPP_SERVER_NAME"ESP8684 SPP Server"#defineEXAMPLE_DEVICE_NAME"ESP8684_BT"staticvoidesp_spp_cb(esp_spp_cb_event_tevent,esp_spp_cb_param_t*param){switch(event){caseESP_SPP_INIT_EVT:ESP_LOGI(TAG,"ESP_SPP_INIT_EVT");esp_spp_start_srv(ESP_SPP_SEC_AUTHENTICATE,ESP_SPP_ROLE_SLAVE,0,SPP_SERVER_NAME);break;caseESP_SPP_OPEN_EVT:ESP_LOGI(TAG,"ESP_SPP_OPEN_EVT");break;caseESP_SPP_DATA_IND_EVT:ESP_LOGI(TAG,"ESP_SPP_DATA_IND_EVT len=%d handle=%d",param->data_ind.len,param->data_ind.handle);esp_log_buffer_hex(TAG,param->data_ind.data,param->data_ind.len);// 回显收到的数据esp_spp_write(param->data_ind.handle,param->data_ind.len,param->data_ind.data);break;caseESP_SPP_CLOSE_EVT:ESP_LOGI(TAG,"ESP_SPP_CLOSE_EVT");break;default:break;}}voidapp_main(void){esp_err_tret=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_LOGI(TAG,"BT Init");esp_bt_controller_config_tbt_cfg=BT_CONTROLLER_INIT_CONFIG_DEFAULT();if((ret=esp_bt_controller_init(&bt_cfg))!=ESP_OK){ESP_LOGE(TAG,"%s initialize controller failed: %s",__func__,esp_err_to_name(ret));return;}if((ret=esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT))!=ESP_OK){ESP_LOGE(TAG,"%s enable controller failed: %s",__func__,esp_err_to_name(ret));return;}if((ret=esp_bluedroid_init())!=ESP_OK){ESP_LOGE(TAG,"%s initialize bluedroid failed: %s",__func__,esp_err_to_name(ret));return;}if((ret=esp_bluedroid_enable())!=ESP_OK){ESP_LOGE(TAG,"%s enable bluedroid failed: %s",__func__,esp_err_to_name(ret));return;}if((ret=esp_spp_register_callback(esp_spp_cb))!=ESP_OK){ESP_LOGE(TAG,"%s spp register failed: %s",__func__,esp_err_to_name(ret));return;}if((ret=esp_spp_init(ESP_SPP_MODE_CB))!=ESP_OK){ESP_LOGE(TAG,"%s spp init failed: %s",__func__,esp_err_to_name(ret));return;}esp_bt_dev_set_device_name(EXAMPLE_DEVICE_NAME);esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE,ESP_BT_GENERAL_DISCOVERABLE);}idf.py menuconfig在menuconfig中配置:
Component config->Bluetooth-> 启用Bluetooth和BLEComponent config->Bluetooth->BLE-> 启用所需的BLE功能#include<stdio.h>#include"freertos/FreeRTOS.h"#include"freertos/task.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"esp_gatt_common_api.h"staticconstcharTAG[]="ESP_BLE_EXAMPLE";#defineGATTS_SERVICE_UUID_TEST0x00FF#defineGATTS_CHAR_UUID_TEST0xFF01#defineGATTS_DESCR_UUID_TEST0x3333#defineGATTS_NUM_HANDLE_TEST4#defineTEST_DEVICE_NAME"ESP8684_BLE"#defineTEST_MANUFACTURER_DATA_LEN17staticuint8_tmanufacturer_data[TEST_MANUFACTURER_DATA_LEN]={0x12,0x23,0x34,0x45,0x56,0x67,0x78,0x89,0x9a,0xab,0xbc,0xcd,0xde,0xef,0xf0,0x0f,0x10};staticuint16_thandle_table[GATTS_NUM_HANDLE_TEST]={0};staticesp_gatt_if_tgatt_if=ESP_GATT_IF_NONE;staticesp_gatts_attr_db_tgatt_db[GATTS_NUM_HANDLE_TEST]={// 服务声明[0]={.attr_control=ESP_GATT_AUTO_RSP,.att_desc={.uuid_length=ESP_UUID_LEN_16,.uuid_p=(uint8_t*)&primary_service_uuid,.perm=0,.max_length=sizeof(uint16_t),.length=sizeof(uint16_t),.value=(uint8_t*)&GATTS_SERVICE_UUID_TEST,},},// 特征声明[1]={.attr_control=ESP_GATT_AUTO_RSP,.att_desc={.uuid_length=ESP_UUID_LEN_16,.uuid_p=(uint8_t*)&character_declaration_uuid,.perm=0,.max_length=ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY,.length=ESP_GATT_CHAR_PROP_BIT_READ|ESP_GATT_CHAR_PROP_BIT_WRITE|ESP_GATT_CHAR_PROP_BIT_NOTIFY,.value=NULL,},},// 特征值[2]={.attr_control=ESP_GATT_AUTO_RSP,.att_desc={.uuid_length=ESP_UUID_LEN_16,.uuid_p=(uint8_t*)&GATTS_CHAR_UUID_TEST,.perm=ESP_GATT_PERM_READ_ENCRYPTED|ESP_GATT_PERM_WRITE_ENCRYPTED,.max_length=4,.length=4,.value=(uint8_t*)"test",},},// 描述符[3]={.attr_control=ESP_GATT_AUTO_RSP,.att_desc={.uuid_length=ESP_UUID_LEN_16,.uuid_p=(uint8_t*)&character_client_config_uuid,.perm=ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE,.max_length=sizeof(uint16_t),.length=sizeof(uint16_t),.value=(uint8_t*)&gatts_demo_char2_desc,},},};staticvoidgatts_event_handler(esp_gatts_cb_event_tevent,esp_gatt_if_tgatts_if,esp_ble_gatts_cb_param_t*param){switch(event){caseESP_GATTS_REG_EVT:ESP_LOGI(TAG,"REG_EVT, status %d, app_id %d, gatts_if %d",param->reg.status,param->reg.app_id,gatts_if);gatt_if=gatts_if;// 创建服务esp_gatts_create_service(gatts_if,&gatt_db[0].att_desc.uuid,GATTS_NUM_HANDLE_TEST);break;caseESP_GATTS_READ_EVT:ESP_LOGI(TAG,"READ_EVT, conn_id %d, trans_id %d, handle %d",param->read.conn_id,param->read.trans_id,param->read.handle);break;caseESP_GATTS_WRITE_EVT:ESP_LOGI(TAG,"WRITE_EVT, conn_id %d, trans_id %d, handle %d",param->write.conn_id,param->write.trans_id,param->write.handle);if(!param->write.is_prep){ESP_LOGI(TAG,"GATT_WRITE_EVT, value len %d, value:",param->write.len);esp_log_buffer_hex(TAG,param->write.value,param->write.len);}break;caseESP_GATTS_EXEC_WRITE_EVT:ESP_LOGI(TAG,"EXEC_WRITE_EVT, conn_id %d, trans_id %d, flags %d",param->exec_write.conn_id,param->exec_write.trans_id,param->exec_write.flags);break;caseESP_GATTS_MTU_EVT:ESP_LOGI(TAG,"MTU_EVT, conn_id %d, mtu %d",param->mtu.conn_id,param->mtu.mtu);break;caseESP_GATTS_CONF_EVT:ESP_LOGI(TAG,"CONF_EVT, status %d, handle %d",param->conf.status,param->conf.handle);break;caseESP_GATTS_START_EVT:ESP_LOGI(TAG,"START_EVT, status %d",param->start.status);// 开始广告esp_ble_gap_config_adv_data(&adv_data);break;caseESP_GATTS_CONNECT_EVT:ESP_LOGI(TAG,"CONNECT_EVT, conn_id %d",param->connect.conn_id);break;caseESP_GATTS_DISCONNECT_EVT:ESP_LOGI(TAG,"DISCONNECT_EVT, reason %d",param->disconnect.reason);// 断开连接后重新开始广告esp_ble_gap_config_adv_data(&adv_data);break;default:break;}}staticvoidgap_event_handler(esp_gap_ble_cb_event_tevent,esp_ble_gap_cb_param_t*param){switch(event){caseESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:// 广告数据设置完成,开始广告esp_ble_gap_start_advertising();break;default:break;}}voidapp_main(void){esp_err_tret;// 初始化NVSret=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);// 初始化蓝牙ret=esp_bt_controller_init(&bt_cfg);if(ret){ESP_LOGE(TAG,"bt controller init failed: %s",esp_err_to_name(ret));return;}ret=esp_bt_controller_enable(ESP_BT_MODE_BLE);if(ret){ESP_LOGE(TAG,"bt controller enable failed: %s",esp_err_to_name(ret));return;}ret=esp_bluedroid_init();if(ret){ESP_LOGE(TAG,"bluedroid init failed: %s",esp_err_to_name(ret));return;}ret=esp_bluedroid_enable();if(ret){ESP_LOGE(TAG,"bluedroid enable failed: %s",esp_err_to_name(ret));return;}// 注册GAP回调esp_ble_gap_register_callback(gap_event_handler);// 注册GATTS回调esp_ble_gatts_register_callback(gatts_event_handler);// 注册应用esp_ble_gatts_app_register(0);// 设置设备名称esp_ble_gap_set_device_name(TEST_DEVICE_NAME);// 配置广告数据esp_ble_adv_data_tadv_data;memset(&adv_data,0,sizeof(adv_data));adv_data.set_scan_rsp=false;adv_data.include_name=true;adv_data.include_txpower=true;adv_data.min_interval=0x0006;// 100msadv_data.max_interval=0x0010;// 200msadv_data.manufacturer_len=TEST_MANUFACTURER_DATA_LEN;adv_data.p_manufacturer_data=manufacturer_data;adv_data.service_data_len=0;adv_data.p_service_data=NULL;adv_data.service_uuid_len=0;adv_data.p_service_uuid=NULL;adv_data.flag=(ESP_BLE_ADV_FLAG_GEN_DISC|ESP_BLE_ADV_FLAG_BREDR_NOT_SPT);esp_ble_gap_config_adv_data(&adv_data);}idf.py monitor查看调试日志esp_log_level_set("*", ESP_LOG_DEBUG)https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/index.htmlhttps://docs.espressif.com/projects/arduino-esp32/en/latest/https://www.bluetooth.com/specifications/bluetooth-core-specification/https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/bluetooth/index.html本文详细介绍了ESP8684(ESP32C2)平台上的蓝牙通信协议开发,涵盖了Arduino和ESP-IDF两种开发框架,以及经典蓝牙和BLE两种通信模式。