606 lines
23 KiB
C++
606 lines
23 KiB
C++
/**
|
||
* @file wifi_board.cc
|
||
* @brief WiFi板级管理模块实现文件
|
||
*
|
||
* 本文件实现了WiFi板级管理的相关功能,包括WiFi连接管理、
|
||
* BLE蓝牙配网流程控制、网络状态监控等核心功能。
|
||
* 提供完整的网络连接解决方案实现。
|
||
*/
|
||
|
||
#include "wifi_board.h"
|
||
|
||
#include "display.h"
|
||
#include "application.h"
|
||
#include "system_info.h"
|
||
#include "font_awesome_symbols.h"
|
||
#include "settings.h"
|
||
#include "assets/lang_config.h"
|
||
#include "bluetooth_provisioning.h"
|
||
#include "esp_bt.h"
|
||
#include "esp_bt_main.h"
|
||
#include "esp_netif_sntp.h"
|
||
|
||
#include <freertos/FreeRTOS.h>
|
||
#include <freertos/task.h>
|
||
#include <esp_http.h>
|
||
#include <esp_mqtt.h>
|
||
#include <esp_udp.h>
|
||
#include <tcp_transport.h>
|
||
#include <tls_transport.h>
|
||
#include <web_socket.h>
|
||
#include <esp_log.h>
|
||
|
||
#include <wifi_station.h>
|
||
#include <wifi_configuration_ap.h>
|
||
#include <ssid_manager.h>
|
||
|
||
static const char *TAG = "WifiBoard"; ///< 日志标签,用于标识WiFi板级模块的日志输出
|
||
|
||
/**
|
||
* @brief WiFi板级管理构造函数
|
||
*
|
||
* 初始化WiFi板级管理对象,读取NVS存储中的配置参数。
|
||
* 检查是否设置了强制AP模式标志,如果设置则重置为0。
|
||
*/
|
||
WifiBoard::WifiBoard() {
|
||
// 读取NVS存储中的强制AP模式标志
|
||
Settings settings("wifi", true);
|
||
wifi_config_mode_ = settings.GetInt("force_ap") == 1;
|
||
|
||
// 如果检测到强制AP模式,重置为0并记录日志
|
||
if (wifi_config_mode_) {
|
||
ESP_LOGI(TAG, "force_ap is set to 1, reset to 0");
|
||
settings.SetInt("force_ap", 0);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 获取板级类型标识
|
||
* @return std::string 返回"wifi"字符串,标识当前为WiFi板级
|
||
*/
|
||
std::string WifiBoard::GetBoardType() {
|
||
return "wifi";
|
||
}
|
||
|
||
/**
|
||
* @brief 进入WiFi配置模式
|
||
*
|
||
* 启动BLE蓝牙配网流程,等待用户通过手机APP配置WiFi信息。
|
||
* 如果BLE配网启动失败,会持续重试直到成功。
|
||
* 不再使用传统的WiFi AP配网模式。
|
||
*/
|
||
void WifiBoard::EnterWifiConfigMode() {
|
||
ESP_LOGI(TAG, "🔵 进入配网模式 - 使用BLE蓝牙配网");
|
||
|
||
// 使用 BLE 蓝牙配网
|
||
bool success = StartBleProvisioning();
|
||
ESP_LOGI(TAG, "🔍 BLE配网启动结果: %s", success ? "成功" : "失败");
|
||
|
||
if (success) {
|
||
ESP_LOGI(TAG, "✅ BLE配网启动成功,等待手机连接");
|
||
return;
|
||
}
|
||
|
||
ESP_LOGW(TAG, "⚠️ BLE配网启动失败,将持续重试");
|
||
|
||
// 持续重试
|
||
while (true) {
|
||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||
ESP_LOGI(TAG, "🔄 重试启动BLE配网...");
|
||
if (StartBleProvisioning()) {
|
||
ESP_LOGI(TAG, "✅ BLE配网重试成功,等待手机连接");
|
||
return;
|
||
}
|
||
ESP_LOGW(TAG, "❌ BLE配网重试失败,继续重试...");
|
||
}
|
||
|
||
// 以下代码保留但不会执行,用于将来可能重新启用WiFi AP配网
|
||
//ESP_LOGI(TAG, "📶 启动WiFi AP配网模式,播放配网提示音(此代码已被禁用)");
|
||
|
||
auto& application = Application::GetInstance();
|
||
application.SetDeviceState(kDeviceStateWifiConfiguring);
|
||
|
||
auto& wifi_ap = WifiConfigurationAp::GetInstance();
|
||
wifi_ap.SetLanguage(Lang::CODE);
|
||
wifi_ap.SetSsidPrefix("Airhub");
|
||
wifi_ap.Start(); // 初始化AP模式射频
|
||
|
||
// 显示 WiFi 配置 AP 的 SSID 和 Web 服务器 URL
|
||
std::string hint = Lang::Strings::CONNECT_TO_HOTSPOT;
|
||
hint += wifi_ap.GetSsid();
|
||
hint += Lang::Strings::ACCESS_VIA_BROWSER;
|
||
hint += wifi_ap.GetWebServerUrl();
|
||
hint += "\n\n";
|
||
// 播报配置 WiFi 的提示
|
||
// application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "", Lang::Sounds::P3_WIFICONFIG); 原有蜡笔小新音色播报
|
||
if(strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0){
|
||
application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "", Lang::Sounds::P3_KAKA_WIFICONFIG);
|
||
}
|
||
else if(strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0){
|
||
application.Alert(Lang::Strings::WIFI_CONFIG_MODE, hint.c_str(), "", Lang::Sounds::P3_LALA_WIFICONFIG);
|
||
}
|
||
|
||
|
||
|
||
// Wait forever until reset after configuration
|
||
while (true) {
|
||
int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||
int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
|
||
ESP_LOGI(TAG, "Free internal: %u minimal internal: %u", free_sram, min_free_sram);
|
||
vTaskDelay(pdMS_TO_TICKS(10000));
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 启动网络连接
|
||
*
|
||
* 根据配置启动WiFi连接或BLE配网流程。
|
||
* 如果设置了配网模式或没有WiFi凭据,则启动BLE配网;
|
||
* 否则尝试连接已保存的WiFi网络。
|
||
*/
|
||
void WifiBoard::StartNetwork() {
|
||
// 用户可以在启动时按BOOT按钮进入WiFi配置模式
|
||
// 开机按BOOT进入配网模式
|
||
if (wifi_config_mode_) {
|
||
ESP_LOGI(TAG, "🔵 进入配网模式 - BLE蓝牙配网");
|
||
EnterWifiConfigMode();
|
||
return;
|
||
}
|
||
|
||
// 如果没有配置WiFi SSID,优先尝试BLE配网
|
||
auto& ssid_manager = SsidManager::GetInstance(); // 获取SSID管理器实例
|
||
auto ssid_list = ssid_manager.GetSsidList(); // 获取SSID列表
|
||
if (ssid_list.empty()) {
|
||
ESP_LOGI(TAG, "🔍 未找到WiFi凭据,启动BLE配网...");
|
||
if (StartBleProvisioning()) {
|
||
ESP_LOGI(TAG, "✅ BLE配网启动成功,等待手机连接...");
|
||
return;
|
||
} else {
|
||
ESP_LOGW(TAG, "❌ BLE配网启动失败,将重试");
|
||
vTaskDelay(pdMS_TO_TICKS(5000));
|
||
ESP_LOGI(TAG, "🔄 重试启动BLE配网...");
|
||
StartBleProvisioning();
|
||
return;
|
||
}
|
||
}
|
||
|
||
// WiFi凭据存在,尝试直接连接
|
||
auto& wifi_station = WifiStation::GetInstance();
|
||
|
||
// 设置WiFi扫描开始回调
|
||
wifi_station.OnScanBegin([this]() {
|
||
auto display = Board::GetInstance().GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification(Lang::Strings::SCANNING_WIFI, 30000);
|
||
}
|
||
});
|
||
|
||
// 设置WiFi连接开始回调
|
||
wifi_station.OnConnect([this](const std::string& ssid) {
|
||
auto display = Board::GetInstance().GetDisplay();
|
||
if (display) {
|
||
std::string notification = Lang::Strings::CONNECT_TO;
|
||
notification += ssid;
|
||
notification += "...";
|
||
display->ShowNotification(notification.c_str(), 30000);
|
||
}
|
||
|
||
// 根据标志决定是否播放网络连接语音提示
|
||
auto& application = Application::GetInstance();
|
||
if (!application.ShouldSkipDialogIdleSession()) {
|
||
// application.PlaySound(Lang::Sounds::P3_LIANJIEWANGLUO); 原有蜡笔小新 音色播报
|
||
if(strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0){
|
||
application.PlaySound(Lang::Sounds::P3_KAKA_LIANJIEWANGLUO);
|
||
}
|
||
else if(strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0){
|
||
application.PlaySound(Lang::Sounds::P3_LALA_LIANJIEWANGLUO);
|
||
}
|
||
ESP_LOGI(TAG, "Starting WiFi connection, playing network connection sound");
|
||
} else {
|
||
ESP_LOGI(TAG, "Skipping network connection sound due to dialog idle restart flag");
|
||
// 清除跳过标志,确保后续正常使用时能播放播报
|
||
application.ClearDialogIdleSkipSession();
|
||
}
|
||
});
|
||
|
||
// 设置WiFi连接成功回调
|
||
wifi_station.OnConnected([this](const std::string& ssid) {
|
||
auto display = Board::GetInstance().GetDisplay();
|
||
if (display) {
|
||
std::string notification = Lang::Strings::CONNECTED_TO;
|
||
notification += ssid;
|
||
display->ShowNotification(notification.c_str(), 30000);
|
||
}
|
||
});
|
||
|
||
wifi_station.OnReconnectTimeout([this]() {
|
||
auto& ws = WifiStation::GetInstance();
|
||
ws.Stop();
|
||
esp_wifi_restore();
|
||
ResetWifiConfiguration();
|
||
});
|
||
|
||
// 启动WiFi站点模式
|
||
wifi_station.Start();
|
||
|
||
// 尝试连接WiFi,如果失败则尝试BLE配网
|
||
// 尝试连接WiFi,如果失败则尝试BLE配网
|
||
// 增加WiFi连接超时时间,避免过快进入配网模式
|
||
// if (!wifi_station.WaitForConnected(90 * 1000)) {
|
||
if (!wifi_station.WaitForConnected(10 * 1000)) {
|
||
wifi_station.Stop();// 停止WiFi连接尝试
|
||
esp_wifi_restore();// 恢复WiFi默认配置
|
||
ResetWifiConfiguration();// 重置WiFi配置
|
||
return;
|
||
} else {
|
||
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
|
||
esp_netif_sntp_init(&config);
|
||
int retry = 0;
|
||
while (esp_netif_sntp_sync_wait(1000 / portTICK_PERIOD_MS) == ESP_ERR_TIMEOUT && ++retry < 5) {}
|
||
setenv("TZ", "CST-8", 1);
|
||
tzset();
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 创建HTTP客户端对象
|
||
* @return Http* 返回ESP HTTP客户端对象指针
|
||
*/
|
||
Http* WifiBoard::CreateHttp() {
|
||
return new EspHttp();
|
||
}
|
||
|
||
/**
|
||
* @brief 创建WebSocket客户端对象
|
||
* @return WebSocket* 返回WebSocket客户端对象指针,如果未配置则返回nullptr
|
||
*
|
||
* 根据配置的WebSocket URL选择使用TLS或TCP传输协议
|
||
*/
|
||
WebSocket* WifiBoard::CreateWebSocket() {
|
||
#ifdef CONFIG_CONNECTION_TYPE_WEBSOCKET
|
||
std::string url = CONFIG_WEBSOCKET_URL;
|
||
if (url.find("wss://") == 0) {
|
||
return new WebSocket(new TlsTransport()); // 使用TLS安全传输
|
||
} else {
|
||
return new WebSocket(new TcpTransport()); // 使用TCP传输
|
||
}
|
||
#endif
|
||
return nullptr;
|
||
}
|
||
|
||
/**
|
||
* @brief 创建MQTT客户端对象
|
||
* @return Mqtt* 返回ESP MQTT客户端对象指针
|
||
*/
|
||
Mqtt* WifiBoard::CreateMqtt() {
|
||
return new EspMqtt();
|
||
}
|
||
|
||
Udp* WifiBoard::CreateUdp() {
|
||
return new EspUdp();
|
||
}
|
||
|
||
// 获取网络状态图标
|
||
const char* WifiBoard::GetNetworkStateIcon() {
|
||
if (wifi_config_mode_) {// 如果是配网模式
|
||
return FONT_AWESOME_WIFI;// 返回WiFi图标
|
||
}
|
||
auto& wifi_station = WifiStation::GetInstance();// 获取WiFi配置实例
|
||
if (!wifi_station.IsConnected()) {// 如果未连接到WiFi
|
||
return FONT_AWESOME_WIFI_OFF;// 返回WiFi断开图标
|
||
}
|
||
int8_t rssi = wifi_station.GetRssi();// 获取WiFi信号强度
|
||
if (rssi >= -60) { // 信号强度大于等于-60dBm
|
||
return FONT_AWESOME_WIFI;// 返回WiFi图标
|
||
} else if (rssi >= -70) {
|
||
return FONT_AWESOME_WIFI_FAIR;// 返回WiFi信号中等图标
|
||
} else {
|
||
return FONT_AWESOME_WIFI_WEAK;// 返回WiFi信号弱图标
|
||
}
|
||
}
|
||
|
||
// 获取板级JSON配置
|
||
std::string WifiBoard::GetBoardJson() {
|
||
// Set the board type for OTA
|
||
auto& wifi_station = WifiStation::GetInstance();
|
||
std::string board_json = std::string("{\"type\":\"" BOARD_TYPE "\",");// 板级JSON配置字符串,包含设备类型、名称、角色、SSID、信号强度、通道、IP地址和MAC地址
|
||
board_json += "\"name\":\"" BOARD_NAME "\",";
|
||
board_json += "\"role\":\"" CONFIG_DEVICE_ROLE "\","; // 添加设备角色字段,用于OTA升级时的角色匹配
|
||
if (!wifi_config_mode_) {
|
||
board_json += "\"ssid\":\"" + wifi_station.GetSsid() + "\",";
|
||
board_json += "\"rssi\":" + std::to_string(wifi_station.GetRssi()) + ",";
|
||
board_json += "\"channel\":" + std::to_string(wifi_station.GetChannel()) + ",";
|
||
board_json += "\"ip\":\"" + wifi_station.GetIpAddress() + "\",";
|
||
}
|
||
board_json += "\"mac\":\"" + SystemInfo::GetMacAddress() + "\"}";
|
||
return board_json;
|
||
}
|
||
|
||
// 设置低功耗模式 新增配网模式下禁用省电模式
|
||
void WifiBoard::SetPowerSaveMode(bool enabled) {
|
||
// 如果正在进行 BLE 配网,强制禁用省电模式以确保 MAC 地址能正常发送到手机端
|
||
if (enabled && IsBleProvisioningActive()) {
|
||
ESP_LOGI(TAG, "🔵 配网模式下,已强制禁用省电模式!");
|
||
enabled = false;
|
||
}
|
||
ESP_LOGI(TAG, "🔋 电源管理模式切换: %s", enabled ? "启用低功耗模式" : "禁用低功耗模式(恢复正常模式)");
|
||
|
||
auto& wifi_station = WifiStation::GetInstance();
|
||
wifi_station.SetPowerSaveMode(enabled);
|
||
}
|
||
|
||
// 重置WiFi配置,设备将重启进入配网模式
|
||
void WifiBoard::ResetWifiConfiguration() {
|
||
ESP_LOGI(TAG, "🔄 重置WiFi配置,设备将重启进入配网模式");
|
||
// 设置WiFi配网标志位,确保重启后能正确进入配网模式
|
||
{
|
||
Settings settings("wifi", true);// 创建WiFi配置设置对象,第二个参数true表示立即保存到NVS存储
|
||
settings.SetInt("force_ap", 1);// 设置force_ap标志为1,这个标志会在设备重启后被检查,如果为1则启动WiFi配网服务,启动时强制进入AP配网模式
|
||
}
|
||
|
||
// 获取显示设备对象并显示配网提示信息
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
// 在屏幕上显示"进入WiFi配置模式"的多语言提示信息
|
||
// 让用户知道设备即将重启并进入配网模式
|
||
display->ShowNotification(Lang::Strings::ENTERING_WIFI_CONFIG_MODE);
|
||
}
|
||
vTaskDelay(pdMS_TO_TICKS(500)); // 等待500ms,确保NVS配置保存完成,如果有屏幕显示,可以增加到1000ms让用户看清提示
|
||
ESP_LOGI(TAG, "🔄 正在重启设备...");
|
||
esp_restart(); // 重启设备,重启后会进入配网模式
|
||
}
|
||
|
||
// 启动BLE配网服务
|
||
bool WifiBoard::StartBleProvisioning() {
|
||
ESP_LOGI(TAG, "🔵 正在启动BLE蓝牙配网服务...");
|
||
|
||
Application::GetInstance().StopAudioProcessor();// 停止音频处理器,确保在配网过程中不处理音频数据
|
||
Application::GetInstance().ClearAudioQueue();// 清空音频队列,移除所有待处理的音频数据
|
||
|
||
// 初始化BLE配网服务
|
||
if (!bluetooth_provisioning_.Initialize()) {
|
||
ESP_LOGE(TAG, "❌ BLE蓝牙配网初始化失败");
|
||
ESP_LOGI(TAG, "🔍 BLE Initialize返回结果: false");
|
||
return false;
|
||
}
|
||
ESP_LOGI(TAG, "🔍 BLE Initialize返回结果: true");
|
||
|
||
// 为BLE事件设置回调函数
|
||
bluetooth_provisioning_.SetCallback([this](BluetoothProvisioningEvent event, void* data) {
|
||
OnBleProvisioningEvent(event, data);
|
||
});
|
||
|
||
// 启动BLE配网服务(设备名称由 StartProvisioning 内部构建: Airhub_ + BLE MAC)
|
||
if (!bluetooth_provisioning_.StartProvisioning()) {
|
||
ESP_LOGE(TAG, "❌ BLE蓝牙配网启动失败");
|
||
return false;
|
||
}
|
||
|
||
ESP_LOGI(TAG, "✅ BLE蓝牙配网启动成功");
|
||
ESP_LOGI(TAG, "📱 请使用支持BLE的手机APP连接设备进行配网");
|
||
|
||
ble_provisioning_active_ = true; // 标记BLE配网服务已激活
|
||
ble_provisioning_success_ = false;// 标记BLE配网服务未成功
|
||
ble_start_time_ = xTaskGetTickCount();// 记录启动时间,用于超时检测
|
||
|
||
// 显示BLE配网通知
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("BLE配网模式", 30000);
|
||
}
|
||
|
||
// 播放配网提示音
|
||
auto& application = Application::GetInstance();
|
||
if(strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0){
|
||
application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_KAKA_WIFICONFIG);
|
||
}
|
||
else if(strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0){
|
||
application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_LALA_WIFICONFIG);
|
||
}
|
||
|
||
|
||
|
||
// 创建任务,用于监控BLE配网状态
|
||
xTaskCreate([](void* param) {
|
||
WifiBoard* board = static_cast<WifiBoard*>(param); // 转换参数为WifiBoard指针
|
||
board->MonitorBleProvisioning();// 监控BLE配网状态
|
||
vTaskDelete(nullptr);// 删除任务,因为任务只执行一次
|
||
}, "ble_prov_monitor", 4096, this, 5, nullptr);// 创建任务,优先级为5,栈大小为4096字节
|
||
|
||
return true;// 启动成功,返回true
|
||
}
|
||
|
||
// // BLE JSON Service 配网(暂不使用,保留代码)
|
||
// bool WifiBoard::StartBleJsonProvisioning() {
|
||
// ESP_LOGI(TAG, "🔵 正在启动BLE JSON配网服务...");
|
||
// Application::GetInstance().StopAudioProcessor();
|
||
// Application::GetInstance().ClearAudioQueue();
|
||
// if (!ble_json_service_.Initialize()) {
|
||
// ESP_LOGE(TAG, "❌ BLE JSON服务初始化失败");
|
||
// return false;
|
||
// }
|
||
// ble_json_service_.SetCommandCallback(
|
||
// [this](const std::string& cmd, int msg_id, cJSON* data) {
|
||
// Application::GetInstance().HandleBleJsonCommand(cmd, msg_id, data, ble_json_service_);
|
||
// });
|
||
// if (!ble_json_service_.Start("Airhub_Ble")) {
|
||
// ESP_LOGE(TAG, "❌ BLE JSON服务启动失败");
|
||
// return false;
|
||
// }
|
||
// ESP_LOGI(TAG, "✅ BLE JSON配网启动成功");
|
||
// ble_provisioning_active_ = true;
|
||
// ble_start_time_ = xTaskGetTickCount();
|
||
// auto display = GetDisplay();
|
||
// if (display) {
|
||
// display->ShowNotification("BLE配网模式", 30000);
|
||
// }
|
||
// auto& application = Application::GetInstance();
|
||
// if (strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0) {
|
||
// application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_KAKA_WIFICONFIG);
|
||
// } else if (strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0) {
|
||
// application.Alert("BLE配网模式", "请使用手机APP搜索Airhub_开头的蓝牙设备", "", Lang::Sounds::P3_LALA_WIFICONFIG);
|
||
// }
|
||
// while (true) {
|
||
// int free_sram = heap_caps_get_free_size(MALLOC_CAP_INTERNAL);
|
||
// int min_free_sram = heap_caps_get_minimum_free_size(MALLOC_CAP_INTERNAL);
|
||
// ESP_LOGI(TAG, "BLE配网等待中... Free internal: %u minimal internal: %u", free_sram, min_free_sram);
|
||
// vTaskDelay(pdMS_TO_TICKS(10000));
|
||
// }
|
||
// return true;
|
||
// }
|
||
|
||
// 监控BLE配网状态
|
||
void WifiBoard::MonitorBleProvisioning() {
|
||
ESP_LOGI(TAG, "Starting BLE provisioning monitor...");
|
||
|
||
while (ble_provisioning_active_) {
|
||
TickType_t current_time = xTaskGetTickCount();
|
||
TickType_t elapsed_time = current_time - ble_start_time_;
|
||
|
||
// Check for timeout (2 minutes) - 仅记录日志,不再切换到WiFi配网
|
||
if (elapsed_time >= pdMS_TO_TICKS(BLE_PROV_TIMEOUT_MS)) {
|
||
ESP_LOGW(TAG, "BLE provisioning timeout, but continuing BLE mode (no fallback to WiFi AP)");
|
||
|
||
// 增加延迟避免快速重新进入配网循环
|
||
ESP_LOGI(TAG, "🔵 BLE配网超时,等待10秒后重置计时器继续等待配网");
|
||
vTaskDelay(pdMS_TO_TICKS(10000)); // 等待10秒,冷却期
|
||
|
||
// 重置计时器,继续等待BLE配网
|
||
ble_start_time_ = xTaskGetTickCount();
|
||
ESP_LOGI(TAG, "🔵 计时器已重置,继续等待BLE配网");
|
||
}
|
||
|
||
// Check if provisioning was successful
|
||
if (ble_provisioning_success_) {
|
||
ESP_LOGI(TAG, "BLE provisioning completed successfully");
|
||
ble_provisioning_active_ = false;
|
||
|
||
// Stop BLE provisioning
|
||
// 停止BLE配网
|
||
bluetooth_provisioning_.StopProvisioning();
|
||
|
||
// Try to connect to the configured WiFi
|
||
auto& wifi_station = WifiStation::GetInstance();
|
||
wifi_station.Start();
|
||
|
||
// 增加WiFi连接重试逻辑,避免过快重新进入配网模式
|
||
int retry_count = 0; // 重试次数
|
||
const int max_retries = 3; // 最大重试次数
|
||
const int retry_timeout = 60 * 1000; // 60秒超时
|
||
|
||
// 重试连接WiFi
|
||
while (retry_count < max_retries) {
|
||
ESP_LOGI(TAG, "WiFi connection attempt %d/%d after BLE provisioning", retry_count + 1, max_retries);
|
||
|
||
// 等待WiFi连接成功
|
||
if (wifi_station.WaitForConnected(retry_timeout)) {
|
||
ESP_LOGI(TAG, "WiFi connection successful after BLE provisioning (attempt %d)", retry_count + 1);
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("WiFi连接成功", 5000);
|
||
}
|
||
return;
|
||
}
|
||
|
||
retry_count++;// 增加重试次数
|
||
if (retry_count < max_retries) {
|
||
ESP_LOGW(TAG, "WiFi connection failed (attempt %d/%d), retrying in 10 seconds...", retry_count, max_retries);
|
||
vTaskDelay(pdMS_TO_TICKS(10000)); // 等待10秒后重试
|
||
wifi_station.Stop();
|
||
vTaskDelay(pdMS_TO_TICKS(2000)); // 等待2秒确保完全停止
|
||
wifi_station.Start(); // 重新启动WiFi连接
|
||
} else {
|
||
ESP_LOGW(TAG, "WiFi connection failed after %d attempts, entering AP mode", max_retries);
|
||
wifi_station.Stop();
|
||
wifi_config_mode_ = true;
|
||
EnterWifiConfigMode();
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
|
||
// Wait before next check
|
||
vTaskDelay(pdMS_TO_TICKS(1000)); // 等待1秒后检查
|
||
}
|
||
}
|
||
|
||
// 处理BLE配网事件
|
||
void WifiBoard::OnBleProvisioningEvent(BluetoothProvisioningEvent event, void* data) {
|
||
switch (event) {
|
||
case BluetoothProvisioningEvent::CLIENT_CONNECTED:
|
||
ESP_LOGI(TAG, "BLE client connected");
|
||
{
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("客户端已连接", 5000);
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 客户端断开事件
|
||
case BluetoothProvisioningEvent::CLIENT_DISCONNECTED:
|
||
ESP_LOGI(TAG, "BLE client disconnected");
|
||
{
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("客户端已断开", 5000);
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 接收WiFi凭据事件
|
||
case BluetoothProvisioningEvent::WIFI_CREDENTIALS:
|
||
ESP_LOGI(TAG, "WiFi credentials received via BLE");
|
||
{
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("WiFi凭据已接收", 5000);
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 连接成功事件
|
||
case BluetoothProvisioningEvent::WIFI_CONNECTED:
|
||
ESP_LOGI(TAG, "设备配网成功,已连接到WiFi网络!");
|
||
ble_provisioning_success_ = true;
|
||
{
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("WiFi连接成功", 5000);
|
||
}
|
||
auto& application = Application::GetInstance();
|
||
// application.PlaySound(Lang::Sounds::P3_LIANJIEWANGLUO); 原有蜡笔小新 音色播报
|
||
if(strcmp(CONFIG_DEVICE_ROLE, "KAKA") == 0){
|
||
application.PlaySound(Lang::Sounds::P3_KAKA_LIANJIEWANGLUO);
|
||
}
|
||
else if(strcmp(CONFIG_DEVICE_ROLE, "RTC_Test") == 0){
|
||
application.PlaySound(Lang::Sounds::P3_LALA_LIANJIEWANGLUO);
|
||
}
|
||
}
|
||
break;
|
||
|
||
// 连接失败事件
|
||
case BluetoothProvisioningEvent::WIFI_FAILED:
|
||
ESP_LOGW(TAG, "WiFi connection failed via BLE");
|
||
ble_provisioning_active_ = false;
|
||
{
|
||
auto display = GetDisplay();
|
||
if (display) {
|
||
display->ShowNotification("WiFi连接失败", 5000);
|
||
}
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
// BLE配网回调函数
|
||
void WifiBoard::BleProvisioningCallback(BluetoothProvisioningEvent event, void* data, void* user_data) {
|
||
WifiBoard* board = static_cast<WifiBoard*>(user_data);
|
||
if (board) {
|
||
board->OnBleProvisioningEvent(event, data);
|
||
}
|
||
}
|