soc_fota.lua 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. -- 用http方式下载ota固件并实现升级
  2. --[[
  3. -- 这个是用uart3直接把升级包发给mcu,作为本地升级的一种参考,高速串口单次发送不要超过4K
  4. local rbuff = zbuff.create(16384)
  5. local function uartRx(id, len)
  6. uart.rx(id, rbuff)
  7. if rbuff:used() > 0 then
  8. local succ,fotaDone,nCache = fota.run(rbuff)
  9. if succ then
  10. else
  11. log.error("fota写入异常,请至少在1秒后重试")
  12. fota.finish(false)
  13. return
  14. end
  15. rbuff:del()
  16. -- log.info("收到服务器数据,长度", rbuff:used(), "fota结果", succ, done, "总共", filelen)
  17. if fotaDone then
  18. log.info("下载完成")
  19. sys.publish("downloadOK")
  20. end
  21. end
  22. end
  23. local function otaTask()
  24. local spiFlash = spi.deviceSetup(spi.SPI_1,pin.PA7,0,0,8,24*1000*1000,spi.MSB,1,1)
  25. fota.init(0, 0x00200000, spiFlash)
  26. while not fota.wait() do
  27. sys.wait(100)
  28. end
  29. uart.setup(3,1500000)
  30. uart.on(3, "receive", uartRx)
  31. uart.write(3,"ready")
  32. sys.waitUntil("downloadOK")
  33. while true do
  34. local succ,fotaDone = fota.isDone()
  35. if fotaDone then
  36. fota.finish(true)
  37. log.info("FOTA完成")
  38. rtos.reboot() --如果还有其他事情要做,就不要立刻reboot
  39. break
  40. end
  41. sys.wait(100)
  42. end
  43. end
  44. function otaDemo()
  45. sys.taskInit(otaTask)
  46. end
  47. ]]
  48. local libnet = require "libnet"
  49. local taskName = "OTA_TASK"
  50. local function netCB(msg)
  51. if msg[1] == socket.EVENT then
  52. log.info("socket网络状态变更")
  53. elseif msg[1] == socket.TX_OK then
  54. log.info("socket发送完成")
  55. elseif msg[1] == socket.EV_NW_RESULT_CLOSE then
  56. log.info("socket关闭")
  57. else
  58. log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
  59. end
  60. end
  61. local function otaTask()
  62. fota.init()
  63. local succ, param, ip, port, total, findhead, filelen, rcvCache,d1,d2,statusCode,retry,rspHead,rcvChunked,done,fotaDone,nCache
  64. local tbuff = zbuff.create(512)
  65. local rbuff = zbuff.create(4096)
  66. local netc = socket.create(nil, taskName)
  67. socket.config(netc, nil, nil, nil) -- http用的普通TCP连接
  68. filelen = 0
  69. total = 0
  70. retry = 0
  71. done = false
  72. rspHead = {}
  73. local result = libnet.waitLink(taskName, 0, netc)
  74. while retry < 3 and not done do
  75. result = libnet.connect(taskName, 30000, netc, "www.air32.cn", 80) --后续出了http库则直接用http来处理
  76. tbuff:del()
  77. -- 用的iot平台,所以固件名称和版本号需要对应处理
  78. -- 用的自建平台,可以自主定制规则
  79. local v = rtos.version()
  80. v = tonumber(v:sub(2, 5))
  81. tbuff:copy(0, "GET /output.sota" .. " HTTP/1.1\r\n")
  82. tbuff:copy(nil,"Host: www.air32.cn:80\r\n")
  83. if filelen > 0 then --断网重连的话,只需要下载剩余的部分就行了
  84. tbuff:copy(nil,"Range: bytes=" .. total .. "-\r\n")
  85. end
  86. tbuff:copy(nil,"Accept: application/octet-stream\r\n\r\n")
  87. log.info(tbuff:query())
  88. result = libnet.tx(taskName, 5000, netc, tbuff)
  89. rbuff:del()
  90. findhead = false
  91. while result do
  92. succ, param, ip, port = socket.rx(netc, rbuff)
  93. if not succ then
  94. log.info("服务器断开了", succ, param, ip, port)
  95. break
  96. end
  97. if rbuff:used() > 0 then
  98. if findhead then
  99. succ,fotaDone,nCache = fota.run(rbuff)
  100. if succ then
  101. total = total + rbuff:used()
  102. else
  103. log.error("fota写入异常,请至少在1秒后重试")
  104. fota.finish(false)
  105. done = true
  106. break
  107. end
  108. log.info("收到服务器数据,长度", rbuff:used(), "fota结果", succ, done, "总共", filelen)
  109. rbuff:del()
  110. if fotaDone then
  111. log.info("下载完成")
  112. while true do
  113. succ,fotaDone = fota.isDone()
  114. if fotaDone then
  115. fota.finish(true)
  116. log.info("FOTA完成")
  117. done = true
  118. rtos.reboot() --如果还有其他事情要做,就不要立刻reboot
  119. break
  120. end
  121. sys.wait(100)
  122. end
  123. break
  124. end
  125. else
  126. rcvCache = rbuff:query()
  127. d1,d2 = rcvCache:find("\r\n\r\n")
  128. -- 打印出http response head
  129. -- log.info(rcvCache:sub(1, d2))
  130. if d2 then
  131. --状态行
  132. _,d1,statusCode = rcvCache:find("%s(%d+)%s.-\r\n")
  133. if not statusCode then
  134. log.info("http没有状态返回")
  135. break
  136. end
  137. statusCode = tonumber(statusCode)
  138. if statusCode ~= 200 and statusCode ~= 206 then
  139. log.info("http应答不OK", statusCode)
  140. done = true
  141. break
  142. end
  143. --应答头
  144. for k,v in string.gmatch(rcvCache:sub(d1+1,d2-2),"(.-):%s*(.-)\r\n") do
  145. rspHead[k] = v
  146. if (string.upper(k)==string.upper("Transfer-Encoding")) and (string.upper(v)==string.upper("chunked")) then rcvChunked = true end
  147. end
  148. if filelen == 0 and not rcvChunked then
  149. if not rcvChunked then
  150. filelen = tonumber(rspHead["Content-Length"] or "2147483647")
  151. end
  152. end
  153. --未处理的body数据
  154. rbuff:del(0, d2)
  155. succ,fotaDone,nCache = fota.run(rbuff)
  156. if succ then
  157. total = total + rbuff:used()
  158. else
  159. log.error("fota写入异常,请至少在1秒后重试")
  160. fota.finish(false)
  161. done = true
  162. break
  163. end
  164. log.info("收到服务器数据,长度", rbuff:used(), "fota结果", succ, done, "总共", filelen)
  165. rbuff:del()
  166. if fotaDone then
  167. log.info("下载完成")
  168. while true do
  169. succ,fotaDone = fota.isDone()
  170. if fotaDone then
  171. fota.finish(true)
  172. log.info("FOTA完成")
  173. done = true
  174. rtos.reboot() --如果还有其他事情要做,就不要立刻reboot
  175. break
  176. end
  177. sys.wait(100)
  178. end
  179. break
  180. end
  181. else
  182. break
  183. end
  184. findhead = true
  185. end
  186. end
  187. log.info("等待新数据到来")
  188. result, param = libnet.wait(taskName, 5000, netc)
  189. log.info(result, param)
  190. if not result then
  191. log.info("服务器断开了", result, param)
  192. break
  193. elseif not param then
  194. log.info("服务器没有数据", result, param)
  195. break
  196. end
  197. end
  198. libnet.close(taskName, 5000, netc)
  199. retry = retry + 1
  200. end
  201. socket.release(netc)
  202. sysplus.taskDel(taskName)
  203. fota.finish(false)
  204. end
  205. function otaDemo()
  206. sysplus.taskInitEx(otaTask, taskName, netCB)
  207. end