| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- --- 模块功能:远程升级.
- -- @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
|