-- cmd.lua -- 功能:解析串口帧,调用 linksocket 接口,执行系统命令 local log = require "log" local sys = require "sys" local uart = require "uart" local ril = require "ril" local linksocket = require "linksocket" local uartID = 1 -- 辅助函数:字节转十六进制(调试用) local function toHexcode(str) if not str then return "" end local hex = "" for i = 1, #str do hex = hex .. string.format("%02X", str:byte(i)) end return hex end -- 发送通用响应帧:55 AA mainCmd subCmd [payload] AA 55 local function sendCmdResponse(mainCmd, subCmd, payload) local frame = string.char(0x55, 0xAA, mainCmd, subCmd) if payload and #payload > 0 then frame = frame .. payload end frame = frame .. string.char(0xAA, 0x55) uart.write(uartID, frame) log.debug("sendCmdResponse: mainCmd=", string.format("0x%02X", mainCmd), "subCmd=", string.format("0x%02X", subCmd)) end -- 发送通用响应帧:55 AA 83 subCmd socketId status AA 55 local function sendResponse(subCmd, socketId, status) sendCmdResponse(0x83, subCmd, string.char(socketId, status or 0)) log.debug("Response: subCmd=", subCmd, "socketId=", socketId, "status=", status) end -- 命令处理函数 --------------------------------------------------------------- -- 0x01: 数据发送到指定Socket local function handleCmd01(subCmd, payload) local socketId = subCmd if socketId < 1 or socketId > 6 then log.error("Invalid socket id in cmd 0x01:", socketId) sendResponse(0x03, socketId, 1) return end local success = linksocket.sendToSocket(socketId, payload) if not success then log.warn("Send failed, socket", socketId, "not connected") sendResponse(0x03, socketId, 1) else log.info("Data sent to socket", socketId, "len=", #payload) end end -- 0x02: 系统重启 local function handleCmd02() log.info("System restart command received") sys.restart() end -- 0x03: Socket连接/断开控制 -- subCmd: 0x01=连接 0x02=断开 -- payload: socket_id (1字节) local function handleCmd03(subCmd, payload) if #payload < 1 then return end local socketId = payload:byte(1) if socketId < 1 or socketId > 6 then log.error("Cmd 0x03 invalid socket:", socketId) return end if subCmd == 0x01 then log.info("STM32 request connect socket", socketId) linksocket.connectSocket(socketId) elseif subCmd == 0x02 then log.info("STM32 request disconnect socket", socketId) linksocket.disconnectSocket(socketId) else log.error("Unknown subCmd for 0x03:", subCmd) end end -- 0x04: 设置服务器地址 -- payload: ip_len(1) + ip_str(ip_len) + port_hi(1) + port_lo(1) local function handleCmd04(subCmd, payload) if #payload < 3 then log.error("Cmd 0x04 payload too short") sendCmdResponse(0x87, 0x00, string.char(1)) return end local ip_len = payload:byte(1) if ip_len > 100 or #payload < (2 + ip_len + 1) then log.error("Cmd 0x04 invalid ip_len") sendCmdResponse(0x87, 0x00, string.char(1)) return end local ip_str = payload:sub(2, 1 + ip_len) local port_hi = payload:byte(2 + ip_len) local port_lo = payload:byte(3 + ip_len) local port = port_hi * 256 + port_lo log.info("Set server address:", ip_str, port) local ok = linksocket.setServerAddress(ip_str, port) if ok then sendCmdResponse(0x87, 0x00, string.char(0)) else sendCmdResponse(0x87, 0x00, string.char(1)) end end -- 0x05: 查询SIM卡信息 -- subCmd: 0x01=ICCID 0x02=IMSI 0x03=IMEI local function handleCmd05(subCmd) local at_cmds = { [0x01] = "AT+ICCID", [0x02] = "AT+CIMI", [0x03] = "AT+CGSN", } local at_cmd = at_cmds[subCmd] if not at_cmd then log.error("Unknown SIM query type:", string.format("0x%02X", subCmd)) return end ril.request(at_cmd, nil, function(cmd, result, respdata, interdata) -- interdata才是实际的AT命令响应数据,result只是布尔值表示成功/失败 local response = interdata or "" -- 去除可能的空白字符 response = response:gsub("^[\r\n]+", ""):gsub("[\r\n]+$", "") local value = "" if subCmd == 0x01 then value = string.match(response, "%+ICCID:%s*(%S+)") or string.match(response, "ICCID:%s*(%S+)") or response:match("^(%S+)") or "" elseif subCmd == 0x02 then value = string.match(response, "%+CIMI:%s*(%S+)") or string.match(response, "CIMI:%s*(%S+)") or response:match("^(%S+)") or "" elseif subCmd == 0x03 then value = string.match(response, "%+CGSN:%s*(%S+)") or string.match(response, "CGSN:%s*(%S+)") or response:match("^(%S+)") or "" end value = value or "" log.info("SIM query result type=", string.format("0x%02X", subCmd), "value=", value) local data = string.char(#value) .. value sendCmdResponse(0x84, subCmd, data) end) end -- 0x06: 查询信号强度(CSQ) local function handleCmd06() ril.request("AT+CSQ", nil, function(cmd, result) local csq = 0 local ber = 99 -- result可能是布尔值,需要确保是字符串才能进行模式匹配 if result and type(result) == "string" then local c, b = string.match(result, "CSQ:%s*(%d+),%s*(%d+)") if c then csq = tonumber(c) or 0 end if b then ber = tonumber(b) or 99 end end log.info("Signal query: CSQ=", csq, "BER=", ber) sendCmdResponse(0x85, 0x01, string.char(csq, ber)) end) end -- 0x07: 查询链路状态 local function handleCmd07() local status = linksocket.getLinkStatus() if status then local payload = "" for i = 1, 6 do payload = payload .. string.char(status[i] and 1 or 0) end sendCmdResponse(0x86, 0x01, payload) log.info("Link status sent, 6 sockets") end end local frameBuffer = "" -- 对外接口:处理串口接收到的原始数据 local function process(rawData) if not rawData or #rawData < 1 then return end frameBuffer = frameBuffer .. rawData while true do if #frameBuffer < 7 then break end if frameBuffer:byte(1) == 0x55 and frameBuffer:byte(2) == 0xAA then local tail = frameBuffer:find(string.char(0xAA, 0x55), 5, true) if not tail then break end tail = tail + 1 local frame = frameBuffer:sub(1, tail) frameBuffer = frameBuffer:sub(tail + 1) log.info("CMD raw data:", toHexcode(frame)) local mainCmd = frame:byte(3) local subCmd = frame:byte(4) local payload = frame:sub(5, -3) if mainCmd == 0x01 then handleCmd01(subCmd, payload) elseif mainCmd == 0x02 then handleCmd02() elseif mainCmd == 0x03 then handleCmd03(subCmd, payload) elseif mainCmd == 0x04 then handleCmd04(subCmd, payload) elseif mainCmd == 0x05 then handleCmd05(subCmd) elseif mainCmd == 0x06 then handleCmd06() elseif mainCmd == 0x07 then handleCmd07() else log.warn("Unknown main command:", string.format("0x%02X", mainCmd)) end else local skip = frameBuffer:find(string.char(0x55, 0xAA), 2, true) if skip then log.warn("Skipped", skip - 1, "bytes before frame header") frameBuffer = frameBuffer:sub(skip) else frameBuffer = "" break end end end end -- 模块接口 local M = { process = process, } return M