```
feat(BSP): 添加WiFi模块MQTT连接优化和SNTP配置改进 - 添加SNTP配置标志位,确保只在首次连接时配置SNTP,避免重复重启模块 - 实现MQTT断线重连机制,支持持续运行和自动重连 - 增加SNTP时间查询频率控制,避免频繁查询导致性能问题 - 添加连接状态检测和心跳机制,超时自动重连 - 优化LCD时间显示界面,分别显示时分和年月日信息 - 调整LCD页面刷新策略,时间页面30秒刷新一次以节省资源 ```
This commit is contained in:
@@ -24,6 +24,13 @@ SNTP_Time_t sntp_time = {0};
|
||||
static volatile uint8_t mqtt_connected = 0;
|
||||
static MQTT_State_t mqtt_state = MQTT_STATE_IDLE;
|
||||
|
||||
/* SNTP配置标志:只配置一次,避免重复重启模块 */
|
||||
static volatile uint8_t sntp_configured = 0;
|
||||
|
||||
/* SNTP时间更新控制:避免频繁查询 */
|
||||
static volatile uint32_t sntp_last_query_tick = 0;
|
||||
static const uint32_t SNTP_QUERY_INTERVAL = 5000; // 5秒查询一次
|
||||
|
||||
|
||||
|
||||
static void Generate_Random_ClientID(char *out_id, uint16_t max_len) {
|
||||
@@ -227,6 +234,20 @@ uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
|
||||
|
||||
elog_i(TAG, "开始MQTT连接流程");
|
||||
|
||||
// 只在第一次配置SNTP(避免重复重启模块)
|
||||
if (!sntp_configured) {
|
||||
elog_i(TAG, "首次配置SNTP服务器...");
|
||||
if (!WIFI_Enable_SNTP()) {
|
||||
elog_e(TAG, "SNTP设置失败");
|
||||
return 0;
|
||||
}
|
||||
sntp_configured = 1;
|
||||
|
||||
// SNTP配置后会重启模块,等待模块恢复
|
||||
elog_i(TAG, "等待模块重启后恢复...");
|
||||
osDelay(3000);
|
||||
}
|
||||
|
||||
elog_i(TAG, "断开 MQTT 连接(如果已连接)");
|
||||
|
||||
if (!WIFI_CheckAck("AT+MQTTCLEAN\r\n", "OK", 2000)) {
|
||||
@@ -240,13 +261,6 @@ uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
|
||||
/* 稍微延时,避免状态机还没稳定 */
|
||||
osDelay(500);
|
||||
|
||||
// 设置SNTP服务器,设置成功会自动重启模块
|
||||
elog_i(TAG,"设置SNTP服务器");
|
||||
if (!WIFI_Enable_SNTP()) {
|
||||
elog_e(TAG, "SNTP设置失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
elog_i(TAG, "1. 检查模块响应...");
|
||||
if (!WIFI_CheckAck("AT\r\n", "OK", 1000)) {
|
||||
elog_e(TAG, "模块无响应");
|
||||
@@ -449,6 +463,8 @@ uint8_t WIFI_MQTT_Publish_RAW(const char *topic, const uint8_t *payload,
|
||||
|
||||
void wifi_task_mqtt(void *argument) {
|
||||
MQTT_Message_t msg;
|
||||
uint8_t mqtt_connected = 0;
|
||||
uint32_t retry_count = 0;
|
||||
|
||||
elog_i(TAG, "启动WiFi MQTT任务");
|
||||
WIFI_RECV_DMA_Init();
|
||||
@@ -461,30 +477,37 @@ void wifi_task_mqtt(void *argument) {
|
||||
|
||||
elog_i(TAG, "生成ClientID: %s", client_id);
|
||||
|
||||
elog_i(TAG, "开始MQTT连接...");
|
||||
if (!WIFI_Connect_MQTT("WIFI_TEST", "88888888", "mqtt.beihong.wang", 1883,
|
||||
client_id, "STM32_MQTT", "123456")) {
|
||||
elog_e(TAG, "MQTT连接失败,任务退出");
|
||||
vTaskDelete(NULL); // 删除自身任务
|
||||
}
|
||||
|
||||
|
||||
|
||||
elog_i(TAG, "发布设备上线状态");
|
||||
WIFI_MQTT_Publish_Status("{\"status\":\"online\"}");
|
||||
|
||||
// 连接MQTT服务器成功后,获取SNTP时间
|
||||
WIFI_Get_SNTP_Time();
|
||||
|
||||
// 获取SNTP时间
|
||||
elog_i(TAG, "获取SNTP时间...");
|
||||
WIFI_Get_Current_Time();
|
||||
elog_i(TAG, "当前SNTP时间为: %04d-%02d-%02d %02d:%02d:%02d",
|
||||
sntp_time.year, sntp_time.month, sntp_time.day,
|
||||
sntp_time.hour, sntp_time.minute, sntp_time.second);
|
||||
|
||||
elog_i(TAG, "进入MQTT消息处理循环");
|
||||
// 主循环:一直运行,支持断线重连
|
||||
for (;;) {
|
||||
// ========== 尝试MQTT连接 ==========
|
||||
if (!mqtt_connected) {
|
||||
elog_i(TAG, "尝试MQTT连接... (重试次数: %lu)", ++retry_count);
|
||||
|
||||
if (WIFI_Connect_MQTT("WIFI_TEST", "88888888", "mqtt.beihong.wang", 1883,
|
||||
client_id, "STM32_MQTT", "123456")) {
|
||||
elog_i(TAG, "MQTT连接成功!");
|
||||
mqtt_connected = 1;
|
||||
retry_count = 0;
|
||||
|
||||
// 发布设备上线状态
|
||||
elog_i(TAG, "发布设备上线状态");
|
||||
WIFI_MQTT_Publish_Status("{\"status\":\"online\"}");
|
||||
|
||||
// 获取SNTP时间
|
||||
elog_i(TAG, "获取SNTP时间...");
|
||||
WIFI_Get_SNTP_Time();
|
||||
WIFI_Get_Current_Time();
|
||||
elog_i(TAG, "当前SNTP时间为: %04d-%02d-%02d %02d:%02d:%02d",
|
||||
sntp_time.year, sntp_time.month, sntp_time.day,
|
||||
sntp_time.hour, sntp_time.minute, sntp_time.second);
|
||||
} else {
|
||||
elog_w(TAG, "MQTT连接失败,5秒后重试...");
|
||||
osDelay(5000);
|
||||
continue; // 继续尝试连接
|
||||
}
|
||||
}
|
||||
|
||||
// ========== MQTT消息处理循环 ==========
|
||||
if (wifi.rx_flag) {
|
||||
wifi.rx_flag = 0;
|
||||
|
||||
@@ -515,6 +538,20 @@ void wifi_task_mqtt(void *argument) {
|
||||
}
|
||||
}
|
||||
|
||||
// 检查连接状态:如果长时间没收到数据,认为可能断线
|
||||
// 这里可以添加心跳检测机制
|
||||
static uint32_t last_activity = 0;
|
||||
if (wifi.rx_flag || mqtt_connected) {
|
||||
last_activity = osKernelGetTickCount();
|
||||
}
|
||||
|
||||
// 5分钟无活动,重新连接
|
||||
if (mqtt_connected && (osKernelGetTickCount() - last_activity > 300000)) {
|
||||
elog_w(TAG, "检测到长时间无活动,重新连接MQTT...");
|
||||
mqtt_connected = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
osDelay(20);
|
||||
}
|
||||
}
|
||||
@@ -605,46 +642,49 @@ uint8_t WIFI_Enable_SNTP(void) {
|
||||
uint8_t WIFI_Get_SNTP_Time(void) {
|
||||
char *time_str;
|
||||
char time_buf[32];
|
||||
|
||||
elog_i(TAG, "查询SNTP时间");
|
||||
|
||||
uint32_t current_tick = osKernelGetTickCount();
|
||||
|
||||
// 避免频繁查询:距离上次查询不足5秒则跳过
|
||||
if (current_tick - sntp_last_query_tick < SNTP_QUERY_INTERVAL) {
|
||||
return sntp_time.valid; // 返回现有时间状态
|
||||
}
|
||||
|
||||
sntp_last_query_tick = current_tick;
|
||||
|
||||
// 发送AT+CIPSNTPTIME命令
|
||||
if (WIFI_SEND_DMA("AT+CIPSNTPTIME\r\n") != HAL_OK) {
|
||||
elog_e(TAG, "SNTP时间查询命令发送失败");
|
||||
elog_w(TAG, "SNTP时间查询命令发送失败");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 等待响应
|
||||
if (!WIFI_WaitEvent("+CIPSNTPTIME:", "ERROR", 5000)) {
|
||||
elog_e(TAG, "SNTP时间查询失败");
|
||||
if (!WIFI_WaitEvent("+CIPSNTPTIME:", "ERROR", 3000)) {
|
||||
// 超时不打印错误日志,避免刷屏
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 解析时间字符串 "+CIPSNTPTIME:2024-05-08 21:11:38"
|
||||
time_str = strstr((char *)wifi.rx_buffer, "+CIPSNTPTIME:");
|
||||
if (!time_str) {
|
||||
elog_e(TAG, "未找到时间字符串");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// 提取时间部分 "2024-05-08 21:11:38"
|
||||
time_str += strlen("+CIPSNTPTIME:");
|
||||
|
||||
|
||||
// 复制到缓冲区以便处理
|
||||
strncpy(time_buf, time_str, sizeof(time_buf) - 1);
|
||||
time_buf[sizeof(time_buf) - 1] = '\0';
|
||||
|
||||
|
||||
// 移除末尾的换行符和回车符
|
||||
char *newline = strchr(time_buf, '\r');
|
||||
if (newline) *newline = '\0';
|
||||
newline = strchr(time_buf, '\n');
|
||||
if (newline) *newline = '\0';
|
||||
|
||||
elog_i(TAG, "解析时间字符串: %s", time_buf);
|
||||
|
||||
|
||||
// 解析时间格式 YYYY-MM-DD HH:MM:SS
|
||||
int year, month, day, hour, minute, second;
|
||||
if (sscanf(time_buf, "%d-%d-%d %d:%d:%d",
|
||||
if (sscanf(time_buf, "%d-%d-%d %d:%d:%d",
|
||||
&year, &month, &day, &hour, &minute, &second) == 6) {
|
||||
sntp_time.year = (uint16_t)year;
|
||||
sntp_time.month = (uint8_t)month;
|
||||
@@ -653,14 +693,17 @@ uint8_t WIFI_Get_SNTP_Time(void) {
|
||||
sntp_time.minute = (uint8_t)minute;
|
||||
sntp_time.second = (uint8_t)second;
|
||||
sntp_time.valid = 1;
|
||||
|
||||
elog_i(TAG, "SNTP时间获取成功: %04d-%02d-%02d %02d:%02d:%02d",
|
||||
sntp_time.year, sntp_time.month, sntp_time.day,
|
||||
sntp_time.hour, sntp_time.minute, sntp_time.second);
|
||||
|
||||
// 只在首次获取成功时打印日志
|
||||
static uint8_t first_time_sync = 0;
|
||||
if (!first_time_sync) {
|
||||
elog_i(TAG, "SNTP时间同步成功: %04d-%02d-%02d %02d:%02d:%02d",
|
||||
sntp_time.year, sntp_time.month, sntp_time.day,
|
||||
sntp_time.hour, sntp_time.minute, sntp_time.second);
|
||||
first_time_sync = 1;
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
elog_e(TAG, "时间字符串解析失败: %s", time_buf);
|
||||
sntp_time.valid = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user