shuichan_old/V1.2/STM32F103_App1/HardWare/NETWORK/net_wifi.c

112 lines
3.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* net_wifi.c - WiFi 后端(网络层下的通道实现之一)
*
* 组成esp8266.c (ESP-01S AT驱动/TCP透传) + mqtt_client.c (软件MQTT 3.1.1)。
* 连接顺序:硬件复位 → 等已存AP自动连接(20s) → 连固定SSID(60s) →
* Smart Config 智能配网(60s) → 失败返回,由 network.c 切回 4G。
* 运行阶段mqttc_process 解析下行报文30s 心跳保活,
* 断链(CLOSED/心跳超时) 清 ready由 network.c 调度重连或切回 4G。
*/
#include "net_wifi.h"
#include "esp8266.h"
#include "mqtt_client.h"
#include "network.h"
#include "air780e.h" /* bg_delay */
#include "uart.h"
#include "log.h"
#include "stdio.h"
#include "string.h"
volatile uint8_t g_wifi_mqtt_ready = 0;
volatile uint8_t g_wifi_first_publish_ok = 0;
static uint32_t s_ping_tick = 0;
/* 上行发布主题暂存 */
static char s_topic_up[48];
/*==== 阻塞建链:成功返回 0 并置 g_wifi_mqtt_ready ====*/
int net_wifi_init(void)
{
log_info("> WiFi: init...");
g_wifi_mqtt_ready = 0;
g_wifi_first_publish_ok = 0;
esp_gpio_init();
UART4_StartRx();
if (esp_reset() != 0) return -1;
if (esp_send_cmd("AT", "OK", 2000) != 0) return -1;
esp_send_cmd("ATE0", "OK", 1000); /* 关回显,失败不致命 */
if (esp_send_cmd("AT+CWMODE=1", "OK", 2000) != 0) return -1;
/* ① 优先等模块自动连接已保存的APSmartConfig/历史CWJAP保存的
② 失败则连代码里固定的SSID(60s);③ 再失败进SmartConfig(60s) */
if (esp_wait_got_ip(20) != 0) {
if (esp_join_fixed_ap() != 0) {
if (esp_smartconfig() != 0) {
log_warn("> WiFi: all AP attempts failed");
return -1;
}
}
}
/* TCP 透传到 MQTT 服务器 */
if (esp_enter_transparent(MqttInfoStr.ServerIP, MqttInfoStr.ServerPort) != 0) return -1;
/* 软件 MQTT 建链 + 订阅下行主题 */
mqttc_init(MqttInfoStr.ClientID, MqttInfoStr.Username, MqttInfoStr.Passward);
if (mqttc_connect() != 0) return -1;
{
char topic_down[48];
snprintf(topic_down, sizeof(topic_down), "%s%s", MqttInfoStr.Topic, MqttInfoStr.ClientID);
if (mqttc_subscribe(topic_down) != 0) return -1;
snprintf(s_topic_up, sizeof(s_topic_up), "/iot/data/up/%s", MqttInfoStr.ClientID);
}
g_wifi_mqtt_ready = 1;
s_ping_tick = HAL_GetTick();
log_info("> WiFi: Ready");
/* 就绪后上报一次电量,与 4G 就绪行为对齐(同时标记首次发布成功) */
NET_publish_power(1);
return 0;
}
/*==== 非阻塞轮询:下行报文解析 + 心跳保活 ====*/
void net_wifi_process(void)
{
if (!g_wifi_mqtt_ready) return;
int r;
while ((r = mqttc_process()) == 1) { }
if (r == -1) {
log_warn("> WiFi: TCP closed, need reconnect");
g_wifi_mqtt_ready = 0;
return;
}
/* 30s 一次 PINGREQ上一帧 PINGREQ 未收到 PINGRESP 判断链 */
if (HAL_GetTick() - s_ping_tick >= 30000) {
if (g_mqttc_ping_outstanding) {
log_warn("> WiFi: ping timeout, need reconnect");
g_wifi_mqtt_ready = 0;
return;
}
s_ping_tick = HAL_GetTick();
mqttc_ping();
}
}
/*==== 上行发布 ====*/
void net_wifi_publish_up(const char *json)
{
if (!g_wifi_mqtt_ready) return;
if (mqttc_publish(s_topic_up, json) == 0 && !g_wifi_first_publish_ok) {
g_wifi_first_publish_ok = 1;
log_info("> WiFi: first publish ok");
}
}