实现在连接网络后,获取SNTP时间

This commit is contained in:
2026-02-11 22:00:11 +08:00
parent a30497958a
commit f8564dbcc5
2 changed files with 176 additions and 51 deletions

View File

@@ -22,7 +22,20 @@ WIFI_HandleTypeDef wifi = {0};
static volatile uint8_t mqtt_connected = 0;
static MQTT_State_t mqtt_state = MQTT_STATE_IDLE;
static void Generate_Random_ClientID(char *out_id, uint16_t max_len) {
// SNTP 时间结构体
typedef struct {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint8_t valid; // 1表示有效0表示无效
} SNTP_Time_t;
static SNTP_Time_t sntp_time = {0};
static void Generate_Random_ClientID(char *out_id, uint16_t max_len) {
// 获取系统运行时间
uint32_t tick = HAL_GetTick();
@@ -46,6 +59,7 @@ static void Generate_Random_ClientID(char *out_id, uint16_t max_len) {
sum);
}
/* ================= DMA RX 初始化 ================= */
HAL_StatusTypeDef WIFI_RECV_DMA_Init(void) {
@@ -127,6 +141,7 @@ uint8_t WIFI_WaitEvent(const char *ok_str, const char *fail_str,
elog_i(TAG, "接收到WiFi模块数据: %s", buf);
/* ===== 优先处理断线事件 ===== */
if (strstr(buf, "+MQTTDISCONNECTED")) {
mqtt_connected = 0;
@@ -231,6 +246,13 @@ uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
/* 稍微延时,避免状态机还没稳定 */
osDelay(200);
// 设置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, "模块无响应");
@@ -249,6 +271,8 @@ uint8_t WIFI_Connect_MQTT(const char *wifi_ssid, const char *wifi_pass,
return 0;
}
mqtt_state = MQTT_STATE_WIFI_CONNECTED;
elog_i(TAG, "WiFi连接完成状态: %d", mqtt_state);
@@ -430,63 +454,68 @@ uint8_t WIFI_MQTT_Publish_RAW(const char *topic, const uint8_t *payload,
/* ================= MQTT接收任务 ================= */
void wifi_task_mqtt(void *argument) {
MQTT_Message_t msg;
MQTT_Message_t msg;
elog_i(TAG, "启动WiFi MQTT任务");
WIFI_RECV_DMA_Init();
osDelay(3000);
elog_i(TAG, "启动WiFi MQTT任务");
WIFI_RECV_DMA_Init();
osDelay(3000);
char client_id[64] = {0};
char client_id[64] = {0};
// 生成唯一ClientID
Generate_Random_ClientID(client_id, sizeof(client_id));
// 生成唯一ClientID
Generate_Random_ClientID(client_id, sizeof(client_id));
elog_i(TAG, "生成ClientID: %s", client_id);
elog_i(TAG, "生成ClientID: %s", client_id);
elog_i(TAG, "开始MQTT连接...");
if (!WIFI_Connect_MQTT("WIFI_TEST", "88888888", "www.beihong.wang", 1883,
client_id, "STM32_MQTT", "123456")) {
elog_e(TAG, "MQTT连接失败任务退出");
vTaskDelete(NULL); // 删除自身任务
}
elog_i(TAG, "发布设备上线状态");
WIFI_MQTT_Publish_Status("{\"status\":\"online\"}");
elog_i(TAG, "进入MQTT消息处理循环");
for (;;) {
if (wifi.rx_flag) {
wifi.rx_flag = 0;
elog_i(TAG, "收到WiFi数据: %s", wifi.rx_buffer);
if (WIFI_Parse_MQTT_Message((char *)wifi.rx_buffer, &msg)) {
elog_i(TAG, "解析MQTT消息成功");
elog_i(TAG, "收到主题: %s", msg.topic);
elog_i(TAG, "内容: %s", msg.payload);
/* ===== control主题 ===== */
if (strcmp(msg.topic, "petfeeder/control") == 0) {
elog_i(TAG, "处理control主题消息");
if (strstr(msg.payload, "feed")) {
elog_i(TAG, "执行喂食动作");
// 执行喂食函数
}
}
/* ===== config主题 ===== */
else if (strcmp(msg.topic, "petfeeder/config") == 0) {
elog_i(TAG, "处理config主题消息");
elog_i(TAG, "更新配置参数");
// 更新参数逻辑
}
} else {
elog_w(TAG, "MQTT消息解析失败");
}
elog_i(TAG, "开始MQTT连接...");
if (!WIFI_Connect_MQTT("WIFI_TEST", "88888888", "www.beihong.wang", 1883,
client_id, "STM32_MQTT", "123456")) {
elog_e(TAG, "MQTT连接失败任务退出");
vTaskDelete(NULL); // 删除自身任务
}
osDelay(20);
}
elog_i(TAG, "发布设备上线状态");
WIFI_MQTT_Publish_Status("{\"status\":\"online\"}");
// 连接MQTT服务器成功后获取SNTP时间
WIFI_Get_SNTP_Time();
elog_i(TAG, "进入MQTT消息处理循环");
for (;;) {
if (wifi.rx_flag) {
wifi.rx_flag = 0;
elog_i(TAG, "收到WiFi数据: %s", wifi.rx_buffer);
if (WIFI_Parse_MQTT_Message((char *)wifi.rx_buffer, &msg)) {
elog_i(TAG, "解析MQTT消息成功");
elog_i(TAG, "收到主题: %s", msg.topic);
elog_i(TAG, "内容: %s", msg.payload);
/* ===== control主题 ===== */
if (strcmp(msg.topic, "petfeeder/control") == 0) {
elog_i(TAG, "处理control主题消息");
if (strstr(msg.payload, "feed")) {
elog_i(TAG, "执行喂食动作");
// 执行喂食函数
}
}
/* ===== config主题 ===== */
else if (strcmp(msg.topic, "petfeeder/config") == 0) {
elog_i(TAG, "处理config主题消息");
elog_i(TAG, "更新配置参数");
// 更新参数逻辑
}
} else {
elog_w(TAG, "MQTT消息解析失败");
}
}
osDelay(20);
}
}
uint8_t WIFI_Parse_MQTT_Message(char *input, MQTT_Message_t *msg) {
@@ -553,3 +582,94 @@ uint8_t WIFI_MQTT_Publish_Status(const char *json) {
return WIFI_MQTT_Publish_RAW("petfeeder/status", (uint8_t *)json,
strlen(json), 0, 1);
}
/* ================= SNTP 时间相关函数 ================= */
uint8_t WIFI_Enable_SNTP(void) {
elog_i(TAG, "使能SNTP服务器设置中国时区");
// 发送AT+CIPSNTPCFG=1,8,cn.ntp.org.cn命令
if (!WIFI_CheckAck("AT+CIPSNTPCFG=1,8,cn.ntp.org.cn\r\n", "OK", 3000)) {
elog_e(TAG, "SNTP配置失败");
return 0;
}
osDelay(10000); // 等待模块重启并连接到SNTP服务器
elog_i(TAG, "SNTP服务器配置成功模块将自动重启以应用设置");
return 1;
}
uint8_t WIFI_Get_SNTP_Time(void) {
char *time_str;
char time_buf[32];
elog_i(TAG, "查询SNTP时间");
// 发送AT+CIPSNTPTIME命令
if (WIFI_SEND_DMA("AT+CIPSNTPTIME\r\n") != HAL_OK) {
elog_e(TAG, "SNTP时间查询命令发送失败");
return 0;
}
// 等待响应
if (!WIFI_WaitEvent("+CIPSNTPTIME:", "ERROR", 5000)) {
elog_e(TAG, "SNTP时间查询失败");
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",
&year, &month, &day, &hour, &minute, &second) == 6) {
sntp_time.year = (uint16_t)year;
sntp_time.month = (uint8_t)month;
sntp_time.day = (uint8_t)day;
sntp_time.hour = (uint8_t)hour;
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);
return 1;
} else {
elog_e(TAG, "时间字符串解析失败: %s", time_buf);
sntp_time.valid = 0;
return 0;
}
}
// 获取当前SNTP时间返回结构体副本
SNTP_Time_t WIFI_Get_Current_Time(void) {
return sntp_time;
}
// 检查SNTP时间是否有效
uint8_t WIFI_Is_Time_Valid(void) {
return sntp_time.valid;
}

View File

@@ -59,4 +59,9 @@ void wifi_task_mqtt(void *argument);
uint8_t WIFI_MQTT_Publish_Sensor(const char *json);
uint8_t WIFI_MQTT_Publish_Status(const char *json);
/* ================= SNTP函数声明 ================= */
uint8_t WIFI_Enable_SNTP(void);
uint8_t WIFI_Get_SNTP_Time(void);
#endif /* __DX_WF_24_H__ */