572 lines
18 KiB
C++
572 lines
18 KiB
C++
|
|
#include "wifi_manager.h"
|
|||
|
|
|
|||
|
|
// 外部变量和函数声明
|
|||
|
|
extern bool deviceConnected;
|
|||
|
|
void sendJSONDataToBLE(const String& jsonData);
|
|||
|
|
void setNetworkStatus(NetworkStatus status);
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief WiFi管理器构造函数
|
|||
|
|
* 初始化WiFi管理器的成员变量
|
|||
|
|
*/
|
|||
|
|
WiFiManager::WiFiManager() {
|
|||
|
|
savedNetworkCount = 0;
|
|||
|
|
currentState = WIFI_IDLE;
|
|||
|
|
lastReconnectAttempt = 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 初始化WiFi管理器
|
|||
|
|
* 开启Preferences存储,并加载保存的WiFi配置
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::begin() {
|
|||
|
|
preferences.begin("wifi_manager", false);
|
|||
|
|
loadWiFiConfigs();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 加载保存的WiFi配置
|
|||
|
|
* 从Flash中读取之前保存的WiFi网络配置
|
|||
|
|
* @return 是否成功加载到配置
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::loadWiFiConfigs() {
|
|||
|
|
savedNetworkCount = 0;
|
|||
|
|
|
|||
|
|
for (int i = 0; i < MAX_WIFI_NETWORKS; i++) {
|
|||
|
|
String key = "wifi_" + String(i);
|
|||
|
|
String configStr = preferences.getString(key.c_str(), "");
|
|||
|
|
|
|||
|
|
if (configStr.length() > 0) {
|
|||
|
|
JsonDocument doc;
|
|||
|
|
DeserializationError error = deserializeJson(doc, configStr);
|
|||
|
|
|
|||
|
|
if (!error) {
|
|||
|
|
const char* ssid = doc["ssid"];
|
|||
|
|
const char* password = doc["password"];
|
|||
|
|
|
|||
|
|
if (ssid && password) {
|
|||
|
|
strncpy(savedNetworks[savedNetworkCount].ssid, ssid, 31);
|
|||
|
|
savedNetworks[savedNetworkCount].ssid[31] = '\0';
|
|||
|
|
strncpy(savedNetworks[savedNetworkCount].password, password, 63);
|
|||
|
|
savedNetworks[savedNetworkCount].password[63] = '\0';
|
|||
|
|
savedNetworkCount++;
|
|||
|
|
|
|||
|
|
Serial.printf("📶 加载WiFi配置 %d: %s\n", savedNetworkCount, ssid);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Serial.printf("✅ 共加载 %d 个WiFi配置\n", savedNetworkCount);
|
|||
|
|
return savedNetworkCount > 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 保存WiFi配置
|
|||
|
|
* 将WiFi网络配置保存到Flash中
|
|||
|
|
* @param ssid WiFi网络名称
|
|||
|
|
* @param password WiFi网络密码
|
|||
|
|
* @return 是否保存成功
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::saveWiFiConfig(const char* ssid, const char* password) {
|
|||
|
|
// 检查是否已存在该网络配置
|
|||
|
|
for (int i = 0; i < savedNetworkCount; i++) {
|
|||
|
|
if (strcmp(savedNetworks[i].ssid, ssid) == 0) {
|
|||
|
|
// 更新现有配置
|
|||
|
|
strncpy(savedNetworks[i].password, password, 63);
|
|||
|
|
savedNetworks[i].password[63] = '\0';
|
|||
|
|
|
|||
|
|
JsonDocument doc;
|
|||
|
|
doc["ssid"] = ssid;
|
|||
|
|
doc["password"] = password;
|
|||
|
|
String configStr;
|
|||
|
|
serializeJson(doc, configStr);
|
|||
|
|
|
|||
|
|
String key = "wifi_" + String(i);
|
|||
|
|
preferences.putString(key.c_str(), configStr);
|
|||
|
|
|
|||
|
|
Serial.printf("🔄 更新WiFi配置: %s\n", ssid);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 添加新配置
|
|||
|
|
if (savedNetworkCount < MAX_WIFI_NETWORKS) {
|
|||
|
|
strncpy(savedNetworks[savedNetworkCount].ssid, ssid, 31);
|
|||
|
|
savedNetworks[savedNetworkCount].ssid[31] = '\0';
|
|||
|
|
strncpy(savedNetworks[savedNetworkCount].password, password, 63);
|
|||
|
|
savedNetworks[savedNetworkCount].password[63] = '\0';
|
|||
|
|
|
|||
|
|
JsonDocument doc;
|
|||
|
|
doc["ssid"] = ssid;
|
|||
|
|
doc["password"] = password;
|
|||
|
|
String configStr;
|
|||
|
|
serializeJson(doc, configStr);
|
|||
|
|
|
|||
|
|
String key = "wifi_" + String(savedNetworkCount);
|
|||
|
|
preferences.putString(key.c_str(), configStr);
|
|||
|
|
savedNetworkCount++;
|
|||
|
|
|
|||
|
|
Serial.printf("➕ 新增WiFi配置: %s (总计: %d)\n", ssid, savedNetworkCount);
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Serial.println("❌ WiFi配置已满,无法添加");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 连接到指定WiFi网络
|
|||
|
|
* 尝试连接到给定的WiFi网络
|
|||
|
|
* @param ssid WiFi网络名称
|
|||
|
|
* @param password WiFi网络密码
|
|||
|
|
* @return 是否连接成功
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::connectToNetwork(const char* ssid, const char* password) {
|
|||
|
|
Serial.printf("🌐 [WiFi] 尝试连接到 SSID: %s\n", ssid);
|
|||
|
|
|
|||
|
|
currentState = WIFI_CONNECTING;
|
|||
|
|
setNetworkStatus(NET_CONNECTING);
|
|||
|
|
|
|||
|
|
WiFi.mode(WIFI_STA);
|
|||
|
|
WiFi.begin(ssid, password);
|
|||
|
|
|
|||
|
|
unsigned long startTime = millis();
|
|||
|
|
unsigned long lastStatusPrint = 0;
|
|||
|
|
|
|||
|
|
// 等待连接成功或超时
|
|||
|
|
while (WiFi.status() != WL_CONNECTED && (millis() - startTime) < WIFI_CONNECT_TIMEOUT) {
|
|||
|
|
if (millis() - lastStatusPrint >= 500) {
|
|||
|
|
Serial.printf("[WiFi] 连接中,状态: %d\n", WiFi.status());
|
|||
|
|
lastStatusPrint = millis();
|
|||
|
|
}
|
|||
|
|
yield();
|
|||
|
|
vTaskDelay(50 / portTICK_PERIOD_MS);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|||
|
|
Serial.println("✅ [WiFi] 连接成功!");
|
|||
|
|
Serial.printf("🌐 IP地址: %s\n", WiFi.localIP().toString().c_str());
|
|||
|
|
Serial.printf("🔒 信号强度: %d dBm\n", WiFi.RSSI());
|
|||
|
|
|
|||
|
|
currentState = WIFI_CONNECTED;
|
|||
|
|
setNetworkStatus(NET_CONNECTED);
|
|||
|
|
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
Serial.println("❌ [WiFi] 连接超时");
|
|||
|
|
currentState = WIFI_DISCONNECTED;
|
|||
|
|
setNetworkStatus(NET_DISCONNECTED);
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 扫描并匹配WiFi网络
|
|||
|
|
* 扫描附近的WiFi网络,并尝试匹配已保存的配置
|
|||
|
|
* 如果找到多个匹配的网络,优先连接信号强度最强的那一组
|
|||
|
|
* @return 是否成功连接到匹配的网络
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::scanAndMatchNetworks() {
|
|||
|
|
Serial.println("🔍 [WiFi] 开始扫描WiFi网络...");
|
|||
|
|
currentState = WIFI_SCANNING;
|
|||
|
|
|
|||
|
|
WiFi.disconnect(true);
|
|||
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|||
|
|
WiFi.mode(WIFI_STA);
|
|||
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|||
|
|
|
|||
|
|
int n = WiFi.scanNetworks();
|
|||
|
|
Serial.printf("🔍 扫描到 %d 个WiFi网络\n", n);
|
|||
|
|
|
|||
|
|
if (n <= 0) {
|
|||
|
|
Serial.println("❌ 未扫描到任何WiFi网络或扫描失败");
|
|||
|
|
currentState = WIFI_DISCONNECTED;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 收集所有匹配的、信号强度符合要求的网络
|
|||
|
|
struct {
|
|||
|
|
const char* ssid;
|
|||
|
|
const char* password;
|
|||
|
|
int rssi;
|
|||
|
|
} bestNetwork = {nullptr, nullptr, -1000}; // 初始化为非常弱的信号
|
|||
|
|
|
|||
|
|
// 遍历已保存的网络,寻找匹配的网络
|
|||
|
|
for (int i = 0; i < savedNetworkCount; i++) {
|
|||
|
|
for (int j = 0; j < n; j++) {
|
|||
|
|
if (WiFi.SSID(j) == String(savedNetworks[i].ssid)) {
|
|||
|
|
int rssi = WiFi.RSSI(j);
|
|||
|
|
Serial.printf("📶 找到匹配网络: %s, 信号: %d dBm\n",
|
|||
|
|
savedNetworks[i].ssid, rssi);
|
|||
|
|
|
|||
|
|
// 检查信号强度是否符合要求
|
|||
|
|
if (rssi >= MIN_RSSI_THRESHOLD) {
|
|||
|
|
// 检查是否是当前找到的信号最强的网络
|
|||
|
|
if (rssi > bestNetwork.rssi) {
|
|||
|
|
bestNetwork.ssid = savedNetworks[i].ssid;
|
|||
|
|
bestNetwork.password = savedNetworks[i].password;
|
|||
|
|
bestNetwork.rssi = rssi;
|
|||
|
|
Serial.printf("📈 更新最佳网络: %s, 信号: %d dBm\n",
|
|||
|
|
bestNetwork.ssid, bestNetwork.rssi);
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
Serial.printf("⚠️ 信号强度过低,跳过\n");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 如果找到最佳网络,尝试连接
|
|||
|
|
if (bestNetwork.ssid != nullptr) {
|
|||
|
|
Serial.printf("✅ 选择信号最强的网络: %s, 信号: %d dBm\n",
|
|||
|
|
bestNetwork.ssid, bestNetwork.rssi);
|
|||
|
|
if (connectToNetwork(bestNetwork.ssid, bestNetwork.password)) {
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Serial.println("❌ 未找到匹配的WiFi网络或信号过弱");
|
|||
|
|
currentState = WIFI_DISCONNECTED;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 初始化WiFi连接
|
|||
|
|
* 启动WiFi初始化过程,尝试连接到已保存的网络
|
|||
|
|
* @return 是否初始化成功
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::initializeWiFi() {
|
|||
|
|
Serial.println("🚀 [WiFi] 初始化WiFi连接...");
|
|||
|
|
|
|||
|
|
if (savedNetworkCount == 0) {
|
|||
|
|
Serial.println("⚠️ 未保存的WiFi配置");
|
|||
|
|
currentState = WIFI_IDLE;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (scanAndMatchNetworks()) {
|
|||
|
|
Serial.println("✅ WiFi初始化成功");
|
|||
|
|
return true;
|
|||
|
|
} else {
|
|||
|
|
Serial.println("❌ WiFi初始化失败");
|
|||
|
|
currentState = WIFI_DISCONNECTED;
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 扫描WiFi网络并发送结果
|
|||
|
|
* 扫描附近的WiFi网络,过滤信号弱的网络,将结果通过BLE发送给客户端
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::scanAndSendResults() {
|
|||
|
|
Serial.println("📱 [BLE-WiFi] 开始WiFi扫描...");
|
|||
|
|
|
|||
|
|
WiFi.disconnect(true);
|
|||
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|||
|
|
WiFi.mode(WIFI_STA);
|
|||
|
|
vTaskDelay(100 / portTICK_PERIOD_MS);
|
|||
|
|
|
|||
|
|
int n = WiFi.scanNetworks();
|
|||
|
|
Serial.printf("🔍 扫描到 %d 个WiFi网络\n", n);
|
|||
|
|
|
|||
|
|
if (n <= 0) {
|
|||
|
|
Serial.println("❌ 未扫描到任何WiFi网络或扫描失败");
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
String errorMsg = String("{\"type\":\"scanWiFiResult\",\"success\":false,\"message\":\"未扫描到任何WiFi网络或扫描失败\",\"networks\":[],\"count\":0}");
|
|||
|
|
sendJSONDataToBLE(errorMsg);
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 构建WiFi网络列表的JSON数据
|
|||
|
|
String wifiList = String("{\"type\":\"scanWiFiResult\",\"success\":true,\"count\":") + String(n) + String(",\"networks\":[");
|
|||
|
|
|
|||
|
|
bool first = true;
|
|||
|
|
for (int i = 0; i < n; ++i) {
|
|||
|
|
if (WiFi.RSSI(i) >= MIN_RSSI_THRESHOLD) {
|
|||
|
|
if (!first) {
|
|||
|
|
wifiList += ",";
|
|||
|
|
}
|
|||
|
|
wifiList += String("{\"ssid\":\"") + WiFi.SSID(i) + String("\",\"rssi\":") +
|
|||
|
|
String(WiFi.RSSI(i)) + String(",\"channel\":") +
|
|||
|
|
String(WiFi.channel(i)) + String(",\"encryption\":");
|
|||
|
|
|
|||
|
|
// 根据加密类型添加相应的描述
|
|||
|
|
switch (WiFi.encryptionType(i)) {
|
|||
|
|
case WIFI_AUTH_OPEN:
|
|||
|
|
wifiList += String("\"open\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WEP:
|
|||
|
|
wifiList += String("\"WEP\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WPA_PSK:
|
|||
|
|
wifiList += String("\"WPA\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WPA2_PSK:
|
|||
|
|
wifiList += String("\"WPA2\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WPA_WPA2_PSK:
|
|||
|
|
wifiList += String("\"WPA/WPA2\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WPA2_ENTERPRISE:
|
|||
|
|
wifiList += String("\"WPA2-EAP\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WPA3_PSK:
|
|||
|
|
wifiList += String("\"WPA3\"");
|
|||
|
|
break;
|
|||
|
|
case WIFI_AUTH_WPA2_WPA3_PSK:
|
|||
|
|
wifiList += String("\"WPA2/WPA3\"");
|
|||
|
|
break;
|
|||
|
|
default:
|
|||
|
|
wifiList += String("\"unknown\"");
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
wifiList += "}";
|
|||
|
|
first = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
wifiList += "]}";
|
|||
|
|
|
|||
|
|
Serial.printf("✅ 发送WiFi扫描结果,包含 %d 个可用网络\n", first ? 0 : n);
|
|||
|
|
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
sendJSONDataToBLE(wifiList);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 开始配网模式
|
|||
|
|
* 进入配网模式,扫描WiFi网络并发送结果给客户端
|
|||
|
|
* @return 是否成功进入配网模式
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::startConfiguration() {
|
|||
|
|
Serial.println("⚙️ [WiFi] 开始配网模式...");
|
|||
|
|
currentState = WIFI_CONFIGURING;
|
|||
|
|
scanAndSendResults();
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 处理配网数据
|
|||
|
|
* 处理从客户端收到的WiFi配网信息,先扫描WiFi是否有匹配的网络,再尝试连接并保存
|
|||
|
|
* @param ssid WiFi网络名称
|
|||
|
|
* @param password WiFi网络密码
|
|||
|
|
* @return 是否配置成功
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::handleConfigurationData(const char* ssid, const char* password) {
|
|||
|
|
Serial.printf("📱 [BLE-WiFi] 收到配网信息: SSID='%s'\n", ssid);
|
|||
|
|
|
|||
|
|
if (ssid == nullptr || password == nullptr || strlen(ssid) == 0) {
|
|||
|
|
Serial.println("❌ 配网参数无效");
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 先扫描WiFi网络,检查是否存在匹配的网络
|
|||
|
|
Serial.println("🔍 [WiFi] 扫描WiFi网络,检查是否存在匹配的网络...");
|
|||
|
|
int n = WiFi.scanNetworks();
|
|||
|
|
Serial.printf("🔍 扫描到 %d 个WiFi网络\n", n);
|
|||
|
|
|
|||
|
|
if (n == 0) {
|
|||
|
|
Serial.println("❌ 未扫描到任何WiFi网络");
|
|||
|
|
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
String resultMsg = String("{\"type\":\"wifiConfigResult\",\"success\":false,\"message\":\"未扫描到任何WiFi网络,请检查设备位置\"}");
|
|||
|
|
sendJSONDataToBLE(resultMsg);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
bool networkFound = false;
|
|||
|
|
bool signalTooWeak = false;
|
|||
|
|
int foundRssi = 0;
|
|||
|
|
|
|||
|
|
for (int i = 0; i < n; i++) {
|
|||
|
|
if (WiFi.SSID(i) == String(ssid)) {
|
|||
|
|
foundRssi = WiFi.RSSI(i);
|
|||
|
|
Serial.printf("📶 找到匹配网络: %s, 信号: %d dBm\n", ssid, foundRssi);
|
|||
|
|
|
|||
|
|
if (foundRssi >= MIN_RSSI_THRESHOLD) {
|
|||
|
|
Serial.printf("✅ 信号强度符合要求,准备连接...\n");
|
|||
|
|
networkFound = true;
|
|||
|
|
break;
|
|||
|
|
} else {
|
|||
|
|
Serial.printf("⚠️ 信号强度过低,跳过\n");
|
|||
|
|
signalTooWeak = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (!networkFound) {
|
|||
|
|
String errorMsg;
|
|||
|
|
|
|||
|
|
if (signalTooWeak) {
|
|||
|
|
errorMsg = String("{\"type\":\"wifiConfigResult\",\"success\":false,\"message\":\"目标WiFi信号过弱,请将设备靠近路由器\"}");
|
|||
|
|
Serial.printf("❌ 目标WiFi信号过弱: %d dBm (阈值: %d dBm)\n", foundRssi, MIN_RSSI_THRESHOLD);
|
|||
|
|
} else {
|
|||
|
|
errorMsg = String("{\"type\":\"wifiConfigResult\",\"success\":false,\"message\":\"未找到目标WiFi网络,请检查WiFi名称是否正确\"}");
|
|||
|
|
Serial.println("❌ 未找到目标WiFi网络");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
sendJSONDataToBLE(errorMsg);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 尝试连接到指定网络
|
|||
|
|
if (connectToNetwork(ssid, password)) {
|
|||
|
|
// 连接成功后保存配置
|
|||
|
|
if (saveWiFiConfig(ssid, password)) {
|
|||
|
|
Serial.println("✅ WiFi配置成功并已保存");
|
|||
|
|
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
String resultMsg = String("{\"type\":\"wifiConfigResult\",\"success\":true,\"message\":\"WiFi配置成功\"}");
|
|||
|
|
sendJSONDataToBLE(resultMsg);
|
|||
|
|
}
|
|||
|
|
return true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
Serial.println("❌ WiFi配置失败");
|
|||
|
|
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
String resultMsg = String("{\"type\":\"wifiConfigResult\",\"success\":false,\"message\":\"WiFi配置失败,请检查密码是否正确\"}");
|
|||
|
|
sendJSONDataToBLE(resultMsg);
|
|||
|
|
}
|
|||
|
|
return false;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 处理WiFi重连
|
|||
|
|
* 检查WiFi连接状态,当断开连接时尝试重连
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::handleReconnect() {
|
|||
|
|
// 检查当前是否已连接
|
|||
|
|
if (currentState == WIFI_CONNECTED) {
|
|||
|
|
if (WiFi.status() == WL_CONNECTED) {
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
// 连接已断开
|
|||
|
|
currentState = WIFI_DISCONNECTED;
|
|||
|
|
setNetworkStatus(NET_DISCONNECTED);
|
|||
|
|
Serial.println("⚠️ WiFi连接断开");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 处理重连逻辑
|
|||
|
|
if (currentState == WIFI_DISCONNECTED) {
|
|||
|
|
unsigned long currentTime = millis();
|
|||
|
|
|
|||
|
|
// 按照设定的间隔尝试重连
|
|||
|
|
if (currentTime - lastReconnectAttempt >= WIFI_RECONNECT_INTERVAL) {
|
|||
|
|
lastReconnectAttempt = currentTime;
|
|||
|
|
|
|||
|
|
if (scanAndMatchNetworks()) {
|
|||
|
|
Serial.println("✅ WiFi重连成功");
|
|||
|
|
} else {
|
|||
|
|
Serial.println("❌ WiFi重连失败,2秒后重试");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取当前WiFi状态
|
|||
|
|
* @return 当前的WiFi管理器状态
|
|||
|
|
*/
|
|||
|
|
WiFiManagerState WiFiManager::getState() {
|
|||
|
|
return currentState;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 检查WiFi是否已连接
|
|||
|
|
* @return WiFi是否已成功连接
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::isConnected() {
|
|||
|
|
return currentState == WIFI_CONNECTED && WiFi.status() == WL_CONNECTED;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 断开WiFi连接
|
|||
|
|
* 主动断开当前的WiFi连接
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::disconnect() {
|
|||
|
|
WiFi.disconnect(true);
|
|||
|
|
currentState = WIFI_DISCONNECTED;
|
|||
|
|
setNetworkStatus(NET_DISCONNECTED);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 添加WiFi配置
|
|||
|
|
* 向保存的配置中添加新的WiFi网络
|
|||
|
|
* @param ssid WiFi网络名称
|
|||
|
|
* @param password WiFi网络密码
|
|||
|
|
* @return 是否添加成功
|
|||
|
|
*/
|
|||
|
|
bool WiFiManager::addWiFiConfig(const char* ssid, const char* password) {
|
|||
|
|
return saveWiFiConfig(ssid, password);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 清除所有WiFi配置
|
|||
|
|
* 删除所有保存的WiFi网络配置
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::clearAllConfigs() {
|
|||
|
|
for (int i = 0; i < MAX_WIFI_NETWORKS; i++) {
|
|||
|
|
String key = "wifi_" + String(i);
|
|||
|
|
preferences.remove(key.c_str());
|
|||
|
|
}
|
|||
|
|
savedNetworkCount = 0;
|
|||
|
|
Serial.println("🗑️ 已清除所有WiFi配置");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取已保存的网络数量
|
|||
|
|
* @return 已保存的WiFi网络配置数量
|
|||
|
|
*/
|
|||
|
|
int WiFiManager::getSavedNetworkCount() {
|
|||
|
|
return savedNetworkCount;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 获取已保存的WiFi网络列表
|
|||
|
|
* 将保存的WiFi网络配置通过BLE发送给客户端
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::getSavedNetworks() {
|
|||
|
|
Serial.printf("📋 [WiFi] 获取已保存的WiFi网络列表,共 %d 个\n", savedNetworkCount);
|
|||
|
|
|
|||
|
|
if (savedNetworkCount == 0) {
|
|||
|
|
Serial.println("⚠️ 没有保存的WiFi网络");
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
String responseMsg = String("{\"type\":\"savedNetworks\",\"success\":true,\"count\":0,\"networks\":[]}");
|
|||
|
|
sendJSONDataToBLE(responseMsg);
|
|||
|
|
}
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
String wifiList = String("{\"type\":\"savedNetworks\",\"success\":true,\"count\":") + String(savedNetworkCount) + String(",\"networks\":[");
|
|||
|
|
|
|||
|
|
for (int i = 0; i < savedNetworkCount; i++) {
|
|||
|
|
if (i > 0) {
|
|||
|
|
wifiList += ",";
|
|||
|
|
}
|
|||
|
|
wifiList += String("{\"ssid\":\"") + String(savedNetworks[i].ssid) + String("\"}");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
wifiList += "]}";
|
|||
|
|
|
|||
|
|
Serial.printf("📤 [WiFi] 发送已保存的WiFi网络列表: %s\n", wifiList.c_str());
|
|||
|
|
|
|||
|
|
if (deviceConnected) {
|
|||
|
|
sendJSONDataToBLE(wifiList);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* @brief 更新WiFi管理器状态
|
|||
|
|
* 定期调用此函数,处理WiFi重连等状态管理
|
|||
|
|
*/
|
|||
|
|
void WiFiManager::update() {
|
|||
|
|
handleReconnect();
|
|||
|
|
}
|