| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- --[[
- @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
- }
|