air530z.lua 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. --[[
  2. ]]
  3. local air530z = {}
  4. local sys = require("sys")
  5. function air530z.setup(opts)
  6. air530z.opts = opts
  7. end
  8. function air530z.start()
  9. -- 初始化串口
  10. local gps_uart_id = air530z.opts.uart_id or 2
  11. local opts = air530z.opts
  12. local write = air530z.writeCmd
  13. -- 切换波特率
  14. uart.setup(gps_uart_id, 9600)
  15. uart.write(gps_uart_id,"$PCAS01,5*19\r\n")
  16. sys.wait(100)
  17. uart.close(gps_uart_id)
  18. sys.wait(100)
  19. uart.setup(gps_uart_id, 115200)
  20. -- 是否为调试模式
  21. if opts.debug then
  22. libgnss.debug(true)
  23. end
  24. libgnss.bind(gps_uart_id)
  25. libgnss.on("txt", function(txt)
  26. -- log.info("air530z", "收到TXT数据", txt)
  27. if txt:startsWith("$GPTXT,01,01,02,MS=") then
  28. local tmp = txt:split(",")
  29. log.info("air530z", "GPS有效星历", tmp[8], "BDS有效星历", tmp[11])
  30. air530z.xl_gps = tonumber(tmp[8])
  31. air530z.xl_bds = tonumber(tmp[11])
  32. air530z.xl_tm = os.time()
  33. elseif txt:startsWith("$GPTXT,01,01,01,ANTENNA") then
  34. -- 天线状态
  35. air530z.antenna = txt:split(" ")[2]
  36. if air530z.antenna then
  37. air530z.antenna = air530z.antenna:split("*")[1]
  38. end
  39. -- log.info("air530z", "天线状态", air530z.antenna)
  40. end
  41. end)
  42. -- 配置NMEA版本, 4.1的GSA有额外的标识
  43. if not opts.nmea_ver or opts.nmea_ver >= 41 then
  44. write("PCAS05,2")
  45. else
  46. write("PCAS05,5")
  47. end
  48. -- 打开全部NMEA语句
  49. if opts.rmc_only then
  50. write("PCAS03,0,0,0,0,1,0,0,0,0,0,,,0,0,,,,0")
  51. write("PCAS03,,,,,,,,,,,0")
  52. elseif air530z.opts.no_nmea then
  53. write("PCAS03,0,0,0,0,0,0,0,0,0,0,,,0,0,,,,0")
  54. write("PCAS03,,,,,,,,,,,0")
  55. else
  56. write("PCAS03,1,1,1,1,1,1,1,0,0,0,,,0,0,,,,0")
  57. write("PCAS03,,,,,,,,,,,1")
  58. end
  59. -- 是否需要切换定位系统呢?
  60. if opts.sys then
  61. if type(opts.sys) == "number" then
  62. air530z.writeCmd("PCAS04," .. tostring(opts.sys))
  63. -- 若开启了GPS, 那么把SBAS和QZSS也打开
  64. if (opts.sys & 1) == 1 then
  65. -- 额外打开SBAS和QZSS
  66. write("PCAS15,4,FFFF")
  67. write("PCAS15,5,1F")
  68. end
  69. end
  70. end
  71. end
  72. function air530z.writeCmd(cmd, full)
  73. if not full then
  74. local ck = crypto.checksum(cmd)
  75. cmd = string.format("$%s*%02X\r\n", cmd, ck)
  76. end
  77. log.info("air530z", "写入指令", cmd:trim())
  78. uart.write(air530z.opts.uart_id, cmd)
  79. end
  80. function air530z.reboot(mode)
  81. local cmd = string.format("PCAS10,%d", mode or 0)
  82. air530z.writeCmd(cmd)
  83. if mode and mode == 2 then
  84. air530z.agps_tm = nil
  85. end
  86. libgnss.clear()
  87. end
  88. function air530z.stop()
  89. uart.close(air530z.opts.uart_id)
  90. end
  91. local function do_agps()
  92. -- 首先, 发起位置查询
  93. local lat, lng
  94. if mobile then
  95. mobile.reqCellInfo(6)
  96. sys.waitUntil("CELL_INFO_UPDATE", 6000)
  97. local lbsLoc2 = require("lbsLoc2")
  98. lat, lng = lbsLoc2.request(5000)
  99. -- local lat, lng, t = lbsLoc2.request(5000, "bs.openluat.com")
  100. log.info("lbsLoc2", lat, lng)
  101. elseif wlan then
  102. -- wlan.scan()
  103. -- sys.waitUntil("WLAN_SCAN_DONE", 5000)
  104. end
  105. if not lat then
  106. -- 获取最后的本地位置
  107. local locStr = io.readFile("/zkwloc")
  108. if locStr then
  109. local jdata = json.decode(locStr)
  110. if jdata and jdata.lat then
  111. lat = jdata.lat
  112. lng = jdata.lng
  113. end
  114. end
  115. end
  116. -- 然后, 判断星历时间和下载星历
  117. local now = os.time()
  118. local agps_time = tonumber(io.readFile("/zkw_tm") or "0") or 0
  119. if now - agps_time > 3600 then
  120. local url = air530z.opts.url
  121. if not air530z.opts.url then
  122. if air530z.opts.sys and 2 == air530z.opts.sys then
  123. url = "http://download.openluat.com/9501-xingli/CASIC_data_bds.dat"
  124. else
  125. url = "http://download.openluat.com/9501-xingli/CASIC_data.dat"
  126. end
  127. end
  128. local code = http.request("GET", url, nil, nil, {dst="/ZKW.dat"}).wait()
  129. if code and code == 200 then
  130. log.info("air530z", "下载星历成功", url)
  131. io.writeFile("/zkw_tm", tostring(now))
  132. else
  133. log.info("air530z", "下载星历失败", code)
  134. end
  135. else
  136. log.info("air530z", "星历不需要更新", now - agps_time)
  137. end
  138. local gps_uart_id = air530z.opts.uart_id or 2
  139. -- 写入星历
  140. local agps_data = io.readFile("/ZKW.dat")
  141. if agps_data and #agps_data > 1024 then
  142. log.info("air530z", "写入星历数据", "长度", #agps_data)
  143. for offset=1,#agps_data,512 do
  144. -- log.info("gnss", "AGNSS", "write >>>", #agps_data:sub(offset, offset + 511))
  145. uart.write(gps_uart_id, agps_data:sub(offset, offset + 511))
  146. sys.wait(100) -- 等100ms反而更成功
  147. end
  148. else
  149. log.info("air530z", "没有星历数据")
  150. return
  151. end
  152. -- 写入参考位置
  153. -- "lat":23.4068813,"min":27,"valid":true,"day":27,"lng":113.2317505
  154. if not lat or not lng then
  155. -- lat, lng = 23.4068813, 113.2317505
  156. return -- TODO 暂时不写入参考位置
  157. end
  158. socket.sntp()
  159. sys.waitUntil("NTP_UPDATE", 1000)
  160. local dt = os.date("!*t")
  161. local lla = {lat=lat, lng=lng}
  162. local aid = libgnss.casic_aid(dt, lla)
  163. uart.write(gps_uart_id, aid.."\r\n")
  164. -- 结束
  165. air530z.agps_tm = now
  166. end
  167. function air530z.agps(force)
  168. -- 如果不是强制写入AGPS信息, 而且是已经定位成功的状态,那就没必要了
  169. if not force and libgnss.isFix() then return end
  170. -- 先判断一下时间
  171. local now = os.time()
  172. if force or not air530z.agps_tm or now - air530z.agps_tm > 3600 then
  173. -- 执行AGPS
  174. log.info("air530z", "开始执行AGPS")
  175. do_agps()
  176. else
  177. log.info("air530z", "暂不需要写入AGPS")
  178. end
  179. end
  180. function air530z.saveloc(lat, lng)
  181. if not lat or not lng then
  182. if libgnss.isFix() then
  183. local rmc = libgnss.getRmc(3)
  184. if rmc then
  185. lat, lng = rmc.lat, rmc.lng
  186. end
  187. end
  188. end
  189. if lat and lng then
  190. log.info("待保存的GPS位置", lat, lng)
  191. local locStr = string.format('{"lat":%7f,"lng":%7f}', lat, lng)
  192. log.info("air530z", "保存GPS位置", locStr)
  193. io.writeFile("/zkwloc", locStr)
  194. end
  195. end
  196. sys.subscribe("GNSS_STATE", function(event)
  197. if event == "FIXED" then
  198. air530z.saveloc()
  199. end
  200. end)
  201. return air530z