Files
mobile_comm/luatos/air780epm/module/Air780EPM/demo/websocket/websocket_main.lua
T
wangfq 173dd6874f init: Air780EPM 官方 LuatOS 项目代码基线
- 来源: 合宙 LuatOS 官方仓库 air780epm 模块完整代码
- 路径: luatos/air780epm/module/Air780EPM/demo 含官方 demo(含 mqtt/mqtts/socket/uart 等)
- 后续: 基于 demo 开发 UART<->MQTT 数据上报功能
2026-08-31 08:53:49 +08:00

198 lines
8.7 KiB
Lua
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.
--[[
@module websocket_main
@summary WebSocket client 主应用功能模块
@version 1.2
@date 2025.08.24
@author 陈媛媛
@usage
本文件为WebSocket client 主应用功能模块,核心业务逻辑为:
1、创建一个WebSocket client,连接server
2、处理连接/异常逻辑,出现异常后执行重连动作;
3、调用websocket_receiver的外部接口websocket_receiver.proc,对接收到的数据进行处理;
4、调用sys.sendMsg接口,发送"CONNECT OK"和"DISCONNECTED"两种类型的"WEBSOCKET_EVENT"消息到websocket_sender的task,控制数据发送逻辑;
5、收到WebSocket数据后,执行sys.publish("FEED_NETWORK_WATCHDOG") 对网络环境检测看门狗功能模块进行喂狗;
本文件没有对外接口,直接在main.lua中require "websocket_main"就可以加载运行;
]]
-- 加载WebSocket client数据接收功能模块
local websocket_receiver = require "websocket_receiver"
-- 加载WebSocket client数据发送功能模块
local websocket_sender = require "websocket_sender"
-- WebSocket服务器地址和端口
-- 这里使用的地址和端口,会不定期重启或维护,仅能用作测试用途,不可商用,说不定哪一天就关闭了
-- 用户开发项目时,替换为自己的商用服务器地址和端口
-- 加密TCP链接 wss 表示加密
local SERVER_URL = "wss://wstest.luatos.com/ws/echo"
-- 这是另外一个测试服务, 能响应websocket的二进制帧
--local SERVER_URL = "ws://wstest.luatos.com/ws/echo2"
-- websocket_main的任务名
local TASK_NAME = websocket_sender.TASK_NAME_PREFIX.."main"
-- WebSocket client的事件回调函数
local function websocket_client_event_cbfunc(ws_client, event, data, fin, opcode)
log.info("WebSocket事件回调", ws_client, event, data, fin, opcode)
-- WebSocket连接成功
if event == "conack" then
sys.sendMsg(TASK_NAME, "WEBSOCKET_EVENT", "CONNECT", true)
-- 连接成功,通知网络环境检测看门狗功能模块进行喂狗
sys.publish("FEED_NETWORK_WATCHDOG")
-- 接收到服务器下发的数据
-- data:string类型,表示接收到的数据
-- fin:number类型,1表示是最后一个数据包,0表示还有后续数据包
-- opcodenumber类型,表示数据包类型(1-文本,2-二进制)
elseif event == "recv" then
-- 对接收到的数据处理
websocket_receiver.proc(data, fin, opcode)
-- 发送成功数据
-- data:number类型,表示发送状态(通常为nil或0)
elseif event == "sent" then
log.info("WebSocket事件回调", "数据发送成功,发送确认")
-- 发送消息通知 websocket sender task
sys.sendMsg(websocket_sender.TASK_NAME, "WEBSOCKET_EVENT", "SEND_OK", data)
-- 服务器断开WebSocket连接
elseif event == "disconnect" then
-- 发送消息通知 websocket main task
sys.sendMsg(TASK_NAME, "WEBSOCKET_EVENT", "DISCONNECTED", false)
-- 严重异常,本地会主动断开连接
-- data:string类型,表示具体的异常,有以下几种:
-- "connect"tcp连接失败
-- "tx":数据发送失败
-- "rx":数据接收失败(解析错误等)
-- "other":其他异常
elseif event == "error" then
log.error("WebSocket错误", "错误类型:", data)
if data == "connect" then
-- 发送消息通知 websocket main task,连接失败
sys.sendMsg(TASK_NAME, "WEBSOCKET_EVENT", "CONNECT", false)
elseif data == "tx" or data == "rx" or data == "other" then
-- 发送消息通知 websocket main task,出现异常
sys.sendMsg(TASK_NAME, "WEBSOCKET_EVENT", "ERROR")
else
-- 处理未知错误类型
log.error("WebSocket错误", "未知错误类型:", data)
sys.sendMsg(TASK_NAME, "WEBSOCKET_EVENT", "ERROR")
end
end
end
-- websocket main task 的任务处理函数
local function websocket_client_main_task_func()
local ws_client
local result, msg
while true do
-- 如果当前时间点设置的默认网卡还没有连接成功,一直在这里循环等待
while not socket.adapter(socket.dft()) do
log.warn("WebSocket主任务", "等待网络就绪", socket.dft())
-- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
-- 或者等待1秒超时退出阻塞等待状态;
-- 注意:此处的1000毫秒超时不要修改的更长;
-- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
-- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
-- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
sys.waitUntil("IP_READY", 1000)
end
-- 检测到了IP_READY消息
log.info("WebSocket主任务", "收到网络就绪消息", socket.dft())
-- 清空此task绑定的消息队列中的未处理的消息
sys.cleanMsg(TASK_NAME)
-- 创建WebSocket client对象
ws_client = websocket.create(nil, SERVER_URL)
-- 如果创建WebSocket client对象失败
if not ws_client then
log.error("WebSocket主任务", "WebSocket创建失败")
goto EXCEPTION_PROC
end
-- 设置自定义请求头
--如果有需要,根据自己的实际需求,在此处配置请求头并打开注释。
--if ws_client.headers then
--ws_client:headers({Auth="Basic ABCDEGG"})
--end
-- 注册WebSocket client对象的事件回调函数
ws_client:on(websocket_client_event_cbfunc)
-- 连接server
result = ws_client:connect()
-- 如果连接server失败
if not result then
log.error("WebSocket主任务", "WebSocket连接失败")
goto EXCEPTION_PROC
end
-- 连接、断开连接、异常等各种事件的处理调度逻辑
while true do
-- 等待"WEBSOCKET_EVENT"消息
msg = sys.waitMsg(TASK_NAME, "WEBSOCKET_EVENT")
log.info("WebSocket主任务等待消息", msg[2], msg[3], msg[4])
-- connect连接结果
-- msg[3]表示连接结果,true为连接成功,false为连接失败
if msg[2] == "CONNECT" then
-- WebSocket连接成功
if msg[3] then
log.info("WebSocket主任务", "连接成功")
-- 通知websocket sender数据发送应用模块的taskWebSocket连接成功
sys.sendMsg(websocket_sender.TASK_NAME, "WEBSOCKET_EVENT", "CONNECT_OK", ws_client)
-- WebSocket连接失败
else
log.info("WebSocket主任务", "连接失败")
-- 退出循环,发起重连
break
end
-- 需要主动关闭WebSocket连接
-- 用户需要主动关闭WebSocket连接时,可以调用sys.sendMsg(TASK_NAME, "WEBSOCKET_EVENT", "CLOSE")
elseif msg[2] == "CLOSE" then
-- 主动断开WebSocket client连接
ws_client:disconnect()
-- 发送disconnect之后,此处延时1秒,给数据发送预留一点儿时间
sys.wait(1000)
break
-- 被动关闭了WebSocket连接
-- 被网络或者服务器断开了连接
elseif msg[2] == "DISCONNECTED" then
break
-- 出现了其他异常
elseif msg[2] == "ERROR" then
break
end
end
-- 出现异常
::EXCEPTION_PROC::
-- 清空此task绑定的消息队列中的未处理的消息
sys.cleanMsg(TASK_NAME)
-- 通知websocket sender数据发送应用模块的taskWebSocket连接已经断开
sys.sendMsg(websocket_sender.TASK_NAME, "WEBSOCKET_EVENT", "DISCONNECTED")
-- 如果存在WebSocket client对象
if ws_client then
-- 关闭WebSocket client,并且释放WebSocket client对象
ws_client:close()
ws_client = nil
end
-- 5秒后跳转到循环体开始位置,自动发起重连(与MQTT保持一致)
sys.wait(5000)
end
end
--创建并且启动一个task
sys.taskInitEx(websocket_client_main_task_func, TASK_NAME)