1. 文件概览
WSS.lua 是一个用于 WebSocket 通信的 Lua 模块,主要实现了与云服务的 WebSocket 连接、认证、消息订阅和发布等功能,支持设备在线状态管理和数据传输。
2. 核心功能
2.1 WebSocket 连接管理
ws.open()- 打开 WebSocket 连接- 功能:重新启动 WebSocket 服务
- 实现:创建连接任务
ws.close()- 关闭 WebSocket 连接- 功能:关闭 WebSocket 连接,用于切换卡时关闭连接
- 实现:调用
wsc:close()关闭连接并清空引用
ws.link(wssURL)- 连接 WebSocket 服务器- 功能:使用获取的 URL 连接 WebSocket 服务器
- 参数:
wssURL- 包含 WebSocket 连接地址的对象 - 实现:创建 WebSocket 实例,设置回调函数,处理各种事件
2.2 用户认证与令牌管理
ws.login()- 用户登录/注册- 功能:校验令牌是否过期,过期则登录或注册
- 流程:
- 检查令牌是否过期(临过期5小时重新登录)
- 未过期则直接返回成功
- 过期则使用 IMEI 和设备唯一 ID 登录
- 登录失败(用户不存在)则注册新用户
- 存储返回的令牌和过期时间
ws.get_ws_url(userInfo)- 获取 WebSocket 连接地址- 功能:根据用户令牌获取动态 WebSocket 连接地址
- 参数:
userInfo- 包含用户令牌的用户信息 - 实现:调用云函数 API 获取签名后的 WebSocket URL
2.3 消息订阅与发布
ws.subscribe(groupId, will)- 订阅主题- 功能:订阅指定的消息主题
- 参数:
groupId- 主题 ID,如 "imei"..mobile.imei().."/dl"will- 遗嘱消息标志- 实现:发送订阅消息,等待发送确认
ws.unsubscribe(groupId)- 取消订阅- 功能:取消订阅指定的消息主题
- 参数:
groupId- 主题 ID - 实现:发送取消订阅消息,等待发送确认
ws.publish(groupId, content)- 发布消息- 功能:向指定主题发布消息
- 参数:
groupId- 主题 IDcontent- 消息内容,包含设备信息和数据- 实现:发送发布消息,等待发送确认
2.4 消息处理
ws.proc(data, fin, opcode)- 处理接收到的消息- 功能:处理从服务器接收到的 WebSocket 消息
- 参数:
data- 接收到的数据fin- 是否为最后一个数据包opcode- 数据包类型
3. 技术架构
3.1 数据结构
register_data- 设备注册数据结构- 包含设备 ID、通道、URL、客户端信息等
- 用于设备首次连接时的注册
message_data- 消息数据结构- 包含设备 ID、通道、URL、令牌、消息类型、主题 ID、内容等
- 用于订阅、取消订阅和发布消息
3.2 事件处理机制
- WebSocket 事件回调:
conack- 连接成功事件recv- 接收消息事件sent- 发送成功事件disconnect- 断开连接事件error- 错误事件
3.3 认证流程
- 令牌校验:检查存储的令牌是否过期
- 登录:令牌过期则使用 IMEI 和设备唯一 ID 登录
- 注册:登录失败(用户不存在)则注册新用户
- 获取 WebSocket URL:使用令牌获取签名后的 WebSocket 连接地址
- 连接 WebSocket:使用获取的 URL 连接服务器
- 注册设备:连接成功后发送设备注册消息
3.4 重连机制
- 自动重连:在断开连接或连接错误时,自动创建新的连接任务
- 发送确认:所有消息发送都等待确认,确保消息可靠传输
4. 代码结构
-- 模块定义
local ws = {}
local wsc = nil
local connect_state = false
-- 数据结构定义
register_data = { ... }
message_data = { ... }
-- 函数定义
function ws.close() ... end
function ws.open() ... end
function ws.login() ... end
function ws.get_ws_url(userInfo) ... end
function ws.link(wssURL) ... end
function ws.subscribe(groupId, will) ... end
function ws.unsubscribe(groupId) ... end
function ws.publish(groupId, content) ... end
function ws.proc(data, fin, opcode) ... end
5. 关键实现细节
5.1 令牌管理
- 令牌存储:使用
fskv.set("userInfo", user)存储用户信息和令牌 - 令牌校验:通过比较令牌过期时间和当前时间(加5小时缓冲)判断是否需要重新登录
- 令牌使用:在获取 WebSocket URL 和发送消息时使用令牌进行认证
5.2 WebSocket 事件处理
- 连接成功:发送设备注册消息,通知网络看门狗
- 接收消息:调用
ws.proc()处理消息,通知网络看门狗 - 发送成功:更新 LCD 显示,通知网络看门狗,发布发送成功事件
- 断开连接:设置连接状态为 false,创建新的连接任务
- 错误处理:根据错误类型进行处理,连接错误时创建新的连接任务
5.3 消息发送机制
- 异步发送:所有消息发送都在独立任务中执行
- 发送确认:使用
sys.waitUntil("WSC_SEND_OK", 20000)等待发送确认 - 重试机制:发送失败时会重试,直到发送成功
5.4 设备标识
- 用户名:使用 "imei"..mobile.imei() 作为用户名
- 密码:使用 string.toHex(mcu.unique_id()) 作为密码
- 设备 ID:使用 mobile.imei() 作为设备 ID
6. 代码优化建议
6.1 结构优化
- 模块封装:
- 将模块变量(如
wsc、connect_state)封装在模块内部,避免全局变量 - 使用
local关键字声明所有局部变量,提高代码安全性
- 错误处理增强:
- 增加更详细的错误处理和日志记录
- 对网络请求失败的情况进行更细致的处理
- 代码复用:
- 提取登录和注册中的重复代码
- 统一消息发送逻辑,减少重复代码
6.2 功能优化
- 重连机制:
- 实现指数退避重连策略,避免频繁重连导致服务器压力
- 添加重连次数限制,防止无限重连
- 心跳机制:
- 实现客户端心跳发送,确保连接稳定
- 处理服务器心跳响应,及时检测连接状态
- 消息队列:
- 实现消息队列,在连接断开时缓存消息,连接恢复后重新发送
- 对消息进行优先级排序,确保重要消息优先发送
6.3 代码质量
- 注释完善:
- 为所有函数添加详细的注释
- 说明参数含义、返回值和使用场景
- 命名规范:
- 统一变量和函数命名规范
- 使用更有描述性的变量名和函数名
- 代码风格:
- 统一缩进和代码格式
- 避免过长的函数和复杂的嵌套结构
- 安全性:
- 对敏感信息(如密码)进行加密处理
- 验证所有输入参数,防止注入攻击
7. 总结
WSS.lua 是一个功能完整的 WebSocket 通信模块,主要特点包括:
- 完整的认证流程:支持令牌校验、登录、注册和动态 WebSocket URL 获取
- 可靠的消息传递:实现了消息发送确认和重试机制
- 自动重连:在连接断开时自动尝试重连
- 消息订阅/发布:支持主题订阅、取消订阅和消息发布
- 设备在线管理:通过 WebSocket 连接状态管理设备在线状态
该模块设计合理,代码结构清晰,功能完整,能够满足设备与云服务之间的实时通信需求。通过进一步的优化和扩展,可以使其更加健壮和灵活。
8. 技术亮点
- 安全认证:使用 IMEI 和设备唯一 ID 进行认证,确保设备身份安全
- 动态 URL:通过云函数获取签名后的 WebSocket URL,提高连接安全性
- 事件驱动:基于事件的 WebSocket 处理机制,结构清晰
- 异步处理:使用任务进行异步消息处理,提高系统响应速度
- 看门狗集成:与网络环境检测看门狗功能模块集成,确保网络连接稳定
- 遗嘱消息:支持遗嘱消息,在设备异常断开时通知服务器
- LCD 反馈:在消息发送成功时更新 LCD 显示,提供用户反馈
这些技术特点使得该模块在 IoT 设备与云服务的通信中具有较高的实用价值和参考意义。
9. 应用场景
- IoT 设备远程监控:通过 WebSocket 实时传输设备状态和传感器数据
- 远程控制:接收云端下发的控制指令,实现设备远程控制
- 设备管理:管理设备在线状态,支持设备分组和批量操作
- 数据采集:定期采集设备数据并上传到云端进行分析
- 固件升级:通过 WebSocket 接收固件升级通知和数据
该模块可以广泛应用于各种需要与云端进行实时通信的 IoT 设备场景,如智能仪表、工业设备、智能家居等。