Files
BR_YKC/4G/tools/resource/soc_script/v2025.12.31.22/lib/libfota2.lua
2026-03-31 15:46:04 +08:00

220 lines
8.8 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--[[
@module libfota2
@summary fota升级v2
@version 1.1
@date 2024.11.22
@author wendal/HH
@demo fota2
@usage
--用法实例
local libfota2 = require("libfota2")
-- 功能:获取fota的回调函数
-- 参数:
-- result:number类型
-- 0表示成功
-- 1表示连接失败
-- 2表示url错误
-- 3表示服务器断开
-- 4表示接收报文错误
-- 5表示使用iot平台VERSION需要使用 xxx.yyy.zzz形式
function libfota_cb(result)
log.info("fota", "result", result)
-- fota成功
if result == 0 then
rtos.reboot() --如果还有其他事情要做,自行决定reboot的时机
end
end
--下方示例为合宙iot平台,地址:http://iot.openluat.com
libfota2.request(libfota_cb)
--如使用自建服务器,自行更换url
-- 对自定义服务器的要求是:
-- 若需要升级, 响应http 200, body为升级文件的内容
-- 若不需要升级, 响应300或以上的代码,务必注意
local opts = {url="http://xxxxxx.com/xxx/upgrade"}
-- opts的详细说明, 看后面的函数API文档
libfota2.request(libfota_cb, opts)
-- 若需要定时升级
-- 合宙iot平台
sys.timerLoopStart(libfota2.request, 4*3600*1000, libfota_cb)
-- 自建平台
sys.timerLoopStart(libfota2.request, 4*3600*1000, libfota_cb, opts)
]]
local sys = require "sys"
require "sysplus"
local libfota2 = {}
-- 单独判断下服务器下发的数据是不是"{"开头"}"结尾的字符串
local function isjson(str)
local start, _ = string.find(str, "^%{")
local _, end_ = string.find(str, "%}$")
return start == 1 and end_ == #str and string.sub(str, 2, #str - 1):find("%B{") == nil
end
local function fota_task(cbFnc, opts)
local ret = 0
local url = opts.url
local code, headers, body = http.request(opts.method, opts.url, opts.headers, opts.body, opts, opts.server_cert,
opts.client_cert, opts.client_key, opts.client_password).wait()
-- log.info("http fota", code, headers, body)
if code == 200 or code == 206 then
if body == 0 then
ret = 4
else
ret = 0
end
elseif code == -4 then
ret = 1
elseif code == -5 then
ret = 3
else
log.info("libfota2", code, body)
ret = 4
local hziot = "iot.openluat.com"
local msg, json_body, result
if string.find(url, hziot) then
log.info("使用合宙服务器,接下来解析body里的code")
json_body, result = json.decode(body)
-- 如果json解析失败证明服务器下发的不是json
if result == 1 and isjson(body) then
code = json_body["code"]
else
-- 这个值随便取的,只要不和其他定义重复就行
code = 1111111111111
end
if code == 43 then
log.info("请等待",
",云平台生成差分升级包需要等待,一到三分钟后云平台生成完成差分包便可以请求成功")
elseif code == 3 then
log.info("无效的设备", "检查请求键名(imei小写)正确性")
elseif code == 17 then
log.info("无权限",
"设备会上报imei、固件名、项目key,服务器会以此查出设备、固件、项目三 条记录,如果 这三者不在同一个用户名下就会认为无权限。设备不在项目key对应的账户下可寻找合宙技术支持查询该设备在哪个账户下核实情况后可修改设备归属")
elseif code == 21 then
log.info("不允许升级", "请检查IOT平台,是否对应imei被禁止了升级")
elseif code == 25 then
log.info("无效的项目",
"productkey不一致,检查是否存在拼写错误,检查模块是否在本人账户下,若不在本人账户下,请联系合宙工作人员处理")
elseif code == 26 then
log.info("无效的固件",
"固件名称错误,项目中没有对应的固件,也有可能是用户自己修改了固件名称,可对照升级日志中设备当前固件名与升级配置中固件名是否相同(固件名称,固件功能要完全一致,只是版本号不同)")
elseif code == 27 then
log.info("已是最新版本",
"1.设备的固件/脚本版本高于或等于云平台上的版本号 2.用户项目升级配置中未添加该设备 3.云平台升级配置中,是否升级配置为否")
elseif code == 40 then
log.info("循环升级",
"云平台进入设备列表搜索被禁止的imei,解除禁止升级即可. 云平台防止模块在升级失败后,反复请求升级导致流量卡流量耗尽,在模块一天请求升级六次后会禁止模块升级. 可在平台解除")
elseif code == 1111111111111 then
log.info("云平台下发的不是json", "我看看body是个什么东西", type(body), body)
else
log.info("不是上面的那些错误code", code)
end
end
end
cbFnc(ret)
end
--[[
fota升级
@api libfota2.request(cbFnc, opts)
@function cbFnc 用户回调函数回调函数的调用形式为cbFnc(result) , 必须传
@table fota参数, 后面有详细描述
@return nil 无返回值
@usaga
-- opts参数说明, 所有参数都是可选的
-- 1. opts.url string 升级所需要的URL, 若使用合宙iot平台,则不需要填
-- 2. opts.version string 版本号, 默认是 BSP版本号.x.z格式
-- 3. opts.timeout int 请求超时时间, 默认300000毫秒,单位毫秒
-- 4. opts.project_key string 合宙IOT平台的项目key, 默认取全局变量PRODUCT_KEY. 自建服务器不用填
-- 5. opts.imei string 设备识别码, 默认取IMEI(Cat.1模块)或WLAN MAC地址(wifi模块)或MCU唯一ID
-- 6. opts.firmware_name string 固件名称,默认是 _G.PROJECT.. "_LuatOS-SoC_" .. rtos.bsp()
-- 7. opts.server_cert string 服务器证书, 默认不使用
-- 8. opts.client_cert string 客户端证书, 默认不使用
-- 9. opts.client_key string 客户端私钥, 默认不使用
-- 10. opts.client_password string 客户端私钥口令, 默认不使用
-- 11. opts.method string 请求方法, 默认是GET
-- 12. opts.headers table 额外添加的请求头,默认不需要
-- 13. opts.body string 额外添加的请求body,默认不需要
]]
function libfota2.request(cbFnc, opts)
if not opts then
opts = {}
end
if fota then
opts.fota = true
else
os.remove("/update.bin")
opts.dst = "/update.bin"
end
if not cbFnc then
cbFnc = function(ret)
end
end
-- 处理URL
if not opts.url then
opts.url = "http://iot.openluat.com/api/site/firmware_upgrade?"
end
local query = ""
if opts.url:sub(1, 3) ~= "###" and not opts.url_done then
-- 补齐project_key函数
if not opts.project_key then
opts.project_key = _G.PRODUCT_KEY
if not opts.project_key then
log.error("libfota2", "iot.openluat.com need PRODUCT_KEY!!!")
cbFnc(5)
return
end
end
-- 补齐version参数
if not opts.version then
local x, y, z = string.match(_G.VERSION, "(%d+).(%d+).(%d+)")
opts.version = rtos.version():sub(2) .. "." .. x .. "." .. z
end
-- 补齐firmware_name参数
if not opts.firmware_name then
opts.firmware_name = _G.PROJECT .. "_LuatOS-SoC_" .. rtos.bsp()
end
-- 补齐imei参数
if not opts.imei then
if mobile then
query = "imei=" .. mobile.imei()
elseif wlan and wlan.getMac then
query = "mac=" .. wlan.getMac()
else
query = "uid=" .. mcu.unique_id():toHex()
end
end
-- 然后拼接到最终的url里
if not opts.imei then
opts.url = string.format("%s%s&project_key=%s&firmware_name=%s&version=%s", opts.url, query, opts.project_key, opts.firmware_name, opts.version)
else
opts.url = string.format("%simei=%s&project_key=%s&firmware_name=%s&version=%s", opts.url, opts.imei, opts.project_key, opts.firmware_name, opts.version)
end
else
if opts.url:sub(1,3)=="###" then
opts.url = opts.url:sub(4)
end
end
opts.url_done = true
-- 处理method
if not opts.method then
opts.method = "GET"
end
log.info("libfota2.url", opts.method, opts.url)
log.info("libfota2.imei/mac/uid", query)
log.info("libfota2.project_key", opts.project_key)
log.info("libfota2.firmware_name", opts.firmware_name)
log.info("libfota2.version", opts.version)
sys.taskInit(fota_task, cbFnc, opts)
end
return libfota2