#include "network.h" #include "air780e.h" #include "led.h" #include "log.h" #include "main.h" #include "stdio.h" #include "string.h" volatile uint8_t g_net_mqtt_ready = 0; volatile uint8_t g_net_first_publish_ok = 0; /* 网络发送互斥标志:OTA 下载等 AT 交互期间置位 */ volatile uint8_t g_net_tx_busy = 0; /* 4G 无 SIM 卡标志:由 air780e.c 在初始化失败时设置 */ volatile uint8_t g_no_sim_detected = 0; void NET_init(void) { g_net_mqtt_ready = 0; g_net_first_publish_ok = 0; g_no_sim_detected = 0; air780e_init(); if (g_no_sim_detected) { log_warn("> 4G no SIM, please insert SIM card"); /* 不再回退到 WiFi,4G 无 SIM 时持续等待用户插卡 */ } g_net_mqtt_ready = g_air780e_mqtt_ready; } void NET_process(void) { static uint32_t no_sim_retry_tick = 0; static uint16_t no_sim_retry_count = 0; /* 网络未就绪时自动重试 */ if (!g_air780e_mqtt_ready) { if (g_no_sim_detected) { /* 检测到无 SIM 卡:每隔 10s 重新初始化一次, 用户插卡后可自动恢复;超过 20 次(约 3min)仍无卡则复位 */ if (no_sim_retry_tick == 0 || (HAL_GetTick() - no_sim_retry_tick) >= 10000) { no_sim_retry_tick = HAL_GetTick(); no_sim_retry_count++; log_warn("> NET: no SIM detected, retry init %d/20", no_sim_retry_count); g_no_sim_detected = 0; air780e_init(); if (!g_no_sim_detected) { log_info("> NET: SIM card OK or network recovered"); no_sim_retry_count = 0; } else if (no_sim_retry_count >= 20) { log_error("> NET: no SIM for 3min, system reset"); HAL_Delay(100); NVIC_SystemReset(); } } } else { /* 其他原因未就绪,由 air780e_init 内部已经会复位; 这里清零计数,避免后续误触发 */ no_sim_retry_tick = 0; no_sim_retry_count = 0; } } else { no_sim_retry_tick = 0; no_sim_retry_count = 0; } air780e_process(); g_net_mqtt_ready = g_air780e_mqtt_ready; g_net_first_publish_ok = g_air780e_first_publish_ok; } void NET_publish_status(int feeding, int sw2, int sw3, int sw4, float weight_kg, float once_wt_kg, float zero_kg) { if (g_net_tx_busy) { log_info("> NET: status dropped (tx busy)"); return; } /* 云平台字段映射与参考代码字面相反:weight 显示为“空载重量”,zero 显示为“剩余料重” */ /* ver 字段:固件版本号,平台据此可识别设备是否发生了 OTA 回退 */ CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22ver\\22:%u,\\22weight\\22:%.1f,\\22onceWt\\22:%.1f,\\22zero\\22:%.1f,\\22feeding\\22:%d,\\22sw2\\22:%d,\\22sw3\\22:%d,\\22sw4\\22:%d}}\"", MqttInfoStr.ClientID, (unsigned)MqttInfoStr.Ver, zero_kg, once_wt_kg, weight_kg, feeding, sw2, sw3, sw4); } void NET_publish_response(const char *cmd_id, int ok, const char *msg) { if (g_net_tx_busy) { log_info("> NET: response dropped (tx busy)"); return; } const char *text = msg ? msg : (ok ? "OK" : "command failed"); CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22id\\22:\\22%s\\22,\\22code\\22:0,\\22message\\22:\\22%s\\22}\"", MqttInfoStr.ClientID, cmd_id, text); } /* 上报电量状态: on=1 正常, on=0 低电量 */ void NET_publish_power(int on) { if (g_net_tx_busy) { log_info("> NET: power dropped (tx busy)"); return; } CAT1_printf("AT+MPUB=\"/iot/data/up/%s\",0,0,\"{\\22header\\22:\\22iot.prop.post\\22,\\22body\\22:{\\22pow\\22:%d}}\"", MqttInfoStr.ClientID, on ? 1 : 0); } void NET_mqtt_report(const char *header, const char *ota_id, int val) { if (g_net_tx_busy) { log_info("> NET: report dropped (tx busy)"); return; } air780e_mqtt_report(header, ota_id, val); } void NET_ota_confirm(void) { air780e_ota_confirm(); }