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 struct = require("struct") 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 = 1000 -- 注意:firmware_info.mode = 1 -- 升级模式: 并行升级 由lua脚本自行通过http post等方式推送升级文件给下挂设备,严禁调用send_command()\receive_data()等串行升级接口 -- 并行升级参数可在脚本中定义,也可在扩展参数中获取 local firmware_info = {} local ext_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 print(string.format("success closed fd=%d for pipe '%s'", pipe_info.fd, name)) pipe_info.fd = -1 else print(string.format("fail to close fd=%d for pipe '%s': %s", pipe_info.fd, name, err)) end else print(string.format("Pipe %s %s", name, "already closed (fd=-1)")) 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 65535 then error("随机数范围必须在0-65535之间") end if min > max then min, max = max, min end return math.random(min, max) end -- 生成多个随机数 function RandomGenerator.multiRandom(count, min, max) local results = {} for i = 1, count do results[i] = RandomGenerator.random(min, max) end return results end local function exit_update_result(success, ver, err_code) -- local ver = "v1.2.3" -- 升级成功传入设备版本,若协议不支持版本获取,则为""即可 if success then send_update_success(ver) update_log(LOG_INFO, "Firmware upgrade completed success") else send_update_fail(err_code) update_log(LOG_INFO, "Firmware upgrade failed!!!") end posix.sleep(2) close_pipes(pipes_table) end -- 升级目标 local upg_target = { cur_target = "monitor", -- 当前升级目标(默认:监控) id = 0x10100040, list = { {target = "monitor", id = 0x10100040}, -- 监控 {target = "dsp", id = 0x0D304040}, -- DSP广播 {target = "dsp1", id = 0x0c304040}, -- DSP分支1 {target = "dsp2", id = 0x0C308040}, -- DSP分支2 {target = "dsp3", id = 0x0C30C040} -- DSP分支3 } } local interface = "socket" -- 接口方式 rs485 socket -- 执行升级函数 function perform_upgrade(dev_no, addr, fri_str, ext_str) open_pipes() posix.sleep(1) local err_code = 0 local address = tonumber(addr) local currTime = os.time() update_log(LOG_INFO, string.format("dev_no: %s, addr: %d, fri_str: %s, ext_str: %s", dev_no, addr, fri_str, ext_str)) local obj = cjson.decode(fri_str) if not obj.mode or not obj.num or not obj.info then update_log(LOG_ERR, "Invalid firmware mode or num or info") return end firmware_info.mode = obj.mode -- 0:串行升级 1:并行升级(此参数不使用,固化0) firmware_info.num = obj.num -- 升级文件个数 firmware_info.info = obj.info for i, path in ipairs(firmware_info.info) do update_log(LOG_INFO, string.format("info[%d]: %s", i, path)) end ext_info = cjson.decode(ext_str) if not ext_info then update_log(LOG_ERR, "Invalid extend argv") return end for key, value in pairs(ext_info) do update_log(LOG_INFO, string.format("argv %s: %s %s", key, value, type(value))) end local success = true if ext_info['interface'] and ext_info['target'] then -- what to do? else update_log(LOG_ERR, "Invalid parameter!!!") err_code = INVA_PARAM -- 参数无效 success = false exit_update_result(success, "", err_code) end interface = ext_info.interface for i, v in ipairs(upg_target.list) do if v.target == ext_info.target then upg_target.cur_target = v.target upg_target.id = v.id end end update_log(LOG_INFO, string.format("interface: %s, upgrade target %s id %08X", interface, upg_target.cur_target, upg_target.id)) -- siganl.signal(siganl.SIGKILL, handler) -- siganl.signal(siganl.SIGHUP, handler) ------------------------------------------------------------------------- -- 1. 若需要版本校验,需在升级文件名里包含版本信息,解析升级文件名获取版本信息 -- 2. 获取下挂设备版本信息 --local firmware_version = firmware_info.info[1]:match("SeIbuV.*%-(%d+%.%d+%.%d+%.%d+).*%.bin")--string.match(firmware,'[(Se)|(Auto)]lbuV(%d.%d.%d.%d).bin') --update_log(LOG_INFO, string.format("firmware_version: %s", firmware_version)) -- 3. 对比,若版本一致,则返回success = true,否则进入升级流程 -- update_log(LOG_INFO, "firmware same version,no upgrade") update_log(LOG_INFO, "Starting firmware upgrade process...") indx = 0 -- 升级文件索引,升级第二个固件 indx = 1,以此类推(此变量必须被更新) -- 发包前操作 RandomGenerator.init() local jobid = RandomGenerator.random(1, 32768) local fun_code = 0x41 local block_size = 512 local try_cnt = 5 local fail_cnt = 0 --[[ -- 升级流程::::::::::::::::::: 0xCE:握手 0xB100:下发文件校验信息 0xB101:程序数据下发 0xB102:获取校验结果 0xB103:获取升级进度和状态 0xB104:运行 ]] --[[ 文件下发状态 0-初始化 1-数据包接收正常 2-数据包接收错误 3-升级文件校验 OK 4-升级文件校验失败 ]] local mi = 0 -- 终止升级 0xA7,防止之前有未执行完的升级任务 while (true) do local stop_flag = false while (true) do local data local custom = bpack(">ICC", upg_target.id, 0xA7, 0x00) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) -- SEND send_command(3000, send_frame) mi = mi + 1 local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") -- data pkt bunpack if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _,_,_len = bunpack(rev_frame:sub(3, 4), ">S") _custom = rev_frame:sub(5, 5 +_len-1) end -- update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_result = bunpack(_custom, ">ICC") -- _custom bunpack if _comm_r == 0xC7 then -- 0xC7-正常 fail_cnt = 0 stop_flag = true update_log(LOG_NOTICE, "stop success...") break else update_log(LOG_WARNING, string.format("stop Command ack error: ack code: 0x%02X", _comm_r)) err_code = ABNORMAL_CMD -- 指令返回错误,停止升级失败 success = false exit_update_result(success, "", err_code) return success end else -- 0xC1 update_log(LOG_WARNING, string.format("Not allowed upgrade 0x%02X ", _fun)) err_code = ABNORMAL_FUN -- 不允许升级 success = false exit_update_result(success, "", err_code) return success end else update_log(LOG_WARNING, "Timeout waiting for device response") fail_cnt = fail_cnt + 1 if fail_cnt >= try_cnt then err_code = ACK_ERROR_OR_TIMEOUT success = false exit_update_result(success, "", err_code) return success end end end if stop_flag == true then -- 终止升级成功 break end end time.nanosleep({tv_sec=0, tv_nsec=5*1000*1000*1000}) -- 握手 0xAA while (true) do local handshake_flag = false while (true) do local data local custom = bpack(">ICC", upg_target.id, 0xAA, 0x00) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) -- SEND send_command(3000, send_frame) mi = mi + 1 local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") -- data pkt bunpack if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _,_,_len = bunpack(rev_frame:sub(3, 4), ">S") _custom = rev_frame:sub(5, 5 +_len-1) end -- update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_result = bunpack(_custom, ">ICC") -- _custom bunpack if _comm_r == 0xCC then -- 0xCC-正常 fail_cnt = 0 handshake_flag = true update_log(LOG_INFO, "handshake success, and execute the next step...") break else update_log(LOG_WARNING, string.format("handshake_ Command ack error: ack code: 0x%02X", _comm_r)) err_code = ABNORMAL_CMD -- 指令返回错误,握手失败 success = false exit_update_result(success, "", err_code) return success end else -- 0xC1 update_log(LOG_WARNING, string.format("Not allowed upgrade 0x%02X ", _fun)) err_code = ABNORMAL_FUN -- 不允许升级 success = false exit_update_result(success, "", err_code) return success end else update_log(LOG_WARNING, "Timeout waiting for device response") fail_cnt = fail_cnt + 1 if fail_cnt >= try_cnt then err_code = ACK_ERROR_OR_TIMEOUT success = false exit_update_result(success, "", err_code) return success end end end if handshake_flag == true then -- 握手成功 break end end local file = io.open(firmware_info.info[1], "r") local bin_buf = file:read("*a") local quotient = math.floor(#bin_buf / block_size) local mod = math.fmod(#bin_buf, block_size) -- 取余数 --[[if mod ~= 0 then local pad = 4 - mod for i=1, pad do -- bin_buf = bin_buf .. 0 bin_buf = bpack("AC", bin_buf, 0) end end]] local total_pkt = quotient + ((mod == 0) and 0 or 1) update_log(LOG_WARNING, string.format("total pkt number %d ", total_pkt)) -- 初始化 0xA2 while (true) do local init_flag = false while (true) do local data local custom = bpack(">ICC>S", upg_target.id, 0xA2, 0x00, total_pkt) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) -- SEND send_command(3000, send_frame) mi = mi + 1 local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _,_len = bunpack(rev_frame:sub(3, 4), ">S") _custom = rev_frame:sub(5, 5 +_len-1) end -- update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_result = bunpack(_custom, "= try_cnt then err_code = ACK_ERROR_OR_TIMEOUT success = false exit_update_result(success, "", err_code) return success end end end if init_flag == true then -- 初始化成功,同步数据分包总数 break end end -- 普通报文 send data 0xA3 file:seek("set") local offset = 0 local pktno = 0 local last_progress = 0 -- 程序数据下发 while (true) do if (offset >= #bin_buf) then break end local block_data = string.sub(bin_buf, offset+1, offset+block_size) if not block_data then update_log(LOG_ERR, "read data failed!!!") break end local data local custom = bpack(">ICC>S>S>SA", upg_target.id, 0xA3, 0x00, total_pkt, pktno, #block_data, block_data) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) mi = mi + 1 while (true) do send_command(3000, send_frame) local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _,_len = bunpack(rev_frame:sub(3, 4), "C>S") _custom = rev_frame:sub(5, 5 +_len-1) end -- update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_result = bunpack(_custom, ">ICC") if _comm_r == 0xC3 and _result == 0x01 then -- 0xC3-正常 1-数据包接收正常 offset = offset + #block_data pktno = pktno + 1 -- 包序号 fail_cnt = 0 local progress = math.modf((offset * 100)/#bin_buf) -- 提示发送数据进度 if (progress ~= last_progress) then last_progress = progress send_progress(progress) -- 发送实时进度 update_log(LOG_INFO, string.format("Info Current send progress::::::::::::: %f", progress)) end break else -- 0xF3 update_log(LOG_WARNING, string.format("pkt_ Command ack error: ack code: 0x%02X 0x%02X", _comm_r, _result)) err_code = ABNORMAL_CMD -- 指令返回错误,发包失败 success = false exit_update_result(success, "", err_code) return success end else -- 0xC1 update_log(LOG_WARNING, string.format("Not allowed upgrade 0x%02X ", _fun)) err_code = ABNORMAL_FUN -- 不允许升级 success = false exit_update_result(success, "", err_code) return success end else update_log(LOG_WARNING, "Timeout waiting for device response") fail_cnt = fail_cnt + 1 if (fail_cnt >= try_cnt) then err_code = ACK_ERROR_OR_TIMEOUT success = false exit_update_result(success, "", err_code) return success end end end -- time.nanosleep({tv_sec=0, tv_nsec=50*1000*1000}) -- 每报数据间隔50ms end time.nanosleep({tv_sec=0, tv_nsec=2*1000*1000*1000}) -- 升级文件校验判断 0xA4 while (true) do local check_flag = false while (true) do local data local custom = bpack(">ICC>S>I", upg_target.id, 0xA4, 0x00, 0x00, #bin_buf) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) -- SEND send_command(3000, send_frame) mi = mi + 1 local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _,_len = bunpack(rev_frame:sub(3, 4), "C>S") _custom = rev_frame:sub(5, 5 +_len-1) end -- update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_result = bunpack(_custom, ">ICC") if _comm_r == 0xC4 and _result == 0x03 then fail_cnt = 0 check_flag = true update_log(LOG_INFO, "check success, and execute the next step...") break else -- 0xF4 update_log(LOG_WARNING, string.format("check_ Command ack error: ack code: 0x%02X 0x%02X", _comm_r, _result)) err_code = ABNORMAL_CMD -- 指令返回错误,升级文件校验失败 success = false exit_update_result(success, "", err_code) return success end else -- 0xC1 update_log(LOG_WARNING, string.format("Not allowed upgrade 0x%02X ", _fun)) err_code = ABNORMAL_FUN -- 不允许升级 success = false exit_update_result(success, "", err_code) return success end else update_log(LOG_WARNING, "Timeout waiting for device response") fail_cnt = fail_cnt + 1 if fail_cnt >= try_cnt then err_code = ACK_ERROR_OR_TIMEOUT success = false exit_update_result(success, "", err_code) return success end end end if check_flag == true then -- 升级文件校验成功 break end end -- 执行软件升级 0xA5 while (true) do local exec_flag = false while (true) do local data local custom = bpack(">ICC", upg_target.id, 0xA5, 0x00) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) -- SEND send_command(3000, send_frame) mi = mi + 1 local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _,_len = bunpack(rev_frame:sub(3, 4), ">S") _custom = rev_frame:sub(5, 5 +_len-1) end update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_result = bunpack(_custom, ">ICC") if _comm_r == 0xC5 then fail_cnt = 0 exec_flag = true update_log(LOG_INFO, "exec success, and execute the next step...") break else update_log(LOG_WARNING, string.format("exec_ Command ack error: ack code: 0x%02X", _comm_r)) err_code = ABNORMAL_CMD -- 指令返回错误,执行软件升级失败 success = false exit_update_result(success, "", err_code) return success end else -- 0xC1 update_log(LOG_WARNING, string.format("Not allowed upgrade 0x%02X ", _fun)) err_code = ABNORMAL_FUN -- 不允许升级 success = false exit_update_result(success, "", err_code) return success end else update_log(LOG_WARNING, "Timeout waiting for device response") fail_cnt = fail_cnt + 1 if fail_cnt >= try_cnt then err_code = ACK_ERROR_OR_TIMEOUT success = false exit_update_result(success, "", err_code) return success end end end if exec_flag == true then -- 执行软件升级成功 break end end if upg_target.cur_target ~= "monitor" then -- dsp -- 获取升级进度和状态,默认30分钟超时 while (true) do local data local custom = bpack(">ICC", upg_target.id, 0xA6, 0x00) if (interface == "socket") then local tcp_pkt = bpack("CCA", address, fun_code, custom) local mbap = bpack(">S>S>S", mi, 0x00, #tcp_pkt) -- 仿MODBUS_TCP MABP头 - 事务单元标识符 协议标识符 长度 data = bpack("AA", mbap, tcp_pkt) else local rtu_pkt = bpack("CC>SA", address, fun_code, #custom, custom) local crc = dyutils.CRC16(rtu_pkt, #rtu_pkt) data = bpack("A>S", rtu_pkt, crc) end local send_frame = bpack("A", data) send_command(3000, send_frame) mi = mi + 1 local val, response = receive_data() if response then update_log(LOG_INFO, string.format("receive %d byte", #response)) local rev_frame = response -- 解析 local _,_fun = bunpack((interface == "socket") and rev_frame:sub(8, 8) or rev_frame:sub(2, 2), "C") -- data pkt bunpack if _fun == 0x41 then local _custom if interface == "socket" then _custom = rev_frame:sub(9, -1) else local _, _len = bunpack(rev_frame:sub(3, 4), "C>S") _custom = rev_frame:sub(5, 5 +_len-1) end update_log(LOG_INFO, string.format("_custom data %d byte", #_custom)) local _,_id,_comm_r,_sta,_info,_prog, _speed,_tim = bunpack(_custom:sub(1, 16), ">ICC>I>S>S>S") -- _custom bunpack if _comm_r == 0xC6 then update_log(LOG_INFO, string.format("_progress %.1f%%, _status %d, _speed %d byte/s", _prog * 0.1, _sta, _speed)) if _sta == 25 then update_log(LOG_INFO, "ota success...") break elseif _sta == 24 then update_log(LOG_INFO, "ota failed") err_code = 430 -- 升级失败 success = false exit_update_result(success, "", err_code) return success end else update_log(LOG_WARNING, string.format("_progress Command ack error: ack code: 0x%02X", _comm_r)) err_code = ABNORMAL_CMD -- 指令返回错误,获取升级进度和状态 失败 success = false exit_update_result(success, "", err_code) return success end else -- 0xC1 update_log(LOG_WARNING, string.format("Not allowed upgrade 0x%02X ", _fun)) err_code = ABNORMAL_FUN -- 不允许升级 success = false exit_update_result(success, "", err_code) return success end end time.nanosleep({tv_sec=0, tv_nsec=2*1000*1000*1000}) -- 间隔2秒,获取一次升级进度 end end local ver = "" -- 升级成功传入设备版本,若协议不支持版本获取,则为""即可 exit_update_result(success, ver, err_code) --mysem:close() return success end local SIGTERM = 15 -- 允许进程在退出前执行清理操作(如关闭文件、释放资源),替代 kill -9 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)