1、取消了蓝牙连接成功后发送蓝牙MAC地址的逻辑;

2、新增了蓝牙名称显示为“Airhub_”接蓝牙MAC地址的明文显示;
3、取消SDK配置蓝牙名称;
This commit is contained in:
Rdzleo 2026-02-10 16:16:28 +08:00
parent 1a48e387a8
commit d7ec6a5e63
5 changed files with 74 additions and 111 deletions

View File

@ -346,14 +346,6 @@ menu "蓝牙配网 (Bluetooth Provisioning)"
启用蓝牙配网功能允许通过蓝牙BLE连接配置WiFi网络。
需要ESP-IDF的蓝牙和BLUFI组件支持。
config BLUETOOTH_PROVISIONING_DEVICE_NAME
string "默认设备名称"
depends on BLUETOOTH_PROVISIONING_ENABLE
default "Airhub_Ble"
help
蓝牙配网时显示的默认设备名称。
可以在运行时通过API修改。
config BLUETOOTH_PROVISIONING_SECURITY
bool "启用安全模式"
depends on BLUETOOTH_PROVISIONING_ENABLE

View File

@ -122,6 +122,10 @@ static esp_ble_adv_params_t prov_adv_params = {
static uint8_t prov_adv_raw_data[31];
static uint8_t prov_adv_raw_len = 0;
// 扫描响应数据 (携带 TX Power + BLE MAC 地址)
static uint8_t prov_scan_rsp_data[31];
static uint8_t prov_scan_rsp_len = 0;
// ============================================================
// 构造 / 析构
// ============================================================
@ -133,8 +137,7 @@ BluetoothProvisioning::BluetoothProvisioning()
, initialized_(false)
, delayed_disconnect_(false)
, wifi_connecting_(false)
, mac_address_sent_(false)
, ble_mac_sent_(false) {
, mac_address_sent_(false) {
wifi_credentials_.ssid.clear();
wifi_credentials_.password.clear();
@ -351,7 +354,7 @@ bool BluetoothProvisioning::Deinitialize() {
// StartProvisioning — 构建原始广播数据并启动广播
// ============================================================
bool BluetoothProvisioning::StartProvisioning(const char* device_name) {
bool BluetoothProvisioning::StartProvisioning() {
ESP_LOGI(TAG, "🔵 开始启动蓝牙配网服务 (GATT Server)...");
ESP_LOGI(TAG, "🔍 检查初始化状态: initialized_ = %s", initialized_ ? "true" : "false");
@ -367,8 +370,6 @@ bool BluetoothProvisioning::StartProvisioning(const char* device_name) {
return true;
}
ESP_LOGI(TAG, "🚀 开始蓝牙配网,设备名称: %s", device_name);
// 重置状态
client_connected_ = false;
s_retry_num = 0;
@ -389,15 +390,30 @@ bool BluetoothProvisioning::StartProvisioning(const char* device_name) {
wifi_credentials_.bssid_set = false;
ESP_LOGI(TAG, "✅ WiFi凭据清除完成准备接收新的配网信息");
// 构建设备名称: "Airhub_" + BLE MAC 明文
char ble_device_name[32];
const uint8_t* ble_addr = esp_bt_dev_get_address();
if (ble_addr) {
snprintf(ble_device_name, sizeof(ble_device_name),
"Airhub_%02x:%02x:%02x:%02x:%02x:%02x",
ble_addr[0], ble_addr[1], ble_addr[2],
ble_addr[3], ble_addr[4], ble_addr[5]);
} else {
strcpy(ble_device_name, "Airhub_Ble");
ESP_LOGW(TAG, "获取BLE MAC失败使用默认名称: %s", ble_device_name);
}
// 设置设备名称
esp_err_t ret = esp_ble_gap_set_device_name(device_name);
esp_err_t ret = esp_ble_gap_set_device_name(ble_device_name);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "❌ 设置蓝牙设备名称失败: %s", esp_err_to_name(ret));
return false;
}
// 构建原始广播数据 (dzbj 方式: 直接放入设备名,手机系统蓝牙可搜索)
uint8_t name_len = strlen(device_name);
ESP_LOGI(TAG, "📡 蓝牙设备名称: %s", ble_device_name);
// 构建广播数据 (Flags + 设备名)
uint8_t name_len = strlen(ble_device_name);
int offset = 0;
// Flags: LE General Discoverable + BR/EDR Not Supported
@ -408,28 +424,35 @@ bool BluetoothProvisioning::StartProvisioning(const char* device_name) {
// Complete Local Name
prov_adv_raw_data[offset++] = name_len + 1;
prov_adv_raw_data[offset++] = ESP_BLE_AD_TYPE_NAME_CMPL;
memcpy(&prov_adv_raw_data[offset], device_name, name_len);
memcpy(&prov_adv_raw_data[offset], ble_device_name, name_len);
offset += name_len;
// TX Power Level
prov_adv_raw_data[offset++] = 0x02;
prov_adv_raw_data[offset++] = ESP_BLE_AD_TYPE_TX_PWR;
prov_adv_raw_data[offset++] = 0x09;
// 16-bit Service UUID Complete
prov_adv_raw_data[offset++] = 0x03;
prov_adv_raw_data[offset++] = ESP_BLE_AD_TYPE_16SRV_CMPL;
prov_adv_raw_data[offset++] = PROV_SERVICE_UUID & 0xFF;
prov_adv_raw_data[offset++] = (PROV_SERVICE_UUID >> 8) & 0xFF;
prov_adv_raw_len = offset;
ESP_LOGI(TAG, "📡 原始广播数据构建完成,长度: %d 字节", prov_adv_raw_len);
ESP_LOGI(TAG, "📡 广播数据构建完成,长度: %d 字节", prov_adv_raw_len);
// 配置原始广播数据 (GAP回调中会启动广播)
// 构建扫描响应数据 (TX Power + Service UUID)
int rsp_offset = 0;
// TX Power Level
prov_scan_rsp_data[rsp_offset++] = 0x02;
prov_scan_rsp_data[rsp_offset++] = ESP_BLE_AD_TYPE_TX_PWR;
prov_scan_rsp_data[rsp_offset++] = 0x09;
// 16-bit Service UUID Complete
prov_scan_rsp_data[rsp_offset++] = 0x03;
prov_scan_rsp_data[rsp_offset++] = ESP_BLE_AD_TYPE_16SRV_CMPL;
prov_scan_rsp_data[rsp_offset++] = PROV_SERVICE_UUID & 0xFF;
prov_scan_rsp_data[rsp_offset++] = (PROV_SERVICE_UUID >> 8) & 0xFF;
prov_scan_rsp_len = rsp_offset;
ESP_LOGI(TAG, "📡 扫描响应数据构建完成,长度: %d 字节", prov_scan_rsp_len);
// 配置广播数据 (GAP回调中会依次设置扫描响应数据并启动广播)
ret = esp_ble_gap_config_adv_data_raw(prov_adv_raw_data, prov_adv_raw_len);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "❌ 配置原始广播数据失败: %s", esp_err_to_name(ret));
ESP_LOGE(TAG, "❌ 配置广播数据失败: %s", esp_err_to_name(ret));
return false;
}
@ -484,8 +507,18 @@ void BluetoothProvisioning::GapEventHandler(esp_gap_ble_cb_event_t event,
esp_ble_gap_cb_param_t* param) {
switch (event) {
case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
// 原始广播数据设置完成,启动广播 (dzbj 方式)
ESP_LOGI(TAG, "📡 广播数据设置完成,启动广播");
// 广播数据设置完成,接着配置扫描响应数据
ESP_LOGI(TAG, "📡 广播数据设置完成,配置扫描响应数据");
if (prov_scan_rsp_len > 0) {
esp_ble_gap_config_scan_rsp_data_raw(prov_scan_rsp_data, prov_scan_rsp_len);
} else {
esp_ble_gap_start_advertising(&prov_adv_params);
}
break;
case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
// 扫描响应数据设置完成,启动广播
ESP_LOGI(TAG, "📡 扫描响应数据设置完成,启动广播");
esp_ble_gap_start_advertising(&prov_adv_params);
break;
@ -714,11 +747,6 @@ void BluetoothProvisioning::HandleGattsEvent(esp_gatts_cb_event_t event,
uint16_t cccd_value = param->write.value[0] | (param->write.value[1] << 8);
notify_enabled_ = (cccd_value == 0x0001);
ESP_LOGI(TAG, "NOTIFY %s", notify_enabled_ ? "已启用" : "已禁用");
// NOTIFY启用后立即发送BLE MAC地址确保iOS/Android都能获取
if (notify_enabled_) {
SendBleMacAddress();
}
}
if (param->write.need_rsp) {
@ -1098,54 +1126,9 @@ bool BluetoothProvisioning::SendMacAddressReliably() {
void BluetoothProvisioning::ResetMacSendingState() {
mac_address_sent_ = false;
ble_mac_sent_ = false;
ESP_LOGI(TAG, "MAC地址发送状态已重置");
}
// ============================================================
// SendBleMacAddress — 通过 GATT NOTIFY 发送蓝牙MAC地址
// 在客户端启用NOTIFY后立即调用确保iOS/Android都能获取BLE MAC
// ============================================================
bool BluetoothProvisioning::SendBleMacAddress() {
if (!client_connected_ || !notify_enabled_) {
ESP_LOGW(TAG, "无法发送BLE MAC: connected=%d, notify=%d",
client_connected_, notify_enabled_);
return false;
}
if (ble_mac_sent_) {
ESP_LOGI(TAG, "BLE MAC已发送过跳过");
return true;
}
const uint8_t* ble_addr = esp_bt_dev_get_address();
if (!ble_addr) {
ESP_LOGE(TAG, "获取BLE MAC地址失败");
return false;
}
// 构建数据包: 0x84 + "BLE_MAC:xx:xx:xx:xx:xx:xx"
char mac_data[32];
snprintf(mac_data, sizeof(mac_data), "BLE_MAC:%02x:%02x:%02x:%02x:%02x:%02x",
ble_addr[0], ble_addr[1], ble_addr[2],
ble_addr[3], ble_addr[4], ble_addr[5]);
uint8_t buf[1 + 32];
buf[0] = PROV_RESP_CUSTOM_DATA;
uint8_t data_len = strlen(mac_data);
memcpy(&buf[1], mac_data, data_len);
if (SendNotify(buf, 1 + data_len)) {
ble_mac_sent_ = true;
ESP_LOGI(TAG, "✅ BLE MAC地址发送成功: %s", mac_data);
return true;
}
ESP_LOGW(TAG, "❌ BLE MAC地址发送失败");
return false;
}
// ============================================================
// 状态管理
// ============================================================

View File

@ -12,9 +12,6 @@
#include <functional>
#include <string>
// 蓝牙设备名称 广播名称 宏定义自动引用SDK配置可打开SDK修改蓝牙名称
#define BLU_NAME CONFIG_BLUETOOTH_PROVISIONING_DEVICE_NAME
// 使用条件编译避免IDE环境中的头文件错误
#ifdef ESP_PLATFORM
#include "esp_gap_ble_api.h"
@ -114,7 +111,7 @@ public:
bool Initialize();
bool Deinitialize();
bool StartProvisioning(const char* device_name = BLU_NAME);
bool StartProvisioning();
bool StopProvisioning();
BluetoothProvisioningState GetState() const { return state_; }
@ -126,7 +123,6 @@ public:
void ReportWiFiStatus(bool success, uint8_t reason = 0);
void SendWiFiList(const wifi_ap_record_t* ap_list, uint16_t ap_count);
bool SendMacAddressReliably();
bool SendBleMacAddress();
void ResetMacSendingState();
private:
@ -138,7 +134,6 @@ private:
bool delayed_disconnect_;
bool wifi_connecting_;
bool mac_address_sent_;
bool ble_mac_sent_;
static BluetoothProvisioning* instance_;

View File

@ -157,9 +157,8 @@ void bluetooth_provisioning_task(void* pvParameters) {
return;
}
// 4. 启动配网服务
const char* device_name = BLU_NAME;
if (!g_bt_provisioning->StartProvisioning(device_name)) {
// 4. 启动配网服务 (设备名自动构建: Airhub_ + BLE MAC)
if (!g_bt_provisioning->StartProvisioning()) {
ESP_LOGE(TAG, "蓝牙配网启动失败");
g_bt_provisioning->Deinitialize();
delete g_bt_provisioning;

View File

@ -370,15 +370,13 @@ bool WifiBoard::StartBleProvisioning() {
OnBleProvisioningEvent(event, data);
});
// 使用设备名称启动BLE配网服务2.设备发现,设备名称 Airhub777
std::string device_name = BLU_NAME;
// 蓝牙配网服务启动失败StartProvisioning为蓝牙服务启动函数
if (!bluetooth_provisioning_.StartProvisioning(device_name.c_str())) {
// 启动BLE配网服务设备名称由 StartProvisioning 内部构建: Airhub_ + BLE MAC
if (!bluetooth_provisioning_.StartProvisioning()) {
ESP_LOGE(TAG, "❌ BLE蓝牙配网启动失败");
return false;
}
ESP_LOGI(TAG, "✅ BLE蓝牙配网启动成功,设备名称: %s", device_name.c_str());
ESP_LOGI(TAG, "✅ BLE蓝牙配网启动成功");
ESP_LOGI(TAG, "📱 请使用支持BLE的手机APP连接设备进行配网");
ble_provisioning_active_ = true; // 标记BLE配网服务已激活
@ -388,18 +386,16 @@ bool WifiBoard::StartBleProvisioning() {
// 显示BLE配网通知
auto display = GetDisplay();
if (display) {
std::string notification = "BLE配网模式\n设备名: " + device_name;
display->ShowNotification(notification.c_str(), 30000);
display->ShowNotification("BLE配网模式", 30000);
}
// Play BLE provisioning sound
// 播放配网提示音
auto& application = Application::GetInstance();
// application.Alert("BLE配网模式", ("请使用手机APP连接设备: " + device_name).c_str(), "", Lang::Sounds::P3_WIFICONFIG); 原有蜡笔小新音色
if(strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0){
application.Alert("BLE配网模式", ("请使用手机APP连接设备: " + device_name).c_str(), "", Lang::Sounds::P3_KAKA_WIFICONFIG);
application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_KAKA_WIFICONFIG);
}
else if(strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0){
application.Alert("BLE配网模式", ("请使用手机APP连接设备: " + device_name).c_str(), "", Lang::Sounds::P3_LALA_WIFICONFIG);
application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_LALA_WIFICONFIG);
}
@ -433,14 +429,13 @@ bool WifiBoard::StartBleJsonProvisioning() {
Application::GetInstance().HandleBleJsonCommand(cmd, msg_id, data, ble_json_service_);
});
// 使用与 BLE 相同的设备名启动
std::string device_name = BLU_NAME;
if (!ble_json_service_.Start(device_name.c_str())) {
// 启动 BLE JSON 服务
if (!ble_json_service_.Start("Airhub_Ble")) {
ESP_LOGE(TAG, "❌ BLE JSON服务启动失败");
return false;
}
ESP_LOGI(TAG, "✅ BLE JSON配网启动成功,设备名称: %s", device_name.c_str());
ESP_LOGI(TAG, "✅ BLE JSON配网启动成功");
ble_provisioning_active_ = true;
ble_start_time_ = xTaskGetTickCount();
@ -448,16 +443,15 @@ bool WifiBoard::StartBleJsonProvisioning() {
// 显示配网通知
auto display = GetDisplay();
if (display) {
std::string notification = "BLE配网模式\n设备名: " + device_name;
display->ShowNotification(notification.c_str(), 30000);
display->ShowNotification("BLE配网模式", 30000);
}
// 播放配网提示音
auto& application = Application::GetInstance();
if (strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0) {
application.Alert("BLE配网模式", ("请使用手机APP连接设备: " + device_name).c_str(), "", Lang::Sounds::P3_KAKA_WIFICONFIG);
application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_KAKA_WIFICONFIG);
} else if (strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0) {
application.Alert("BLE配网模式", ("请使用手机APP连接设备: " + device_name).c_str(), "", Lang::Sounds::P3_LALA_WIFICONFIG);
application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_LALA_WIFICONFIG);
}
// 配网状态等待循环