main.lua 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. --[[
  2. IPv6服务端演示, 仅EC618系列支持, 例如Air780E/Air600E/Air780UG/Air700E
  3. ]]
  4. -- LuaTools需要PROJECT和VERSION这两个信息
  5. PROJECT = "ipv6_client"
  6. VERSION = "1.0.0"
  7. log.info("main", PROJECT, VERSION)
  8. -- 一定要添加sys.lua !!!!
  9. sys = require("sys")
  10. sysplus = require("sysplus")
  11. libnet = require "libnet"
  12. -- Air780E的AT固件默认会为开机键防抖, 导致部分用户刷机很麻烦
  13. if rtos.bsp() == "EC618" and pm and pm.PWK_MODE then
  14. pm.power(pm.PWK_MODE, false)
  15. end
  16. -- 处理未识别的网络消息
  17. local function netCB(msg)
  18. log.info("未处理消息", msg[1], msg[2], msg[3], msg[4])
  19. end
  20. LED = gpio.setup(27, 0)
  21. GPIO1 = gpio.setup(1, 0)
  22. GPIO24 = gpio.setup(24, 0)
  23. HTTP_200_EMTRY = "HTTP/1.0 200 OK\r\nServer: LuatOS\r\nConnection: close\r\nContent-Length: 0\r\n\r\n"
  24. -- 演示task
  25. function ipv6test()
  26. -- 仅EC618系列支持, 例如Air780E/Air600E/Air780UG/Air700E
  27. if rtos.bsp() ~= "EC618" then
  28. while 1 do
  29. log.info("ipv6", "only Air780E/Air600E/Air780UG/Air700E supported")
  30. sys.wait(1000)
  31. end
  32. end
  33. -- 启用IPv6, 默认关闭状态,必须在驻网前开启
  34. -- 注意, 启用IPv6, 联网速度会慢2~3秒
  35. mobile.ipv6(true)
  36. log.info("ipv6", "等待联网")
  37. sys.waitUntil("IP_READY")
  38. log.info("ipv6", "联网完成")
  39. sys.wait(100)
  40. -- 打印一下本地ip, 一般只有ipv6才可能是公网ip, ipv4基本不可能
  41. -- 而且ipv6不一样是外网ip, 这是运营商决定的, 模块无能为力
  42. ip, mask, gw, ipv6 = socket.localIP()
  43. log.info("本地IP地址", ip, ipv6)
  44. if not ipv6 then
  45. log.info("没有IPV6地址,无法演示")
  46. -- return
  47. end
  48. -- 这里给个演示用的ddns, 临时自建的, 仅供测试
  49. local code, headers, body = http.request("GET", "http://81.70.22.216:8280/update?secret=luatos&domain=" .. mobile.imei() ..".dyndns&addr=" .. ipv6).wait()
  50. log.info("DDNS", "已映射", mobile.imei() .. ".dyndns.u8g2.com", code, body)
  51. log.info("shell", "telnet -6 " .. mobile.imei() .. ".dyndns.u8g2.com 14000")
  52. -- 开始正在的逻辑, 发起socket链接,等待数据/上报心跳
  53. local taskName = "ipv6client"
  54. local topic = taskName .. "_txrx"
  55. local txqueue = {}
  56. sysplus.taskInitEx(ipv6task, taskName, netCB, taskName, txqueue, topic)
  57. while 1 do
  58. local result, tp, data = sys.waitUntil(topic, 60000)
  59. if not result then
  60. -- 等很久了,没数据上传/下发, 发个日期心跳包吧
  61. --table.insert(txqueue, string.char(0))
  62. --sys_send(taskName, socket.EVENT, 0)
  63. elseif tp == "uplink" then
  64. -- 上行数据, 主动上报的数据,那就发送呀
  65. table.insert(txqueue, data)
  66. sys_send(taskName, socket.EVENT, 0)
  67. elseif tp == "downlink" then
  68. -- 下行数据,接收的数据, 从ipv6task来的
  69. -- 其他代码可以通过 sys.publish()
  70. log.info("socket", "收到下发的数据了", #data, data)
  71. -- 下面是模拟一个http服务, 因为httpsrv库还没好,先用着吧
  72. if data:startsWith("GET / ") then
  73. local httpresp = "HTTP/1.0 200 OK\r\n"
  74. httpresp = httpresp .. "Server: LuatOS\r\nContent-Type: text/html\r\nConnection: close\r\n"
  75. local fdata = io.readFile("/luadb/index.html")
  76. httpresp = httpresp .. string.format("Content-Length: %d\r\n\r\n", #fdata)
  77. httpresp = httpresp .. fdata
  78. table.insert(txqueue, httpresp)
  79. table.insert(txqueue, "close")
  80. sys_send(taskName, socket.EVENT, 0)
  81. elseif data:startsWith("GET /led/") then
  82. if data:startsWith("GET /led/1") then
  83. log.info("led", "亮起")
  84. LED(1)
  85. else
  86. log.info("led", "熄灭")
  87. LED(0)
  88. end
  89. table.insert(txqueue, HTTP_200_EMTRY)
  90. table.insert(txqueue, "close")
  91. sys_send(taskName, socket.EVENT, 0)
  92. elseif data:startsWith("GET /gpio24/") then
  93. if data:startsWith("GET /gpio24/1") then
  94. log.info("gpio24", "亮起")
  95. GPIO24(1)
  96. else
  97. log.info("gpio24", "熄灭")
  98. GPIO24(0)
  99. end
  100. table.insert(txqueue, HTTP_200_EMTRY)
  101. table.insert(txqueue, "close")
  102. sys_send(taskName, socket.EVENT, 0)
  103. elseif data:startsWith("GET /gpio1/") then
  104. if data:startsWith("GET /gpio1/1") then
  105. log.info("gpio1", "亮起")
  106. GPIO1(1)
  107. else
  108. log.info("gpio1", "熄灭")
  109. GPIO1(0)
  110. end
  111. table.insert(txqueue, HTTP_200_EMTRY)
  112. table.insert(txqueue, "close")
  113. sys_send(taskName, socket.EVENT, 0)
  114. elseif data:startsWith("GET ") or data:startsWith("POST ") or data:startsWith("HEAD ") then
  115. table.insert(txqueue, HTTP_200_EMTRY)
  116. table.insert(txqueue, "close")
  117. sys_send(taskName, socket.EVENT, 0)
  118. end
  119. end
  120. end
  121. end
  122. function ipv6task(d1Name, txqueue, rxtopic)
  123. -- 本地监听的端口
  124. local port = 14000
  125. local rx_buff = zbuff.create(1024)
  126. local tx_buff = zbuff.create(4 * 1024)
  127. local netc = socket.create(nil, d1Name)
  128. socket.config(netc, 14000)
  129. log.info("任务id", d1Name)
  130. while true do
  131. log.info("socket", "开始监控")
  132. local result = libnet.listen(d1Name, 0, netc)
  133. if result then
  134. log.info("socket", "监听成功")
  135. result = socket.accept(netc, nil) --只支持1对1
  136. if result then
  137. log.info("客户端连上了")
  138. end
  139. else
  140. log.info("socket", "监听失败!!")
  141. end
  142. while result do
  143. -- log.info("socket", "调用rx接收数据")
  144. local succ, param = socket.rx(netc, rx_buff)
  145. if not succ then
  146. log.info("客户端断开了", succ, param, ip, port)
  147. break
  148. end
  149. if rx_buff:used() > 0 then
  150. log.info("socket", "收到客户端数据,长度", rx_buff:used())
  151. local data = rx_buff:query() -- 获取数据
  152. sys.publish(rxtopic, "downlink", data)
  153. rx_buff:del()
  154. end
  155. -- log.info("libnet", "调用wait开始等待消息")
  156. result, param, param2 = libnet.wait(d1Name, 15000, netc)
  157. log.info("libnet", "wait", result, param, param2)
  158. if not result then
  159. -- 网络异常了
  160. log.info("socket", "客户端断开了", result, param)
  161. break
  162. elseif #txqueue > 0 then
  163. local force_close = false
  164. while #txqueue > 0 do
  165. local data = table.remove(txqueue, 1)
  166. if not data then
  167. break
  168. end
  169. log.info("socket", "上行数据长度", #data)
  170. if data == "close" then
  171. --sys.wait(1000)
  172. force_close = true
  173. break
  174. end
  175. tx_buff:del()
  176. tx_buff:copy(nil, data)
  177. result,param = libnet.tx(d1Name, 15000, netc, tx_buff)
  178. log.info("libnet", "发送数据的结果", result, param)
  179. if not result then
  180. log.info("socket", "数据发送异常", result, param)
  181. break
  182. end
  183. end
  184. if force_close then
  185. break
  186. end
  187. end
  188. end
  189. log.info("socket", "连接已断开,继续下一个循环")
  190. libnet.close(d1Name, 5000, netc)
  191. -- log.info(rtos.meminfo("sys"))
  192. sys.wait(50)
  193. end
  194. end
  195. sys.taskInit(ipv6test)
  196. -- 用户代码已结束---------------------------------------------
  197. -- 结尾总是这一句
  198. sys.run()
  199. -- sys.run()之后后面不要加任何语句!!!!!