wifi_sta.lua 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. --[[
  2. @module wifi_sta
  3. @summary wifi_sta模块
  4. @version 1.0
  5. @date 2025.10.20
  6. @author 魏健强
  7. @usage 本文为wifi_sta功能模块,核心逻辑为
  8. 1、模块连接wifi;
  9. 2、连接MQTT服务器并发送消息;
  10. 本文件没有对外接口,直接在其他功能模块中require "wifi_sta"就可以加载运行;
  11. ]]
  12. -- 必须加载sysplus库以支持MQTT
  13. _G.sysplus = require("sysplus")
  14. -- 测试环境MQTT配置
  15. local dflt_svr_cfg = {
  16. ["svr_ip"] = "test-mqtt.cpyypt.cn",
  17. ["svr_port"] = 9000,
  18. ["svr_usr_name"] = "admin",
  19. ["svr_usr_pwd"] = "houjianwei"
  20. }
  21. -- MQTT客户端实例
  22. local mqttc = nil
  23. local pub_topic = "cpyypt/up/test"
  24. local sub_topic = {["cpyypt/down/test"] = 0}
  25. -- 从fskv读取配置,如果不存在则使用默认配置
  26. local function load_svr_cfg()
  27. local cfg = fskv.get("svr_cfg")
  28. if not cfg then
  29. cfg = dflt_svr_cfg
  30. fskv.set("svr_cfg", cfg)
  31. log.info("wifi_sta", "使用默认MQTT配置")
  32. else
  33. log.info("wifi_sta", "从fskv读取MQTT配置")
  34. end
  35. return cfg
  36. end
  37. -- wifi的STA相关事件
  38. sys.subscribe("WLAN_STA_INC", function(evt, data)
  39. -- evt 可能的值有: "CONNECTED", "DISCONNECTED"
  40. -- 当evt=CONNECTED, data是连接的AP的ssid, 字符串类型
  41. -- 当evt=DISCONNECTED, data断开的原因, 整数类型
  42. log.info("收到STA事件", evt, data)
  43. end)
  44. -- MQTT消息处理函数
  45. local function mqtt_event_handler(mqtt_client, event, data, payload)
  46. log.info("mqtt", "event", event, data, payload)
  47. if event == "conack" then
  48. -- MQTT连接成功
  49. log.info("mqtt", "连接成功")
  50. sys.publish("mqtt_conack")
  51. -- 订阅主题
  52. mqtt_client:subscribe(sub_topic)
  53. -- 发送测试消息
  54. local test_msg = json.encode({
  55. type = "test",
  56. timestamp = os.time(),
  57. message = "WiFi连接成功,MQTT测试消息"
  58. })
  59. mqtt_client:publish(pub_topic, test_msg, 1)
  60. log.info("mqtt", "发送测试消息", test_msg)
  61. elseif event == "recv" then
  62. -- 收到下行消息
  63. log.info("mqtt", "收到消息", "topic", data, "payload", payload)
  64. sys.publish("mqtt_payload", data, payload)
  65. elseif event == "sent" then
  66. log.info("mqtt", "消息发送成功", "pkgid", data)
  67. elseif event == "disconnect" then
  68. log.info("mqtt", "断开连接")
  69. end
  70. end
  71. -- 连接MQTT服务器
  72. local function connect_mqtt(svr_cfg)
  73. log.info("mqtt", "准备连接", svr_cfg["svr_ip"], svr_cfg["svr_port"])
  74. -- 等待WiFi网卡就绪
  75. local is_ready, index = socket.adapter(socket.LWIP_STA)
  76. if not is_ready then
  77. log.info("mqtt", "WiFi网卡未就绪,等待...")
  78. while not socket.adapter(socket.LWIP_STA) do
  79. sys.wait(500)
  80. end
  81. end
  82. log.info("mqtt", "WiFi网卡已就绪")
  83. -- 创建MQTT客户端
  84. mqttc = mqtt.create(nil, svr_cfg["svr_ip"], svr_cfg["svr_port"], false)
  85. -- 设置认证信息
  86. mqttc:auth("wifi_test_client", svr_cfg["svr_usr_name"], svr_cfg["svr_usr_pwd"])
  87. -- 启用自动重连
  88. mqttc:autoreconn(true, 3000)
  89. -- 设置事件回调
  90. mqttc:on(mqtt_event_handler)
  91. -- 连接服务器
  92. mqttc:connect()
  93. -- 等待连接成功
  94. local success = sys.waitUntil("mqtt_conack", 10000)
  95. if success then
  96. log.info("mqtt", "连接成功")
  97. return true
  98. else
  99. log.info("mqtt", "连接超时")
  100. return false
  101. end
  102. end
  103. function test_sta()
  104. log.info("执行STA连接操作")
  105. -- 连接WiFi
  106. wlan.connect("Xiaomi_0D49", "Wbjw2025")
  107. -- 等待wifi_sta网络连接成功
  108. while not socket.adapter(socket.LWIP_STA) do
  109. sys.waitUntil("IP_READY", 1000)
  110. end
  111. log.info("wifi", "连接成功", json.encode(wlan.getInfo()))
  112. -- 查看当前默认网卡
  113. local current_dft, last_id = socket.dft()
  114. log.info("socket", "当前默认网卡:", current_dft, "最后注册网卡:", last_id)
  115. log.info("socket", "LWIP_GP(4G)=", socket.LWIP_GP, "LWIP_STA(WiFi)=", socket.LWIP_STA)
  116. -- 设置默认网卡为WiFi
  117. -- socket.dft(socket.LWIP_STA)
  118. -- log.info("socket", "已设置默认网卡为WiFi")
  119. -- 再次查看确认
  120. current_dft = socket.dft()
  121. log.info("socket", "设置后默认网卡:", current_dft)
  122. -- 禁用4G(进入飞行模式),确保socket只能使用WiFi
  123. -- local result = mobile.flymode(0, true)
  124. -- log.info("wifi", "4G进入飞行模式,确保使用WiFi连接")
  125. -- 获取MQTT配置
  126. local svr_cfg = load_svr_cfg()
  127. log.info("mqtt", "配置", json.encode(svr_cfg))
  128. -- 同步时间(MQTT需要正确的时间)
  129. -- 指定使用WiFi网卡(socket.LWIP_STA)进行NTP同步
  130. log.info("sntp", "开始时间同步,使用WiFi网卡")
  131. socket.sntp(nil, socket.LWIP_STA)
  132. -- 等待NTP同步完成(最多等待10秒)
  133. local ntp_ok = sys.waitUntil("NTP_UPDATE", 10000)
  134. if ntp_ok then
  135. log.info("sntp", "时间同步成功", os.date())
  136. else
  137. log.info("sntp", "时间同步失败或超时")
  138. -- 可以选择继续或退出
  139. end
  140. -- 连接MQTT服务器
  141. local mqtt_ok = connect_mqtt(svr_cfg)
  142. if not mqtt_ok then
  143. log.info("mqtt", "连接失败,重试")
  144. return
  145. end
  146. -- 主循环:定时发送心跳消息
  147. while true do
  148. local heartbeat_msg = json.encode({
  149. type = "heartbeat",
  150. timestamp = os.time(),
  151. status = "online"
  152. })
  153. if mqttc then
  154. mqttc:publish(pub_topic, heartbeat_msg, 1)
  155. log.info("mqtt", "发送心跳", heartbeat_msg)
  156. end
  157. sys.wait(2000) -- 每2秒发送一次心跳
  158. end
  159. end
  160. function ip_ready_handle(ip, adapter)
  161. log.info("ip_ready_handle", ip, adapter)
  162. if adapter == socket.LWIP_STA then
  163. log.info("wifi sta 链接成功")
  164. end
  165. end
  166. sys.taskInit(test_sta)
  167. sys.subscribe("IP_READY", ip_ready_handle)
  168. -- 对外接口:发送MQTT消息
  169. function send_mqtt_message(topic, data, qos)
  170. if mqttc then
  171. return mqttc:publish(topic or pub_topic, data, qos or 1)
  172. else
  173. log.info("mqtt", "客户端未连接")
  174. return nil
  175. end
  176. end
  177. return {
  178. send_mqtt_message = send_mqtt_message
  179. }