Files
BR_YKC/4G/code/lib/update.lua
2026-03-31 15:46:04 +08:00

230 lines
9.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 update
-- @author openLuat
-- @license MIT
-- @copyright openLuat
-- @release 2018.03.29
require "misc"
require "http"
require "log"
require "common"
module(..., package.seeall)
local sUpdating,sCbFnc,sUrl,sPeriod,sRedir,sLocation,fotastart
local sProcessedLen = 0
--local sBraekTest = 0
local httpRspCode
local sGetImeiFnc,sDownloadProcessFnc
local updateMsg
local otaBegin
local function httpDownloadCbFnc(result,statusCode,head)
log.info("update.httpDownloadCbFnc",result,statusCode,head,sCbFnc,sPeriod)
sys.publish("UPDATE_DOWNLOAD",result,statusCode,head)
end
local function processOta(stepData,totalLen,statusCode)
if stepData and totalLen then
if statusCode=="200" or statusCode=="206" then
if not otaBegin then sys.publish("LIB_UPDATE_OTA_DOWNLOAD_BEGIN") otaBegin=true end
local fotaProcessStatus=rtos.fota_process((sProcessedLen+stepData:len()>totalLen) and stepData:sub(1,totalLen-sProcessedLen) or stepData,totalLen)
if fotaProcessStatus~=0 then
log.error("update.processOta","fail",fotaProcessStatus,"failFotaProcessStatus")
log.error("update.processOta","get_fs_free_size: ",rtos.get_fs_free_size()," Bytes")
sys.publish("LIB_UPDATE_OTA_DOWNLOAD_END",false)
return false
else
sProcessedLen = sProcessedLen + stepData:len()
if sDownloadProcessFnc then sDownloadProcessFnc(sProcessedLen*100/totalLen) end
log.info("update.processOta",totalLen,sProcessedLen,(sProcessedLen*100/totalLen).."%")
--if sProcessedLen*100/totalLen==sBraekTest then return false end
if sProcessedLen*100/totalLen>=100 then sys.publish("LIB_UPDATE_OTA_DOWNLOAD_END",true) return true end
end
elseif statusCode:sub(1,1)~="3" and stepData:len()==totalLen and totalLen>0 then
if totalLen<=200 then
local msg = stepData:match("\"msg\":%s*\"(.-)\"")
if msg and msg:len()<=200 then
updateMsg = common.ucs2beToUtf8((msg:gsub("\\u","")):fromHex())
log.warn("update.error",updateMsg)
end
end
httpRspCode = stepData:match("\"code\":%s*(%d+)")
end
end
end
function clientTask()
sUpdating = true
--不要省略此处代码否则下文中的misc.getImei有可能获取不到
while not socket.isReady() do sys.waitUntil("IP_READY_IND") end
while true do
local retryCnt = 0
sProcessedLen = 0
otaBegin = false
updateMsg = nil
while true do
--sBraekTest = sBraekTest+30
log.info("update.http.request",sLocation,sUrl,sProcessedLen,sBraekTest,fotastart)
if not fotastart then break end
local coreVer = rtos.get_version()
local coreName1,coreName2 = coreVer:match("(.-)_V%d+(_.+)")
local coreVersion = tonumber(coreVer:match(".-_V(%d+)"))
httpRspCode = nil
-- 合宙云平台升级地址
local iotURL="iot.openluat.com/api/site/firmware_upgrade"
-- 模块信息
local moduleInfo="?project_key=".._G.PRODUCT_KEY
.."&imei="..(sGetImeiFnc and sGetImeiFnc() or misc.getImei())
.."&firmware_name=".._G.PROJECT.."_"..coreName1..coreName2
.."&core_version="..coreVersion
.."&dfota=1&version=".._G.VERSION..(sRedir and "&need_oss_url=1" or "")
-- 如果自定义升级地址前三位为“###”,则不拼接模块信息
if sUrl and string.sub(sUrl,1,3)=="###" then
log.info("1-3",string.sub(sUrl,1,3))
log.info("3-0",string.sub(sUrl,4))
customizeUrl=string.sub(sUrl,4)
elseif sUrl then
customizeUrl=sUrl..moduleInfo
else
-- 默认向合宙云平台地址拼接模块信息
iotURL=iotURL..moduleInfo
end
http.request("GET",
sLocation or (customizeUrl or iotURL),
nil,{["Range"]="bytes="..sProcessedLen.."-"},nil,60000,httpDownloadCbFnc,processOta)
local _,result,statusCode,head = sys.waitUntil("UPDATE_DOWNLOAD")
log.info("update.waitUntil UPDATE_DOWNLOAD",result,statusCode,httpRspCode)
if result then
local needBreak
if statusCode=="200" or statusCode=="206" then
needBreak = true
local check = rtos.fota_end()
log.info("update.rtos.fota_end", check)
if sCbFnc then
if check == 0 then
sCbFnc(true)
else
sCbFnc(false)
end
else
if check == 0 then
sys.restart("UPDATE_DOWNLOAD_SUCCESS")
end
end
elseif statusCode:sub(1,1)=="3" and head and head["Location"] then
sLocation = head["Location"]
sys.wait(2000)
elseif httpRspCode=="43" then
log.info("update.clientTask","wait server create fota")
sys.wait(30000)
else
log.info("update.rtos.fota_end",rtos.fota_end())
if sCbFnc then sCbFnc(false) end
needBreak = true
end
if needBreak then
break
end
else
retryCnt = retryCnt+1
if retryCnt==30 then
rtos.fota_end()
if sCbFnc then sCbFnc(false) end
break
end
end
end
sProcessedLen = 0
if sPeriod then
sys.wait(sPeriod)
if rtos.fota_start()~=0 then
log.error("update.request","fota_start fail")
fotastart = false
else
fotastart = true
end
else
break
end
end
sUpdating = false
end
--- 启动远程升级功能
-- @function[opt=nil] cbFnc 每次执行远程升级功能后的回调函数,回调函数的调用形式为:
-- cbFnc(result)result为true表示升级包下载成功其余表示下载失败
--如果没有设置此参数,则升级包下载成功后,会自动重启
-- @string[opt=nil] url 使用http的get命令下载升级包的url如果没有设置此参数默认使用Luatiot平台的url
-- 如果用户设置了url注意仅传入完整url的前半部分(如果有参数,即传入?前一部分)http.lua会自动添加?以及后面的参数,例如:
-- 设置的url="www.userserver.com/api/site/firmware_upgrade"则http.lua会在此url后面补充下面的参数
-- "?project_key=".._G.PRODUCT_KEY
-- .."&imei="..misc.getimei()
-- .."&device_key="..misc.getsn()
-- .."&firmware_name=".._G.PROJECT.."_"..rtos.get_version().."&version=".._G.VERSION
-- 如果用户设置了url且url前面增加三个井号"###",http.lua会自动忽略"###"并以用户填入的url作为请求地址不会自动添加模块信息例如
-- 设置的url="###www.userserver.com"/api/site/firmware_upgrade?customparam=test",则http.lua会将此url开头的"###"忽略,并以此url为地址进行请求
-- "www.userserver.com"/api/site/firmware_upgrade?customparam=test"
-- 如果redir设置为true还会补充.."&need_oss_url=1"
-- @number[opt=nil] period 单位毫秒,定时启动远程升级功能的间隔,如果没有设置此参数,仅执行一次远程升级功能
-- @bool[opt=nil] redir 是否访问重定向到阿里云的升级包使用Luat提供的升级服务器时此参数才有意义
-- 为了缓解Luat的升级服务器压力从2018年7月11日起在iot.openluat.com新增或者修改升级包的升级配置时升级文件会备份一份到阿里云服务器
-- 如果此参数设置为true会从阿里云服务器下载升级包如果此参数设置为false或者nil仍然从Luat的升级服务器下载升级包
-- @return nil
-- @usage
-- update.request()
-- update.request(cbFnc)
-- update.request(cbFnc,"www.userserver.com/update")
-- update.request(cbFnc,nil,4*3600*1000)
-- update.request(cbFnc,nil,4*3600*1000,true)
function request(cbFnc,url,period,redir)
if rtos.fota_start()~=0 then
log.error("update.request","fota_start fail")
fotastart = false
return
else
fotastart = true
end
sCbFnc,sUrl,sPeriod,sRedir = cbFnc or sCbFnc,url or sUrl,period or sPeriod,sRedir or redir
log.info("update.request",sCbFnc,sUrl,sPeriod,sRedir)
if not sUpdating then
sys.taskInit(clientTask)
end
end
function setGetImeiCbFnc(cbFnc)
sGetImeiFnc = cbFnc
end
--- 设置升级包下载过程中的下载进度通知回调函数
-- @function cbFnc 下载进度通知回调函数,回调函数的调用形式如下:
-- cbFnc(step)
-- step表示下载进度取值范围是0到100下载进度更新很快建议在回调函数中每隔5或者10执行一次实际动作
-- @return nil
-- @usage update.setDownloadProcessCbFnc(function(step) end)
function setDownloadProcessCbFnc(cbFnc)
sDownloadProcessFnc = cbFnc
end
--- 获取请求升级包时服务器返回的信息
-- @return updateMsg, 若没有请求升级或服务器未返回相关信息则返回值为nil否则返回服务器返回的相关信息
-- @usage local msg = getUpdateMsg()
function getUpdateMsg()
return updateMsg
end