|
|
@@ -48,12 +48,27 @@ sys.timerLoopStart(libfota.request, 4*3600*1000, libfota_cb, "http://xxxxxx.com/
|
|
|
|
|
|
local sys = require "sys"
|
|
|
local sysplus = require "sysplus"
|
|
|
+local libnet = require "libnet"
|
|
|
|
|
|
local libfota = {}
|
|
|
|
|
|
+local taskName = "OTA_TASK"
|
|
|
+local tag = "fota"
|
|
|
|
|
|
-local function fota_task(cbFnc,storge_location, len, param1,ota_url,ota_port,libfota_timeout,server_cert, client_cert, client_key, client_password)
|
|
|
- -- fota.init(storge_location, len, param1)
|
|
|
+local function netCB(msg)
|
|
|
+ if msg[1] == socket.EVENT then
|
|
|
+ --log.info(tag, "socket网络状态变更")
|
|
|
+ elseif msg[1] == socket.TX_OK then
|
|
|
+ log.info(tag, "socket发送完成")
|
|
|
+ elseif msg[1] == socket.EV_NW_RESULT_CLOSE then
|
|
|
+ log.info(tag, "socket关闭")
|
|
|
+ else
|
|
|
+ log.info(tag, "未处理消息", msg[1], msg[2], msg[3], msg[4])
|
|
|
+ end
|
|
|
+end
|
|
|
+
|
|
|
+local function fota_task(cbFnc,storge_location, len, param1,ota_url,ota_port,timeout,tls,server_cert, client_cert, client_key, client_password)
|
|
|
+ fota.init(storge_location, len, param1)
|
|
|
if cbFnc == nil then
|
|
|
cbFnc = function() end
|
|
|
end
|
|
|
@@ -77,42 +92,200 @@ local function fota_task(cbFnc,storge_location, len, param1,ota_url,ota_port,lib
|
|
|
end
|
|
|
end
|
|
|
end
|
|
|
- local ret
|
|
|
- if server_cert then
|
|
|
-
|
|
|
+
|
|
|
+ local succ, param, ip, port, total, findhead, filelen, rcvCache,d1,d2,statusCode,retry,rspHead,rcvChunked,done,fotaDone,nCache
|
|
|
+ local tbuff = zbuff.create(512)
|
|
|
+ local rbuff = zbuff.create(4096)
|
|
|
+ local netc = socket.create(nil, taskName)
|
|
|
+ local tls_get = false
|
|
|
+ if ota_url:sub(1,5) == "https" then
|
|
|
+ tls_get = true
|
|
|
end
|
|
|
- local code, headers, body = http.request("GET", ota_url, nil, nil, {fota=true,timeout = libfota_timeout},server_cert, client_cert, client_key, client_password).wait()
|
|
|
- -- log.info("http.get", code, headers, body)
|
|
|
- if code == 200 then
|
|
|
- ret = 0
|
|
|
- elseif code == -4 then
|
|
|
- ret = 1
|
|
|
- elseif code == -5 then
|
|
|
- ret = 3
|
|
|
- else
|
|
|
- ret = 4
|
|
|
+ socket.config(netc, nil, nil, tls or tls_get,server_cert, client_cert, client_key, client_password)
|
|
|
+ filelen = 0
|
|
|
+ total = 0
|
|
|
+ retry = 0
|
|
|
+ done = false
|
|
|
+ rspHead = {}
|
|
|
+ local ret = 1
|
|
|
+ local result = libnet.waitLink(taskName, 0, netc)
|
|
|
+
|
|
|
+ local type,host,uri
|
|
|
+ if ota_url then
|
|
|
+ type,host,uri = string.match(ota_url,"(%a-)://(%S-)/(%S+)")
|
|
|
+ end
|
|
|
+ while retry < 3 and not done do
|
|
|
+ local version
|
|
|
+ if type == nil or host == nil then
|
|
|
+ cbFnc(2)
|
|
|
+ return
|
|
|
+ end
|
|
|
+
|
|
|
+ if ota_port == nil then
|
|
|
+ local url_host,url_port = string.match(host,"(%g+):(%d+)")
|
|
|
+ if url_port then
|
|
|
+ ota_port = url_port
|
|
|
+ host = url_host
|
|
|
+ elseif type == "http" then
|
|
|
+ ota_port = 80
|
|
|
+ elseif type == "https" then
|
|
|
+ ota_port = 443
|
|
|
+ end
|
|
|
+ end
|
|
|
+
|
|
|
+ result = libnet.connect(taskName, 30000, netc, host, ota_port) --后续出了http库则直接用http来处理
|
|
|
+ tbuff:del()
|
|
|
+ tbuff:copy(0, "GET /"..uri.."" .. " HTTP/1.1\r\n")
|
|
|
+ tbuff:copy(nil,"Host: "..host..":"..ota_port.."\r\n")
|
|
|
+ if filelen > 0 then --断网重连的话,只需要下载剩余的部分就行了
|
|
|
+ tbuff:copy(nil,"Range: bytes=" .. total .. "-\r\n")
|
|
|
+ end
|
|
|
+
|
|
|
+ tbuff:copy(nil,"Accept: application/octet-stream\r\n\r\n")
|
|
|
+ log.info(tbuff:query())
|
|
|
+ result = libnet.tx(taskName, 5000, netc, tbuff)
|
|
|
+ rbuff:del()
|
|
|
+ findhead = false
|
|
|
+ while result do
|
|
|
+ succ, param, ip, port = socket.rx(netc, rbuff)
|
|
|
+ if not succ then
|
|
|
+ log.info(tag, "服务器断开了", succ, param, ip, port)
|
|
|
+ ret = 3
|
|
|
+ break
|
|
|
+ end
|
|
|
+ if rbuff:used() > 0 then
|
|
|
+ if findhead then
|
|
|
+ succ,fotaDone,nCache = fota.run(rbuff)
|
|
|
+ if succ then
|
|
|
+ total = total + rbuff:used()
|
|
|
+ else
|
|
|
+ log.error(tag, "写入异常,请至少在1秒后重试")
|
|
|
+ fota.finish(false)
|
|
|
+ done = true
|
|
|
+ break
|
|
|
+ end
|
|
|
+ log.info(tag, "收到服务器数据,长度", rbuff:used(), "fota结果", succ, done, "总共", filelen)
|
|
|
+ rbuff:del()
|
|
|
+ if fotaDone then
|
|
|
+ log.info(tag, "下载完成")
|
|
|
+ while true do
|
|
|
+ succ,fotaDone = fota.isDone()
|
|
|
+ if fotaDone then
|
|
|
+ fota.finish(true)
|
|
|
+ log.info(tag, "FOTA完成")
|
|
|
+ done = true
|
|
|
+ ret = 0
|
|
|
+ break
|
|
|
+ end
|
|
|
+ sys.wait(100)
|
|
|
+ end
|
|
|
+ break
|
|
|
+ end
|
|
|
+ else
|
|
|
+ rcvCache = rbuff:query()
|
|
|
+ d1,d2 = rcvCache:find("\r\n\r\n")
|
|
|
+ -- 打印出http response head
|
|
|
+ -- log.info(rcvCache:sub(1, d2))
|
|
|
+ if d2 then
|
|
|
+ --状态行
|
|
|
+ _,d1,statusCode = rcvCache:find("%s(%d+)%s.-\r\n")
|
|
|
+ if not statusCode then
|
|
|
+ log.info(tag, "http没有状态返回")
|
|
|
+ ret = 4
|
|
|
+ break
|
|
|
+ end
|
|
|
+ statusCode = tonumber(statusCode)
|
|
|
+ if statusCode ~= 200 and statusCode ~= 206 then
|
|
|
+ log.info(tag, "http应答不OK", statusCode,rbuff:toStr(d2))
|
|
|
+ done = true
|
|
|
+ ret = 4
|
|
|
+ break
|
|
|
+ end
|
|
|
+ --应答头
|
|
|
+ for k,v in string.gmatch(rcvCache:sub(d1+1,d2-2),"(.-):%s*(.-)\r\n") do
|
|
|
+ rspHead[k] = v
|
|
|
+ if (string.upper(k)==string.upper("Transfer-Encoding")) and (string.upper(v)==string.upper("chunked")) then rcvChunked = true end
|
|
|
+ end
|
|
|
+ if filelen == 0 and not rcvChunked then
|
|
|
+ if not rcvChunked then
|
|
|
+ filelen = tonumber(rspHead["Content-Length"] or "2147483647")
|
|
|
+ end
|
|
|
+ end
|
|
|
+ --未处理的body数据
|
|
|
+ rbuff:del(0, d2)
|
|
|
+ succ,fotaDone,nCache = fota.run(rbuff)
|
|
|
+ if succ then
|
|
|
+ total = total + rbuff:used()
|
|
|
+ else
|
|
|
+ log.error(tag, "写入异常,请至少在1秒后重试")
|
|
|
+ fota.finish(false)
|
|
|
+ done = true
|
|
|
+ break
|
|
|
+ end
|
|
|
+ log.info(tag, "收到服务器数据,长度", rbuff:used(), "fota结果", succ, done, "总共", filelen)
|
|
|
+ rbuff:del()
|
|
|
+
|
|
|
+ if fotaDone then
|
|
|
+ log.info(tag, "下载完成")
|
|
|
+ while true do
|
|
|
+ succ,fotaDone = fota.isDone()
|
|
|
+ if fotaDone then
|
|
|
+ fota.finish(true)
|
|
|
+ log.info(tag, "FOTA完成")
|
|
|
+ done = true
|
|
|
+ ret = 0
|
|
|
+ break
|
|
|
+ end
|
|
|
+ sys.wait(100)
|
|
|
+ end
|
|
|
+ break
|
|
|
+ end
|
|
|
+
|
|
|
+ else
|
|
|
+ break
|
|
|
+ end
|
|
|
+ findhead = true
|
|
|
+ end
|
|
|
+ end
|
|
|
+ log.info(tag, "等待新数据到来")
|
|
|
+ result, param = libnet.wait(taskName, 30000, netc)
|
|
|
+ log.info(result, param)
|
|
|
+ if not result then
|
|
|
+ log.info(tag, "服务器断开了", result, param)
|
|
|
+ break
|
|
|
+ elseif not param then
|
|
|
+ log.info(tag, "服务器没有数据", result, param)
|
|
|
+ break
|
|
|
+ end
|
|
|
+ end
|
|
|
+ libnet.close(taskName, 5000, netc)
|
|
|
+ retry = retry + 1
|
|
|
end
|
|
|
cbFnc(ret)
|
|
|
+ socket.release(netc)
|
|
|
+ sysplus.taskDel(taskName)
|
|
|
+ fota.finish(false)
|
|
|
end
|
|
|
|
|
|
--[[
|
|
|
fota升级
|
|
|
-@api libfota.request(cbFnc,ota_url,storge_location, len, param1,ota_port,libfota_timeout,server_cert, client_cert, client_key, client_password)
|
|
|
+@api libfota.request(cbFnc,ota_url,storge_location, len, param1,ota_port,timeout,tls,server_cert, client_cert, client_key, client_password)
|
|
|
@function cbFnc 用户回调函数,回调函数的调用形式为:cbFnc(result) , 必须传
|
|
|
@string ota_url 升级URL, 若不填则自动使用合宙iot平台
|
|
|
@number/string storge_location 可选,fota数据存储的起始位置<br>如果是int,则是由芯片平台具体判断<br>如果是string,则存储在文件系统中<br>如果为nil,则由底层决定存储位置
|
|
|
@number len 可选,数据存储的最大空间
|
|
|
@userdata param1,可选,如果数据存储在spiflash时,为spi_device
|
|
|
@number ota_port 可选,请求端口,默认80
|
|
|
-@number libfota_timeout 可选,请求超时时间,单位毫秒,默认30000毫秒
|
|
|
+@number timeout 可选,请求超时时间,单位毫秒,默认20000毫秒
|
|
|
+@boolean tls 可选,是否是加密传输,默认false
|
|
|
@string server_cert 可选,服务器ca证书数据
|
|
|
@string client_cert 可选,客户端ca证书数据
|
|
|
@string client_key 可选,客户端私钥加密数据
|
|
|
@string client_password 可选,客户端私钥口令数据
|
|
|
@return nil 无返回值
|
|
|
]]
|
|
|
-function libfota.request(cbFnc,ota_url,storge_location, len, param1,ota_port,libfota_timeout,server_cert, client_cert, client_key, client_password)
|
|
|
- sys.taskInit(fota_task, cbFnc,storge_location, len, param1,ota_url, ota_port,libfota_timeout or 30000,server_cert, client_cert, client_key, client_password)
|
|
|
+function libfota.request(cbFnc,ota_url,storge_location, len, param1,ota_port,timeout,tls,server_cert, client_cert, client_key, client_password)
|
|
|
+ sysplus.taskInitEx(fota_task, taskName, netCB, cbFnc,storge_location, len, param1,ota_url, ota_port,timeout or 30000,tls,server_cert, client_cert, client_key, client_password)
|
|
|
end
|
|
|
|
|
|
return libfota
|