--[[ @module frame_parser @summary 0x7F 帧解析状态机(Lua 版 lup_feed_byte) @version 0.1 @date 2026.08.31 @usage 解析 vd960DBN 经 UART1 转发的 0x7F 帧(Loop 地感协议),只切包不懂内容: - 帧格式: [7F][Addr][LEN][CMD][Value: LEN-1B][XOR][SUM] - LEN = 1 + data_len(含 CMD 字节) - 校验: XOR + SUM,从 Addr 起(不含 magic 0x7F),与 DBN↔Loop 完全一致 - 状态机: IDLE → HEADER(Addr/LEN/CMD) → VALUE(LEN-1B) → CHECK(XOR/SUM) → COMPLETE - 完整帧通过回调 on_frame(cmd, payload) 交付;校验失败/超长帧回 IDLE 丢弃 用法: local fp = require "frame_parser" fp.init(function(cmd, payload) -- cmd: 命令码(number) -- payload: 除 CMD 外的数据字节(string, 可为空) end) -- UART 收到字节流逐字节喂入: fp.feed(string.byte(s, i)) ]] local frame_parser = {} -- 状态 local ST_IDLE, ST_ADDR, ST_LEN, ST_CMD, ST_VALUE, ST_CHECK_X, ST_CHECK_S = 0, 1, 2, 3, 4, 5, 6 -- 常量(与 DLD960Loop 协议一致) local MAGIC_0x7F = 0x7F local MAX_FRAME_VALUE = 64 -- 协议约定 Value 上限(防御) local state = ST_IDLE local cmd = 0 local value_len = 0 -- LEN - 1(除 CMD 外的数据字节数) local value_buf = "" -- 数据缓冲 local chk_xor = 0 -- 从 Addr 起累计 local chk_sum = 0 local on_frame = nil -- 回调 local function reset() state = ST_IDLE cmd = 0 value_len = 0 value_buf = "" chk_xor = 0 chk_sum = 0 end -- 完整帧校验通过 → 回调 local function complete() if on_frame then on_frame(cmd, value_buf) end reset() end -- 逐字节喂入 function frame_parser.feed(b) if state == ST_IDLE then if b == MAGIC_0x7F then state = ST_ADDR end elseif state == ST_ADDR then chk_xor = b chk_sum = b state = ST_LEN elseif state == ST_LEN then chk_xor = chk_xor ~ b chk_sum = (chk_sum + b) % 256 if b < 1 then reset() -- LEN=0 非法 else value_len = b - 1 -- 减 CMD 字节 if value_len > MAX_FRAME_VALUE then reset() -- 超长帧丢弃 else value_buf = "" state = ST_CMD end end elseif state == ST_CMD then chk_xor = chk_xor ~ b chk_sum = (chk_sum + b) % 256 cmd = b if value_len == 0 then state = ST_CHECK_X else state = ST_VALUE end elseif state == ST_VALUE then chk_xor = chk_xor ~ b chk_sum = (chk_sum + b) % 256 value_buf = value_buf .. string.char(b) if value_buf:len() >= value_len then state = ST_CHECK_X end elseif state == ST_CHECK_X then if b ~= chk_xor then reset() else state = ST_CHECK_S end elseif state == ST_CHECK_S then if b == chk_sum then complete() else reset() end end end -- 初始化回调 function frame_parser.init(cb) on_frame = cb reset() end -- 复位(链路异常/切换时调用) function frame_parser.reset() reset() end return frame_parser