Explorar o código

change:回退libfota

Dozingfiretruck %!s(int64=2) %!d(string=hai) anos
pai
achega
2e13b8e8e3
Modificáronse 1 ficheiros con 192 adicións e 19 borrados
  1. 192 19
      script/libs/libfota.lua

+ 192 - 19
script/libs/libfota.lua

@@ -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