main.lua 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "gnss"
  3. VERSION = "1.0.0"
  4. --[[
  5. 本demo是演示定位数据处理的. script/turnkey目录有更完整的应用.
  6. 本demo需要V1103及以上的固件!!
  7. 注意: 室内无信号!! 无法定位!!! 到室外去, 起码天线要在室外.
  8. 窗口只有少许信号, 无法保证定位成功
  9. 这个demo需要的流量很多,可以注释这行
  10. sys.publish("mqtt_pub", "/gnss/" .. mobile.imei() .. "/up/nmea", data, 1)
  11. ]]
  12. -- sys库是标配
  13. local lbsLoc = require("lbsLoc")
  14. local sys = require("sys")
  15. require("sysplus")
  16. local gps_uart_id = 2
  17. local mqttc = nil
  18. local lla = {
  19. lat,
  20. lng
  21. }
  22. libgnss.clear() -- 清空数据,兼初始化
  23. uart.setup(gps_uart_id, 9600)
  24. function exec_agnss()
  25. if http then
  26. -- AGNSS 已调通
  27. while 1 do
  28. local code, headers, body = http.request("GET", "http://download.openluat.com/9501-xingli/CASIC_data.dat").wait()
  29. -- local code, headers, body = http.request("GET", "http://nutzam.com/6228.bin").wait()
  30. log.info("gnss", "AGNSS", code, body and #body or 0)
  31. if code == 200 and body and #body > 1024 then
  32. -- uart.write(gps_uart_id, "$reset,0,h01\r\n")
  33. -- sys.wait(200)
  34. -- uart.write(gps_uart_id, body)
  35. for offset=1,#body,512 do
  36. log.info("gnss", "AGNSS", "write >>>", #body:sub(offset, offset + 511))
  37. uart.write(gps_uart_id, body:sub(offset, offset + 511))
  38. -- sys.waitUntil("UART2_SEND", 100)
  39. sys.wait(100) -- 等100ms反而更成功
  40. end
  41. -- sys.waitUntil("UART2_SEND", 1000)
  42. io.writeFile("/6228.bin", body)
  43. break
  44. end
  45. sys.wait(60*1000)
  46. end
  47. end
  48. sys.wait(20)
  49. -- 读取之前的位置信息
  50. local str = io.readFile("/gnssrmc")
  51. if str then
  52. -- 首先是时间信息,注意是UTC时间
  53. -- 时间来源很多, 一般建议socket.sntp()时间同步后的系统时间
  54. local dt = os.date("!*t")
  55. lla = json.decode(str)
  56. -- 然后是辅助定位坐标
  57. -- 来源有很多方式:
  58. -- 1. 从历史定位数据得到, 例如之前定位成功后保存到本地文件系统了
  59. -- 2. 通过基站定位或者wifi定位获取到
  60. -- 3. 通过IP定位获取到大概坐标
  61. -- 坐标系是WGS84, 但鉴于是辅助定位,精度不是关键因素
  62. local aid = libgnss.casic_aid(dt, lla)
  63. uart.write(gps_uart_id, aid.."\r\n")
  64. str = nil
  65. else
  66. -- TODO 发起基站定位
  67. mobile.reqCellInfo(15)
  68. sys.waitUntil("CELL_INFO_UPDATE", 3000)
  69. lbsLoc.request(getLocCb)
  70. end
  71. end
  72. -- 功能:获取基站对应的经纬度后的回调函数
  73. -- 参数:-- result:number类型,0表示成功,1表示网络环境尚未就绪,2表示连接服务器失败,3表示发送数据失败,4表示接收服务器应答超时,5表示服务器返回查询失败;为0时,后面的5个参数才有意义
  74. -- lat:string类型,纬度,整数部分3位,小数部分7位,例如031.2425864
  75. -- lng:string类型,经度,整数部分3位,小数部分7位,例如121.4736522
  76. -- addr:目前无意义
  77. -- time:string类型或者nil,服务器返回的时间,6个字节,年月日时分秒,需要转为十六进制读取
  78. -- 第一个字节:年减去2000,例如2017年,则为0x11
  79. -- 第二个字节:月,例如7月则为0x07,12月则为0x0C
  80. -- 第三个字节:日,例如11日则为0x0B
  81. -- 第四个字节:时,例如18时则为0x12
  82. -- 第五个字节:分,例如59分则为0x3B
  83. -- 第六个字节:秒,例如48秒则为0x30
  84. -- locType:numble类型或者nil,定位类型,0表示基站定位成功,255表示WIFI定位成功
  85. function getLocCb(result, lat, lng, addr, time, locType)
  86. local dt = os.date("!*t")
  87. local locStr = { lat ,lng }
  88. locStr.lat = lat
  89. locStr.lng = lng
  90. log.info("testLbsLoc",locStr.lat ,locStr.lng)
  91. -- 获取经纬度成功, 坐标系WGS84
  92. if result == 0 then
  93. local aid = libgnss.casic_aid(dt, locStr)
  94. uart.write(gps_uart_id, aid.."\r\n")
  95. end
  96. end
  97. function upload_stat()
  98. if mqttc == nil or not mqttc:ready() then return end
  99. local stat = {
  100. csq = mobile.csq(),
  101. rssi = mobile.rssi(),
  102. rsrq = mobile.rsrq(),
  103. rsrp = mobile.rsrp(),
  104. --iccid = mobile.iccid(),
  105. snr = mobile.snr()
  106. }
  107. sys.publish("mqtt_pub", "/gnss/" .. mobile.imei() .. "/up/stat", (json.encode(stat)), 1)
  108. end
  109. sys.timerLoopStart(upload_stat, 60*1000)
  110. sys.taskInit(function()
  111. -- Air780EG工程样品的GPS的默认波特率是9600, 量产版是115200,以下是临时代码
  112. log.info("GPS", "start")
  113. pm.power(pm.GPS, true)
  114. -- 绑定uart,底层自动处理GNSS数据
  115. -- 第二个参数是转发到虚拟UART, 方便上位机分析
  116. libgnss.bind(gps_uart_id, uart.VUART_0)
  117. libgnss.on("raw", function(data)
  118. -- 默认不上报, 需要的话自行打开
  119. data = data:split("\r\n")
  120. if data == nil then
  121. return
  122. end
  123. for k, v in pairs(data) do
  124. if v and v:startsWith("$GNRMC") then
  125. sys.publish("mqtt_pub", "/gnss/" .. mobile.imei() .. "/up/nmea", v, 0)
  126. end
  127. end
  128. end)
  129. sys.wait(200) -- GPNSS芯片启动需要时间
  130. -- 调试日志,可选
  131. libgnss.debug(true)
  132. -- 显示串口配置
  133. -- uart.write(gps_uart_id, "$CFGPRT,1\r\n")
  134. -- sys.wait(20)
  135. -- 增加显示的语句
  136. uart.write(gps_uart_id, "$PCAS03,1,1,1,1,1,1,1,1,0,0,1,1,1*33\r\n") -- 默认所有name语句都打开
  137. sys.wait(20)
  138. -- 定位成功后,使用GNSS时间设置RTC, 暂不可用
  139. -- libgnss.rtcAuto(true)
  140. exec_agnss()
  141. end)
  142. sys.taskInit(function()
  143. while 1 do
  144. sys.wait(5000)
  145. -- 6228CI, 查询产品信息, 可选
  146. -- uart.write(gps_uart_id, "$PDTINFO,*62\r\n")
  147. -- uart.write(gps_uart_id, "$AIDINFO\r\n")
  148. -- sys.wait(100)
  149. -- uart.write(gps_uart_id, "$CFGSYS\r\n")
  150. -- uart.write(gps_uart_id, "$CFGMSG,6,4\r\n")
  151. log.info("RMC", json.encode(libgnss.getRmc(2) or {}))
  152. -- log.info("GGA", libgnss.getGga(3))
  153. -- log.info("GLL", json.encode(libgnss.getGll(2) or {}))
  154. -- log.info("GSA", json.encode(libgnss.getGsa(2) or {}))
  155. -- log.info("GSV", json.encode(libgnss.getGsv(2) or {}))
  156. -- log.info("VTG", json.encode(libgnss.getVtg(2) or {}))
  157. -- log.info("ZDA", json.encode(libgnss.getZda(2) or {}))
  158. -- log.info("date", os.date())
  159. log.info("sys", rtos.meminfo("sys"))
  160. log.info("lua", rtos.meminfo("lua"))
  161. end
  162. end)
  163. -- 订阅GNSS状态编码
  164. sys.subscribe("GNSS_STATE", function(event, ticks)
  165. -- event取值有
  166. -- FIXED 定位成功
  167. -- LOSE 定位丢失
  168. -- ticks是事件发生的时间,一般可以忽略
  169. log.info("gnss", "state", event, ticks)
  170. if event == "FIXED" then
  171. local rmc = libgnss.getRmc(2)
  172. local locStr = { lat ,lng }
  173. locStr.lat = rmc.lat
  174. locStr.lng = rmc.lng
  175. local str = json.encode(locStr, "7f")
  176. io.writeFile("/gnssrmc", str)
  177. log.info("gnss", "rmc", str)
  178. end
  179. end)
  180. -- mqtt 上传任务
  181. sys.taskInit(function()
  182. sys.waitUntil("IP_READY", 15000)
  183. mqttc = mqtt.create(nil, "lbsmqtt.airm2m.com", 1886) --mqtt客户端创建
  184. mqttc:auth(mobile.imei(), mobile.imei(), mobile.muid()) --mqtt三元组配置
  185. log.info("mqtt", mobile.imei(), mobile.imei(), mobile.muid())
  186. mqttc:keepalive(30) -- 默认值240s
  187. mqttc:autoreconn(true, 3000) -- 自动重连机制
  188. mqttc:on(function(mqtt_client, event, data, payload) --mqtt回调注册
  189. -- 用户自定义代码,按event处理
  190. --log.info("mqtt", "event", event, mqtt_client, data, payload)
  191. if event == "conack" then -- mqtt成功完成鉴权后的消息
  192. sys.publish("mqtt_conack") -- 小写字母的topic均为自定义topic
  193. -- 订阅不是必须的,但一般会有
  194. mqtt_client:subscribe("/gnss/" .. mobile.imei() .. "/down/#")
  195. elseif event == "recv" then -- 服务器下发的数据
  196. log.info("mqtt", "downlink", "topic", data, "payload", payload)
  197. -- 这里继续加自定义的业务处理逻辑
  198. elseif event == "sent" then -- publish成功后的事件
  199. log.info("mqtt", "sent", "pkgid", data)
  200. end
  201. end)
  202. -- 发起连接之后,mqtt库会自动维护链接,若连接断开,默认会自动重连
  203. mqttc:connect()
  204. sys.waitUntil("mqtt_conack")
  205. log.info("mqtt连接成功")
  206. sys.timerStart(upload_stat, 1000) -- 一秒后主动上传一次
  207. while true do
  208. -- 业务演示。等待其他task发过来的待上报数据
  209. -- 这里的mqtt_pub字符串是自定义的,与mqtt库没有直接联系
  210. -- 若不需要异步关闭mqtt链接,while内的代码可以替换成sys.wait(30000)
  211. local ret, topic, data, qos = sys.waitUntil("mqtt_pub", 30000)
  212. if ret then
  213. if topic == "close" then break end
  214. log.info("mqtt", "publish", "topic", topic)
  215. mqttc:publish(topic, data, qos)
  216. end
  217. end
  218. mqttc:close()
  219. mqttc = nil
  220. end)
  221. sys.taskInit(function()
  222. while 1 do
  223. sys.wait(3600*1000) -- 一小时检查一次
  224. local fixed, time_fixed = libgnss.isFix()
  225. if not fixed then
  226. exec_agnss()
  227. end
  228. end
  229. end)
  230. sys.timerLoopStart(function()
  231. upload_stat()
  232. end, 60000)
  233. -- sys.subscribe("NTP_UPDATE", function()
  234. -- if not libgnss.isFix() then
  235. -- -- "$AIDTIME,year,month,day,hour,minute,second,millisecond"
  236. -- local date = os.date("!*t")
  237. -- local str = string.format("$AIDTIME,%d,%d,%d,%d,%d,%d,000",
  238. -- date["year"], date["month"], date["day"], date["hour"], date["min"], date["sec"])
  239. -- log.info("gnss", str)
  240. -- uart.write(gps_uart_id, str .. "\r\n")
  241. -- end
  242. -- end)
  243. -- if socket and socket.sntp then
  244. -- sys.subscribe("IP_READY", function()
  245. -- socket.sntp()
  246. -- end)
  247. -- end
  248. -- 用户代码已结束---------------------------------------------
  249. -- 结尾总是这一句
  250. sys.run()
  251. -- sys.run()之后后面不要加任何语句!!!!!