--[[ @module wifi_sta @summary wifi_sta模块 @version 1.0 @date 2025.10.20 @author 魏健强 @usage 本文为wifi_sta功能模块,核心逻辑为 1、模块连接wifi; 2、连接MQTT服务器并发送消息; 本文件没有对外接口,直接在其他功能模块中require "wifi_sta"就可以加载运行; ]] -- 必须加载sysplus库以支持MQTT _G.sysplus = require("sysplus") -- 测试环境MQTT配置 local dflt_svr_cfg = { ["svr_ip"] = "test-mqtt.cpyypt.cn", ["svr_port"] = 9000, ["svr_usr_name"] = "admin", ["svr_usr_pwd"] = "houjianwei" } -- MQTT客户端实例 local mqttc = nil local pub_topic = "cpyypt/up/test" local sub_topic = {["cpyypt/down/test"] = 0} -- 从fskv读取配置,如果不存在则使用默认配置 local function load_svr_cfg() local cfg = fskv.get("svr_cfg") if not cfg then cfg = dflt_svr_cfg fskv.set("svr_cfg", cfg) log.info("wifi_sta", "使用默认MQTT配置") else log.info("wifi_sta", "从fskv读取MQTT配置") end return cfg end -- wifi的STA相关事件 sys.subscribe("WLAN_STA_INC", function(evt, data) -- evt 可能的值有: "CONNECTED", "DISCONNECTED" -- 当evt=CONNECTED, data是连接的AP的ssid, 字符串类型 -- 当evt=DISCONNECTED, data断开的原因, 整数类型 log.info("收到STA事件", evt, data) end) -- MQTT消息处理函数 local function mqtt_event_handler(mqtt_client, event, data, payload) log.info("mqtt", "event", event, data, payload) if event == "conack" then -- MQTT连接成功 log.info("mqtt", "连接成功") sys.publish("mqtt_conack") -- 订阅主题 mqtt_client:subscribe(sub_topic) -- 发送测试消息 local test_msg = json.encode({ type = "test", timestamp = os.time(), message = "WiFi连接成功,MQTT测试消息" }) mqtt_client:publish(pub_topic, test_msg, 1) log.info("mqtt", "发送测试消息", test_msg) elseif event == "recv" then -- 收到下行消息 log.info("mqtt", "收到消息", "topic", data, "payload", payload) sys.publish("mqtt_payload", data, payload) elseif event == "sent" then log.info("mqtt", "消息发送成功", "pkgid", data) elseif event == "disconnect" then log.info("mqtt", "断开连接") end end -- 连接MQTT服务器 local function connect_mqtt(svr_cfg) log.info("mqtt", "准备连接", svr_cfg["svr_ip"], svr_cfg["svr_port"]) -- 等待WiFi网卡就绪 local is_ready, index = socket.adapter(socket.LWIP_STA) if not is_ready then log.info("mqtt", "WiFi网卡未就绪,等待...") while not socket.adapter(socket.LWIP_STA) do sys.wait(500) end end log.info("mqtt", "WiFi网卡已就绪") -- 创建MQTT客户端 mqttc = mqtt.create(nil, svr_cfg["svr_ip"], svr_cfg["svr_port"], false) -- 设置认证信息 mqttc:auth("wifi_test_client", svr_cfg["svr_usr_name"], svr_cfg["svr_usr_pwd"]) -- 启用自动重连 mqttc:autoreconn(true, 3000) -- 设置事件回调 mqttc:on(mqtt_event_handler) -- 连接服务器 mqttc:connect() -- 等待连接成功 local success = sys.waitUntil("mqtt_conack", 10000) if success then log.info("mqtt", "连接成功") return true else log.info("mqtt", "连接超时") return false end end function test_sta() log.info("执行STA连接操作") -- 连接WiFi wlan.connect("Xiaomi_0D49", "Wbjw2025") -- 等待wifi_sta网络连接成功 while not socket.adapter(socket.LWIP_STA) do sys.waitUntil("IP_READY", 1000) end log.info("wifi", "连接成功", json.encode(wlan.getInfo())) -- 查看当前默认网卡 local current_dft, last_id = socket.dft() log.info("socket", "当前默认网卡:", current_dft, "最后注册网卡:", last_id) log.info("socket", "LWIP_GP(4G)=", socket.LWIP_GP, "LWIP_STA(WiFi)=", socket.LWIP_STA) -- 设置默认网卡为WiFi -- socket.dft(socket.LWIP_STA) -- log.info("socket", "已设置默认网卡为WiFi") -- 再次查看确认 current_dft = socket.dft() log.info("socket", "设置后默认网卡:", current_dft) -- 禁用4G(进入飞行模式),确保socket只能使用WiFi -- local result = mobile.flymode(0, true) -- log.info("wifi", "4G进入飞行模式,确保使用WiFi连接") -- 获取MQTT配置 local svr_cfg = load_svr_cfg() log.info("mqtt", "配置", json.encode(svr_cfg)) -- 同步时间(MQTT需要正确的时间) -- 指定使用WiFi网卡(socket.LWIP_STA)进行NTP同步 log.info("sntp", "开始时间同步,使用WiFi网卡") socket.sntp(nil, socket.LWIP_STA) -- 等待NTP同步完成(最多等待10秒) local ntp_ok = sys.waitUntil("NTP_UPDATE", 10000) if ntp_ok then log.info("sntp", "时间同步成功", os.date()) else log.info("sntp", "时间同步失败或超时") -- 可以选择继续或退出 end -- 连接MQTT服务器 local mqtt_ok = connect_mqtt(svr_cfg) if not mqtt_ok then log.info("mqtt", "连接失败,重试") return end -- 主循环:定时发送心跳消息 while true do local heartbeat_msg = json.encode({ type = "heartbeat", timestamp = os.time(), status = "online" }) if mqttc then mqttc:publish(pub_topic, heartbeat_msg, 1) log.info("mqtt", "发送心跳", heartbeat_msg) end sys.wait(2000) -- 每2秒发送一次心跳 end end function ip_ready_handle(ip, adapter) log.info("ip_ready_handle", ip, adapter) if adapter == socket.LWIP_STA then log.info("wifi sta 链接成功") end end sys.taskInit(test_sta) sys.subscribe("IP_READY", ip_ready_handle) -- 对外接口:发送MQTT消息 function send_mqtt_message(topic, data, qos) if mqttc then return mqttc:publish(topic or pub_topic, data, qos or 1) else log.info("mqtt", "客户端未连接") return nil end end return { send_mqtt_message = send_mqtt_message }