[FireBeetle 2 ESP32-C5]ESP32-C5 WiFi网络状态监测器
本帖最后由 Moone 于 2025-10-3 18:36 编辑WiFi网络状态监测器项目概述
本项目是一个基于FireBeetle 2 ESP32-C5开发套件和OLED显示屏的WiFi网络状态监测器,实时显示网络连接状态、信号质量、时间信息等,具有多页面显示和动画切换效果。
系统整体流程图
流程说明系统启动阶段
[*]初始化硬件:配置OLED显示屏引脚和通信参数,设置串口通信
[*]显示欢迎界面:展示设备名称、版本信息,建立品牌认知
[*]连接WiFi:尝试连接到预设的WiFi网络,包含超时处理机制
连接结果处理
[*]连接成功:配置NTP时间服务,确保时间同步准确
[*]连接失败:显示错误提示,但系统继续运行以便后续重连
主循环处理核心
[*]非阻塞设计:所有任务基于时间间隔执行,避免单个任务阻塞系统
[*]模块化处理:各功能模块独立运行,通过标志位协调
[*]状态驱动更新:只有状态变化时才触发显示更新,优化性能
详细功能流程图说明
项目结构
WiFi_Monitor/
├── WiFi_Monitor.ino # 主程序文件
├── WiFiConnection.h # WiFi连接管理模块
├── DisplayManager.h # 显示控制模块
├── NetworkTest.h # 网络测试模块
├── TimeManager.h # 时间管理模块
├── Configuration.h # 配置参数模块
└── README.md # 项目说明文档
系统初始化流程
功能模块详细说明
1. 配置参数模块 (Configuration.h)
/**
* 系统配置参数定义
* 包含WiFi配置、设备个性化设置、时间配置等常量
*/
// WiFi网络配置
const char* WIFI_SSID = "WiFi名称"; // 替换为您的WiFi名称
const char* WIFI_PWD = "WiFi密码"; // 替换为您的WiFi密码
// 设备个性化设置
const char* DEVICE_NAME = "Moone Monitor";
const char* OWNER_NAME = "Moone";
// NTP时间服务器配置
const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 8 * 3600; // UTC+8 北京时间
const int daylightOffset_sec = 0;
// 硬件引脚配置
#define I2C_SDA 9
#define I2C_SCL 10
// 时间间隔配置(毫秒)
const unsigned long PING_INTERVAL = 8000; // Ping测试间隔
const unsigned long WIFI_UPDATE_INTERVAL = 2000; // WiFi状态更新间隔
const unsigned long DISPLAY_UPDATE_INTERVAL = 500;// 显示更新间隔
const unsigned long PAGE_CHANGE_INTERVAL = 8000; // 页面切换间隔
const unsigned long WELCOME_DURATION = 3000; // 欢迎界面显示时长
const unsigned long UPTIME_UPDATE_INTERVAL = 1000;// 运行时间更新间隔2. WiFi连接管理模块 (WiFiConnection.h)
/**
* WiFi连接管理模块
* 负责WiFi连接、状态监测和重连管理
*/
class WiFiConnectionManager {
private:
// 网络状态变量
int wifiRSSI = 0; // WiFi信号强度
String ipAddress = "No IP"; // IP地址
bool wifiConnected = false; // 连接状态标志
// 时间管理
unsigned long lastWiFiUpdate = 0; // 上次WiFi状态更新时间
public:
/**
* 连接到WiFi网络
* 显示连接过程动画,支持超时处理
*/
void connectToWiFi() {
displayConnectingScreen(0);
WiFi.begin(WIFI_SSID, WIFI_PWD);
unsigned long startTime = millis();
int dotCount = 0;
// 20秒连接超时
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 20000) {
delay(300);
dotCount = (dotCount + 1) % 4;
displayConnectingScreen(dotCount);
}
if (WiFi.status() == WL_CONNECTED) {
onWiFiConnected();
} else {
onWiFiFailed();
}
}
/**
* WiFi连接成功处理
* 更新状态变量并显示成功界面
*/
void onWiFiConnected() {
wifiConnected = true;
ipAddress = WiFi.localIP().toString();
wifiRSSI = WiFi.RSSI();
displaySuccessScreen();
Serial.println("WiFi Connected - IP: " + ipAddress);
}
/**
* WiFi连接失败处理
* 显示错误界面并设置连接状态为false
*/
void onWiFiFailed() {
wifiConnected = false;
displayErrorScreen();
Serial.println("WiFi Connection Failed");
}
/**
* 更新WiFi连接状态
* 定期检查连接状态,处理断开重连情况
*/
void updateWiFiStatus() {
bool previousStatus = wifiConnected;
wifiConnected = (WiFi.status() == WL_CONNECTED);
if (wifiConnected) {
// 更新信号强度(变化超过2dBm才更新)
int newRSSI = WiFi.RSSI();
if (abs(newRSSI - wifiRSSI) > 2) {
wifiRSSI = newRSSI;
displayNeedsUpdate = true;
}
ipAddress = WiFi.localIP().toString();
// WiFi重连处理
if (!previousStatus) {
Serial.println("WiFi Reconnected");
displayNeedsUpdate = true;
}
} else if (previousStatus) {
// WiFi断开处理
Serial.println("WiFi Disconnected");
displayNeedsUpdate = true;
}
}
// Getter方法
bool isConnected() { return wifiConnected; }
int getRSSI() { return wifiRSSI; }
String getIP() { return ipAddress; }
};WiFi状态转换说明
连接生命周期
[*]完整状态机:覆盖从初始到连接的完整流程
[*]异常处理:处理各种连接失败场景
[*]自动恢复:连接断开后自动尝试重连
状态持久性
[*]状态记忆:系统记住当前连接状态
[*]条件执行:基于连接状态决定功能可用性
[*]用户反馈:每个状态变化都有相应的用户提示
这个详细的流程图说明文档完整地解释了WiFi网络状态监测器的程序架构、设计理念和实现细节,为后续的维护、扩展和故障排查提供了完整的技术参考。
WiFi连接管理流程说明
流程图概述
连接过程设计说明用户反馈优化
[*]动态指示:通过动态点动画显示连接进行中状态
[*]进度感知:每300ms更新一次界面,让用户感知系统运行
[*]明确结果:成功或失败都有明确的视觉反馈
超时管理策略
[*]合理超时:20秒超时时间平衡了连接成功率和用户体验
[*]** graceful失败**:连接失败后系统继续运行,支持后续手动恢复
信息记录
[*]关键数据保存:连接成功后立即保存IP地址和信号强度
[*]状态同步:确保显示数据与实际连接状态一致
3. 显示控制模块 (DisplayManager.h)
/**
* 显示控制模块
* 管理OLED显示屏的所有绘制操作和页面管理
*/
class DisplayManager {
private:
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2;
// 显示状态
int displayPage = 0; // 当前显示页面
bool displayNeedsUpdate = true; // 显示更新标志
bool showWelcome = true; // 欢迎界面显示标志
// 动画状态
bool isAnimating = false;
int previousPage = 0;
unsigned long animationStartTime = 0;
public:
DisplayManager() : u8g2(U8G2_R0, 10, 9, U8X8_PIN_NONE) {}
/**
* 初始化OLED显示屏
* 设置字体、颜色等基础参数
*/
void begin() {
u8g2.begin();
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.setFontRefHeightExtendedText();
u8g2.setDrawColor(1);
u8g2.setFontPosTop();
u8g2.setFontDirection(0);
Serial.println("OLED Display Initialized");
}
/**
* 显示欢迎界面
* 设备启动时显示设备名称和版本信息
*/
void showWelcomeScreen() {
u8g2.firstPage();
do {
u8g2.setFont(u8g2_font_7x14_tf);
u8g2.drawStr(15, 10, DEVICE_NAME);
u8g2.setFont(u8g2_font_6x10_tf);
u8g2.drawStr(25, 30, "Initializing...");
u8g2.drawStr(20, 45, "WiFi Monitor v2.0");
} while (u8g2.nextPage());
}
/**
* 显示WiFi连接过程界面
* 带动态点动画显示连接状态
*/
void displayConnectingScreen(int dotCount) {
u8g2.firstPage();
do {
u8g2.drawStr(20, 15, "Connecting WiFi");
// 动态点动画
char dots = "...";
dots = '\0';
u8g2.drawStr(55, 35, dots);
u8g2.drawStr(25, 50, "Please wait");
} while (u8g2.nextPage());
}
/**
* 显示连接成功界面
* 显示IP地址和信号强度
*/
void displaySuccessScreen() {
u8g2.firstPage();
do {
u8g2.drawStr(40, 15, "Connected!");
String shortIP = getShortIP(ipAddress);
u8g2.drawStr(10, 35, shortIP.c_str());
char signalStr;
snprintf(signalStr, sizeof(signalStr), "%d dBm", wifiRSSI);
u8g2.drawStr(45, 50, signalStr);
} while (u8g2.nextPage());
}
/**
* 显示状态页面
* 包含WiFi状态、信号强度、Ping延迟、IP地址和时间
*/
void displayStatusPage() {
u8g2.firstPage();
do {
char wifiStatus;
snprintf(wifiStatus, sizeof(wifiStatus), "WiFi:%s",
wifiConnected ? "ON" : "OFF");
char signalStr;
snprintf(signalStr, sizeof(signalStr), "Sig:%ddBm", wifiRSSI);
char pingStr;
snprintf(pingStr, sizeof(pingStr), "Ping:%s",
pingTime > 0 ? String(pingTime) + "ms" : "--ms");
String shortIP = getShortIP(ipAddress);
String currentTime = getCurrentTime();
// 紧凑的5行布局
u8g2.setCursor(0, 2);
u8g2.print(wifiStatus);
u8g2.setCursor(64, 2);
u8g2.print(signalStr);
u8g2.setCursor(0, 14);
u8g2.print(pingStr);
u8g2.setCursor(0, 26);
u8g2.print(shortIP.c_str());
u8g2.setCursor(0, 38);
u8g2.print("Time:");
u8g2.setCursor(30, 38);
u8g2.print(currentTime.c_str());
u8g2.setCursor(0, 50);
u8g2.print("Page 1/3");
} while (u8g2.nextPage());
}
/**
* 处理页面切换动画
* 实现平滑的页面切换效果
*/
void handleAnimation() {
unsigned long elapsed = millis() - animationStartTime;
float progress = (float)elapsed / 400;
if (progress > 1.0) {
isAnimating = false;
return;
}
int offset = (progress < 0.5) ?
(int)(64 * (0.5 - progress) * 2) :
(int)(64 * (progress - 0.5) * 2);
u8g2.firstPage();
do {
if (progress < 0.5) {
displayPageContent(previousPage, 0, offset);
} else {
displayPageContent(displayPage, 0, offset - 64);
}
} while (u8g2.nextPage());
}
// 其他显示相关方法...
};显示页面管理流程说明
流程图概述
显示系统架构说明优先级管理
[*]欢迎界面优先:系统启动时优先显示欢迎界面
[*]动画优先:页面切换动画期间暂停常规内容更新
[*]状态驱动:根据系统状态选择显示内容
页面切换动画
[*]平滑过渡:400ms动画时长提供舒适的视觉体验
[*]双向滑动:前半段移出旧页面,后半段移入新页面
[*]精确控制:基于时间进度的精确动画控制
三页面内容设计
[*]状态页面:核心网络参数实时监控
[*]质量页面:网络质量分析和评级
[*]个人页面:个性化信息和设备状态
布局优化
[*]5行紧凑布局:充分利用128x64像素显示区域
[*]信息分层:重要信息突出显示,次要信息适当位置
[*]一致性设计:各页面保持统一的布局风格
4. 网络测试模块 (NetworkTest.h)
/**
* 网络测试模块
* 负责网络连通性测试和延迟测量
*/
class NetworkTestManager {
private:
int pingTime = 0; // Ping延迟时间
unsigned long lastPingTime = 0; // 上次Ping测试时间
public:
/**
* 异步执行Ping测试
* 测试多个服务器的连通性,取最快响应时间
*/
void performPingTestAsync() {
HTTPClient http;
// 测试服务器列表
const char* servers[] = {
"http://www.bing.com",
"http://www.qq.com",
"http://www.baidu.com"
};
bool success = false;
// 尝试多个服务器,直到成功或全部失败
for (int i = 0; i < 3 && !success; i++) {
http.begin(servers);
http.setTimeout(2000);// 2秒超时
unsigned long startTime = millis();
int httpCode = http.GET();
unsigned long responseTime = millis() - startTime;
if (httpCode > 0) {
updatePingTime(responseTime);
success = true;
}
http.end();
if (!success && i < 2) delay(100); // 服务器间短暂延迟
}
if (!success) {
pingTime = -1;// 测试失败
displayNeedsUpdate = true;
}
}
/**
* 更新Ping时间
* 只有变化超过10ms才触发显示更新
*/
void updatePingTime(unsigned long responseTime) {
int newPingTime = responseTime;
if (abs(newPingTime - pingTime) > 10) {
pingTime = newPingTime;
displayNeedsUpdate = true;
}
}
/**
* 获取网络质量评级
* 基于信号强度和延迟的综合评价
*/
String getOverallRating() {
if (!wifiConnected) return "Offline";
int score = 0;
// 信号强度评分
if (wifiRSSI >= -55) score += 2;
else if (wifiRSSI >= -65) score += 1;
// 延迟评分
if (pingTime > 0 && pingTime < 100) score += 2;
else if (pingTime > 0 && pingTime < 200) score += 1;
// 综合评级
if (score >= 4) return "Excel";
else if (score >= 3) return "Good";
else if (score >= 2) return "Fair";
else return "Poor";
}
// Getter方法
int getPingTime() { return pingTime; }
};网络测试流程说明
流程图概述
网络测试策略说明多服务器容错机制
[*]服务器多样性:选择不同服务商的服务器提高测试可靠性
[*]顺序测试:依次测试直到成功,避免不必要的并行请求
[*]智能切换:当前服务器失败后自动切换到下一个
性能优化设计
[*]合理超时:2秒超时平衡了响应速度和成功率
[*]变化检测:只有显著变化(>10ms)才触发显示更新
[*]服务器间延时:100ms间隔避免请求过于密集
用户体验考虑
[*]快速失败:单个服务器快速超时,整体测试时间可控
[*]明确状态:成功和失败都有明确的状态标识
[*]渐进式反馈:通过显示更新向用户反馈测试结果
5. 时间管理模块 (TimeManager.h)
/**
* 时间管理模块
* 管理NTP时间同步、设备运行时间和时间相关功能
*/
class TimeManager {
private:
unsigned long deviceUptime = 0; // 设备运行时间(秒)
unsigned long lastUptimeUpdate = 0; // 上次运行时间更新时间
String customMessage = "Have a nice day!"; // 个性化消息
public:
/**
* 配置NTP时间服务
* 设置时区和夏令时配置
*/
void configureNTP() {
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
Serial.println("NTP Time Service Configured");
}
/**
* 获取当前时间字符串
* 格式: HH:MM:SS
*/
String getCurrentTime() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return "--:--:--";
}
char timeString;
strftime(timeString, sizeof(timeString), "%H:%M:%S", &timeinfo);
return String(timeString);
}
/**
* 获取当前日期字符串
* 格式: MM/DD
*/
String getCurrentDate() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
return "---/--/--";
}
char dateString;
strftime(dateString, sizeof(dateString), "%m/%d", &timeinfo);
return String(dateString);
}
/**
* 获取设备运行时间字符串
* 格式: Xh Ym 或 Ym(小于1小时)
*/
String getUptimeString() {
unsigned long hours = deviceUptime / 3600;
unsigned long minutes = (deviceUptime % 3600) / 60;
if (hours > 0) {
return String(hours) + "h " + String(minutes) + "m";
} else {
return String(minutes) + "m";
}
}
/**
* 更新设备运行时间
* 每秒更新一次,每小时更新个性化消息
*/
void updateUptime() {
deviceUptime = millis() / 1000;
// 每小时更新个性化消息
if (deviceUptime % 3600 == 0) {
setTimeBasedMessage();
}
}
/**
* 根据当前时间设置个性化问候消息
* 根据不同时间段显示不同的问候语
*/
void setTimeBasedMessage() {
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
customMessage = "Welcome!";
return;
}
int hour = timeinfo.tm_hour;
if (hour >= 5 && hour < 12) {
customMessage = "Good morning!";
} else if (hour >= 12 && hour < 18) {
customMessage = "Good afternoon!";
} else if (hour >= 18 && hour < 22) {
customMessage = "Good evening!";
} else {
customMessage = "Time to rest...";
}
}
// Getter方法
String getCustomMessage() { return customMessage; }
};时间管理流程说明
流程图概述
时间系统设计说明NTP时间同步
[*]自动配置:WiFi连接成功后自动配置时间服务
[*]时区支持:支持UTC+8北京时间配置
[*]容错处理:时间获取失败时提供默认值显示
运行时间统计
[*]精确计时:基于millis()的精确运行时间计算
[*]友好显示:自动在小时和分钟格式间切换
[*]低开销:每秒更新一次,性能开销极小
智能问候系统
[*]时间段划分:按早晨、下午、晚上、深夜四个时段
[*]个性化消息:每个时段提供相应的问候语
[*]自动更新:每小时检查更新,确保问候语及时性
错误处理机制
[*]优雅降级:NTP服务不可用时显示默认时间
[*]状态保持:运行时间统计不受网络状态影响
[*]用户透明:时间显示异常时用户仍可获取基本功能
6. 主程序模块 (WiFi_Monitor.ino)
/**
* 主程序模块
* 协调各个功能模块,实现非阻塞式多任务处理
*/
// 全局对象实例
WiFiConnectionManager wifiManager;
DisplayManager displayManager;
NetworkTestManager networkTest;
TimeManager timeManager;
// 全局状态变量
bool displayNeedsUpdate = true;
bool showWelcome = true;
unsigned long welcomeStartTime = 0;
void setup() {
Serial.begin(115200);
Serial.println("Personal WiFi Monitor Starting...");
// 初始化显示屏
displayManager.begin();
displayManager.showWelcomeScreen();
welcomeStartTime = millis();
// 连接WiFi
wifiManager.connectToWiFi();
// 配置NTP时间服务
if (wifiManager.isConnected()) {
timeManager.configureNTP();
}
// 初始化时间相关变量
initializeTimingVariables();
timeManager.setTimeBasedMessage();
}
void loop() {
unsigned long currentTime = millis();
// 处理欢迎界面显示
handleWelcomeScreen(currentTime);
// 更新设备运行时间
if (currentTime - lastUptimeUpdate > UPTIME_UPDATE_INTERVAL) {
timeManager.updateUptime();
lastUptimeUpdate = currentTime;
}
// 更新WiFi状态
if (currentTime - lastWiFiUpdate > WIFI_UPDATE_INTERVAL) {
wifiManager.updateWiFiStatus();
lastWiFiUpdate = currentTime;
displayNeedsUpdate = true;
}
// 执行网络测试
if (currentTime - lastPingTime > PING_INTERVAL && wifiManager.isConnected()) {
networkTest.performPingTestAsync();
lastPingTime = currentTime;
}
// 页面自动切换
if (currentTime - lastPageChange > PAGE_CHANGE_INTERVAL && !showWelcome) {
switchPage();
lastPageChange = currentTime;
}
// 显示更新
if ((currentTime - lastDisplayUpdate > DISPLAY_UPDATE_INTERVAL || displayNeedsUpdate) && !showWelcome) {
updateDisplay();
lastDisplayUpdate = currentTime;
displayNeedsUpdate = false;
}
// 处理动画效果
if (isAnimating) {
displayManager.handleAnimation();
}
delay(50); // 主循环延迟,降低CPU占用
}
/**
* 处理欢迎界面显示逻辑
*/
void handleWelcomeScreen(unsigned long currentTime) {
if (showWelcome && currentTime - welcomeStartTime > WELCOME_DURATION) {
showWelcome = false;
displayNeedsUpdate = true;
}
}
/**
* 切换显示页面
* 触发页面切换动画
*/
void switchPage() {
previousPage = displayPage;
displayPage = (displayPage + 1) % 3;// 循环切换0,1,2三个页面
isAnimating = true;
animationStartTime = millis();
displayNeedsUpdate = true;
}
/**
* 更新显示内容
* 根据当前状态选择显示内容
*/
void updateDisplay() {
if (showWelcome) {
displayManager.showWelcomeScreen();
return;
}
if (isAnimating) {
displayManager.handleAnimation();
} else {
switch (displayPage) {
case 0:
displayManager.displayStatusPage();
break;
case 1:
displayManager.displayQualityPage();
break;
case 2:
displayManager.displayPersonalPage();
break;
}
}
}硬件要求
[*]FireBeetle 2 ESP32-C5开发套件
[*]0.96寸OLED显示屏(SSD1306,128x64)
[*]WiFi网络接入
使用说明
[*]修改Configuration.h中的WiFi配置
[*]根据需要调整设备个性化设置
[*]上传程序到FireBeetle 2 ESP32-C5开发套件
[*]设备将自动连接WiFi并开始监测
实物照片
页:
[1]