local posix = require('posix') local time = require('posix.time') local siganl = require('posix.signal') --local sem = require('posix.sem') local bit = require('bit') local cjson = require('cjson') local base64 = require('base64') local dyutils = require('dyutils') local lpack = require('lua_pack') local band, bor, bxor, bnot = bit.band, bit.bor, bit.bxor, bit.bnot local lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol local bpack = string.pack local bunpack = string.unpack local TIMEOUT_MS = 3000 -- 注意:firmware_info.mode = 1 -- 升级模式: 并行升级 由lua脚本自行通过http post等方式推送升级文件给下挂设备,严禁调用send_command()\receive_data()等串行升级接口 -- 并行升级参数可在脚本中定义,也可在扩展参数中获取 local firmware_info = {} local extend_info = nil -- log Level local LOG_EMERG = 0 --/* system is unusable */ local LOG_ALERT = 1 --/* action must be taken immediately */ local LOG_CRIT = 2 --/* critical conditions */ local LOG_ERR = 3 --/* error conditions */ local LOG_WARNING = 4 --/* warning conditions */ local LOG_NOTICE = 5 --/* normal but significant condition */ local LOG_INFO = 6 --/* informational */ local LOG_DEBUG = 7 --/* debug-level messages */ local pipes_table = { ["command"] = {fd = -1, path = "/tmp/command"}, -- Lua → C ["response"] = {fd = -1, path = "/tmp/response"},-- C → Lua ["progress"] = {fd = -1, path = "/tmp/progress"},-- Lua → C ["log"] = {fd = -1, path = "/tmp/log"}, -- Lua → C } --local mysem, err = sem.open("/otasem") local function open_pipes() local flags = bor(posix.O_RDONLY, posix.O_NONBLOCK) pipes_table["command"].fd = posix.open(pipes_table["command"].path, posix.O_WRONLY) pipes_table["progress"].fd = posix.open(pipes_table["progress"].path, posix.O_WRONLY) pipes_table["log"].fd = posix.open(pipes_table["log"].path, posix.O_WRONLY) pipes_table["response"].fd = posix.open(pipes_table["response"].path, flags) end local update_log local function close_pipes(pipes) for name, pipe_info in pairs(pipes) do if pipe_info.fd ~= -1 then local ok, err = pcall(posix.close, pipe_info.fd) if ok then pipe_info.fd = -1 update_log(LOG_INFO, string.format("success closed fd=%d for pipe '%s'", pipe_info.fd, name)) else update_log(LOG_ERR, string.format("fail to close fd=%d for pipe '%s': %s", pipe_info.fd, name, err)) end end end end -- 接收C返回LUA的响应帧(带超时时间ms,返回0 此帧无应答 返回 1 正常解析数据) local function receive_data() local fd_Id = pipes_table["response"].fd if fd_Id == -1 then update_log(LOG_ERR, "fd_Id is -1 (already closed)") return -1, nil end local fds = { [fd_Id] = { events = { IN = true, -- 数据可读 HUP = true, -- 挂断事件 ERR = true -- 错误事件 } } } local poll = require 'posix.poll' local ret = poll.poll(fds, TIMEOUT_MS) if ret == 0 then update_log(LOG_INFO, "timeout, no data received") return 0, nil elseif ret == -1 then update_log(LOG_WARNING, "poll call failed, reason: " .. tostring(posix.errno())) return -1, nil else for fd in pairs(fds) do if fds[fd].revents.IN then local data, err = posix.read(fd, 1024) if data then --update_log(LOG_INFO, string.format("RX[%d]: %s", #data, string.toHex(data," "))) return 1, data else return -1, nil end elseif fds[fd].revents.HUP then update_log(LOG_ERR, "pipe closed (HUP)") posix.close(fd) -- 关闭 fd fd = -1 -- 标记为已关闭 pipes_table["response"].fd = -1 return -2, nil elseif fds[fd].revents.ERR then update_log(LOG_ERR, "pipe error (ERR)") posix.close(fd) fd = -1 pipes_table["response"].fd = -1 return -3, nil end end end end -- 发送命令/固件包 --(每包数据可指定超时时间) local function send_command(timeout_ms, data) --mysem:wait() local block_pkt = bpack("C posix.signal(posix.SIGTERM, function(sig) print(string.format("[signal %d] received the termination request, cleanup...", sig)) close_pipes(pipes_table) os.exit(128 + SIGTERM) end) local ok, err = pcall(perform_upgrade, arg[1], arg[2], arg[3], arg[4]) if not ok then print("Fatal error: " .. tostring(err)) -- print to stdout,提示lua语法错误/崩溃信息 ---语、运行时法错误错误、或主动调用的 error() close_pipes(pipes_table) os.exit(1) end os.exit(0)