main.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "httpdemo"
  3. VERSION = "1.0.0"
  4. --[[
  5. 本demo需要http库, 大部分能联网的设备都具有这个库
  6. http也是内置库, 无需require
  7. 1. 如需上传大文件,请使用 httpplus 库, 对应demo/httpplus
  8. 2.
  9. ]]
  10. -- sys库是标配
  11. _G.sys = require("sys")
  12. --[[特别注意, 使用http库需要下列语句]]
  13. _G.sysplus = require("sysplus")
  14. -- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
  15. if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
  16. pm.power(pm.PWK_MODE, false)
  17. end
  18. sys.taskInit(function()
  19. -----------------------------
  20. -- 统一联网函数, 可自行删减
  21. ----------------------------
  22. if wlan and wlan.connect then
  23. -- wifi 联网, ESP32系列均支持
  24. local ssid = "luatos1234"
  25. local password = "12341234"
  26. log.info("wifi", ssid, password)
  27. -- TODO 改成esptouch配网
  28. -- LED = gpio.setup(12, 0, gpio.PULLUP)
  29. wlan.init()
  30. wlan.setMode(wlan.STATION)
  31. wlan.connect(ssid, password, 1)
  32. local result, data = sys.waitUntil("IP_READY", 30000)
  33. log.info("wlan", "IP_READY", result, data)
  34. device_id = wlan.getMac()
  35. elseif mobile then
  36. -- Air780E/Air600E系列
  37. --mobile.simid(2)
  38. -- LED = gpio.setup(27, 0, gpio.PULLUP)
  39. device_id = mobile.imei()
  40. log.info("ipv6", mobile.ipv6(true))
  41. sys.waitUntil("IP_READY", 30000)
  42. elseif http then
  43. sys.waitUntil("IP_READY")
  44. else
  45. while 1 do
  46. sys.wait(1000)
  47. log.info("http", "当前固件未包含http库")
  48. end
  49. end
  50. log.info("已联网")
  51. sys.publish("net_ready")
  52. end)
  53. function demo_http_get()
  54. -- 最普通的Http GET请求
  55. local code, headers, body = http.request("GET", "https://www.air32.cn/").wait()
  56. log.info("http.get", code, headers, body)
  57. local code, headers, body = http.request("GET", "https://mirrors6.tuna.tsinghua.edu.cn/", nil, nil, {ipv6=true}).wait()
  58. log.info("http.get", code, headers, body)
  59. sys.wait(100)
  60. local code, headers, body = http.request("GET", "https://www.luatos.com/").wait()
  61. log.info("http.get", code, headers, body)
  62. -- 按需打印
  63. -- code 响应值, 若大于等于 100 为服务器响应, 小于的均为错误代码
  64. -- headers是个table, 一般作为调试数据存在
  65. -- body是字符串. 注意lua的字符串是带长度的byte[]/char*, 是可以包含不可见字符的
  66. -- log.info("http", code, json.encode(headers or {}), #body > 512 and #body or body)
  67. end
  68. function demo_http_post_json()
  69. -- POST request 演示
  70. local req_headers = {}
  71. req_headers["Content-Type"] = "application/json"
  72. local body = json.encode({name="LuatOS"})
  73. local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
  74. req_headers,
  75. body -- POST请求所需要的body, string, zbuff, file均可
  76. ).wait()
  77. log.info("http.post", code, headers, body)
  78. end
  79. function demo_http_post_form()
  80. -- POST request 演示
  81. local req_headers = {}
  82. req_headers["Content-Type"] = "application/x-www-form-urlencoded"
  83. local params = {
  84. ABC = "123",
  85. DEF = 345
  86. }
  87. local body = ""
  88. for k, v in pairs(params) do
  89. body = body .. tostring(k) .. "=" .. tostring(v):urlEncode() .. "&"
  90. end
  91. local code, headers, body = http.request("POST","http://echohttp.wendal.cn/post",
  92. req_headers,
  93. body -- POST请求所需要的body, string, zbuff, file均可
  94. ).wait()
  95. log.info("http.post.form", code, headers, body)
  96. end
  97. -- local function http_download_callback(content_len,body_len,userdata)
  98. -- print("http_download_callback",content_len,body_len,userdata)
  99. -- end
  100. -- local http_userdata = "123456789"
  101. function demo_http_download()
  102. -- POST and download, task内的同步操作
  103. local opts = {} -- 额外的配置项
  104. opts["dst"] = "/data.bin" -- 下载路径,可选
  105. opts["timeout"] = 30000 -- 超时时长,单位ms,可选
  106. -- opts["adapter"] = socket.ETH0 -- 使用哪个网卡,可选
  107. -- opts["callback"] = http_download_callback
  108. -- opts["userdata"] = http_userdata
  109. for k, v in pairs(opts) do
  110. print("opts",k,v)
  111. end
  112. local code, headers, body = http.request("POST","http://site0.cn/api/httptest/simple/date",
  113. {}, -- 请求所添加的 headers, 可以是nil
  114. "",
  115. opts
  116. ).wait()
  117. log.info("http.post", code, headers, body) -- 只返回code和headers
  118. -- local f = io.open("/data.bin", "rb")
  119. -- if f then
  120. -- local data = f:read("*a")
  121. -- log.info("fs", "data", data, data:toHex())
  122. -- end
  123. -- GET request, 开个task让它自行执行去吧, 不管执行结果了
  124. sys.taskInit(http.request("GET","http://site0.cn/api/httptest/simple/time").wait)
  125. end
  126. function demo_http_post_file()
  127. -- -- POST multipart/form-data模式 上传文件---手动拼接
  128. local boundary = "----WebKitFormBoundary"..os.time()
  129. local req_headers = {
  130. ["Content-Type"] = "multipart/form-data; boundary="..boundary,
  131. }
  132. local body = "--"..boundary.."\r\n"..
  133. "Content-Disposition: form-data; name=\"uploadFile\"; filename=\"luatos_uploadFile_TEST01.txt\""..
  134. "\r\nContent-Type: text/plain\r\n\r\n"..
  135. "1111http_测试一二三四654zacc\r\n"..
  136. "--"..boundary
  137. log.info("headers: ", "\r\n"..json.encode(req_headers))
  138. log.info("body: ", "\r\n"..body)
  139. local code, headers, body = http.request("POST","http://airtest.openluat.com:2900/uploadFileToStatic",
  140. req_headers,
  141. body -- POST请求所需要的body, string, zbuff, file均可
  142. ).wait()
  143. log.info("http.post", code, headers, body)
  144. -- 也可用postMultipartFormData(url, params) 上传文件
  145. postMultipartFormData(
  146. "http://airtest.openluat.com:2900/uploadFileToStatic",
  147. {
  148. -- texts =
  149. -- {
  150. -- ["imei"] = "862991234567890",
  151. -- ["time"] = "20180802180345"
  152. -- },
  153. files =
  154. {
  155. ["uploadFile"] = "/luadb/luatos_uploadFile.txt",
  156. }
  157. }
  158. )
  159. end
  160. local function demo_http_get_gzip()
  161. -- 这里用 和风天气 的API做演示
  162. -- 这个API的响应, 总会gzip压缩过, 需要配合miniz库进行解压
  163. local code, headers, body = http.request("GET", "https://devapi.qweather.com/v7/weather/now?location=101010100&key=0e8c72015e2b4a1dbff1688ad54053de").wait()
  164. log.info("http.gzip", code)
  165. if code == 200 then
  166. local re = miniz.uncompress(body:sub(11), 0)
  167. log.info("和风天气", re)
  168. if re then
  169. local jdata = json.decode(re)
  170. log.info("jdata", jdata)
  171. if jdata then
  172. log.info("和风天气", jdata.code)
  173. if jdata.now then
  174. log.info("和风天气", "天气", jdata.now.text)
  175. log.info("和风天气", "温度", jdata.now.temp)
  176. end
  177. end
  178. end
  179. end
  180. end
  181. sys.taskInit(function()
  182. sys.wait(100)
  183. -- 打印一下支持的加密套件, 通常来说, 固件已包含常见的99%的加密套件
  184. -- if crypto.cipher_suites then
  185. -- log.info("cipher", "suites", json.encode(crypto.cipher_suites()))
  186. -- end
  187. -------------------------------------
  188. -------- HTTP 演示代码 --------------
  189. -------------------------------------
  190. sys.waitUntil("net_ready") -- 等联网
  191. while 1 do
  192. -- 演示GET请求
  193. demo_http_get()
  194. -- 表单提交
  195. -- demo_http_post_form()
  196. -- POST一个json字符串
  197. -- demo_http_post_json()
  198. -- 上传文件, mulitform形式
  199. -- demo_http_post_file()
  200. -- 文件下载
  201. -- demo_http_download()
  202. -- gzip压缩的响应, 以和风天气为例
  203. -- demo_http_get_gzip()
  204. sys.wait(1000)
  205. -- 打印一下内存状态
  206. log.info("sys", rtos.meminfo("sys"))
  207. log.info("lua", rtos.meminfo("lua"))
  208. sys.wait(600000)
  209. end
  210. end)
  211. ---- MultipartForm上传文件
  212. -- url string 请求URL地址
  213. -- req_headers table 请求头
  214. -- params table 需要传输的数据参数
  215. function postMultipartFormData(url, params)
  216. local boundary = "----WebKitFormBoundary"..os.time()
  217. local req_headers = {
  218. ["Content-Type"] = "multipart/form-data; boundary="..boundary,
  219. }
  220. local body = {}
  221. -- 解析拼接 body
  222. for k,v in pairs(params) do
  223. if k=="texts" then
  224. local bodyText = ""
  225. for kk,vv in pairs(v) do
  226. print(kk,vv)
  227. bodyText = bodyText.."--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"\r\n\r\n"..vv.."\r\n"
  228. end
  229. table.insert(body, bodyText)
  230. elseif k=="files" then
  231. local contentType =
  232. {
  233. txt = "text/plain", -- 文本
  234. jpg = "image/jpeg", -- JPG 格式图片
  235. jpeg = "image/jpeg", -- JPEG 格式图片
  236. png = "image/png", -- PNG 格式图片
  237. gif = "image/gif", -- GIF 格式图片
  238. html = "image/html", -- HTML
  239. json = "application/json" -- JSON
  240. }
  241. for kk,vv in pairs(v) do
  242. if type(vv) == "table" then
  243. for i=1, #vv do
  244. print(kk,vv[i])
  245. table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv[i]:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv[i]:match("%.(%w+)$")].."\r\n\r\n")
  246. table.insert(body, io.readFile(vv[i]))
  247. table.insert(body, "\r\n")
  248. end
  249. else
  250. print(kk,vv)
  251. table.insert(body, "--"..boundary.."\r\nContent-Disposition: form-data; name=\""..kk.."\"; filename=\""..vv:match("[^%/]+%w$").."\"\r\nContent-Type: "..contentType[vv:match("%.(%w+)$")].."\r\n\r\n")
  252. table.insert(body, io.readFile(vv))
  253. table.insert(body, "\r\n")
  254. end
  255. end
  256. end
  257. end
  258. table.insert(body, "--"..boundary.."--\r\n")
  259. body = table.concat(body)
  260. log.info("headers: ", "\r\n" .. json.encode(req_headers), type(body))
  261. log.info("body: " .. body:len() .. "\r\n" .. body)
  262. local code, headers, body = http.request("POST",url,
  263. req_headers,
  264. body
  265. ).wait()
  266. log.info("http.post", code, headers, body)
  267. end
  268. -- 用户代码已结束---------------------------------------------
  269. -- 结尾总是这一句
  270. sys.run()
  271. -- sys.run()之后后面不要加任何语句!!!!!