hdgnss.lua 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. local lbsLoc2 = require "lbsLoc2"
  2. local hdgnss = {}
  3. function hdcrc(str, len)
  4. if not len then
  5. len = #str
  6. end
  7. local crc1 = 0
  8. local crc2 = 0
  9. for i = 3, len do
  10. crc1 = crc1 + str:byte(i)
  11. crc2 = crc2 + (crc1 & 0xff)
  12. end
  13. -- print(string.format("%02X%02X", crc1 & 0xFF, crc2 & 0xFF))
  14. return string.char(crc1 & 0xFF, crc2 & 0xFF)
  15. end
  16. function hdgnss.aideph()
  17. local url = "http://download.openluat.com/9501-xingli/HD_GPS_BDS.hdb"
  18. local eph_body = nil
  19. if io.fileSize("/hdgnss.bin") > 1024 then
  20. local date = os.date("!*t")
  21. -- log.info("gnss", "当前系统时间", os.date())
  22. if date.year < 2024 then
  23. date = os.date("!*t")
  24. end
  25. if date.year > 2023 then
  26. local tm = io.readFile("/hdgnss_tm")
  27. if tm then
  28. local t = tonumber(tm)
  29. if t and (os.time() - t < 3600*2) then
  30. log.info("hdgnss", "重用星历文件")
  31. eph_body = io.readFile("/hdgnss.bin")
  32. else
  33. log.info("hdgnss", "星历过期了")
  34. os.remove("/hdgnss.bin")
  35. end
  36. else
  37. log.info("hdgnss", "星历时间有问题")
  38. end
  39. else
  40. log.info("hdgnss", "系统时间有问题")
  41. end
  42. end
  43. if http and not eph_body then
  44. -- AGNSS 已调通
  45. for i = 1, 3 do
  46. local code, _, body = http.request("GET", url, nil, nil, {timeout=3000}).wait()
  47. log.info("hdgnss", "AGNSS", code, body and #body or 0)
  48. if code == 200 and body and #body > 1024 then
  49. io.writeFile("/hdgnss.bin", body)
  50. sys.wait(1000)
  51. local date = os.date("!*t")
  52. if date.year > 2022 then
  53. io.writeFile("/hdgnss_tm", tostring(os.time()))
  54. end
  55. eph_body = body
  56. break
  57. end
  58. sys.wait(6 * 1000)
  59. end
  60. end
  61. if eph_body and #eph_body > 1024 then
  62. local body = eph_body
  63. -- for offset = 1, #body, 512 do
  64. -- -- log.info("hdgnss", "AGNSS", "write >>>", #body:sub(offset, offset + 511))
  65. -- -- uart.write(gps_uart_id, body:sub(offset, offset + 511))
  66. -- -- sys.waitUntil("UART2_SEND", 100)
  67. -- sys.wait(100) -- 等100ms反而更成功
  68. -- end
  69. -- uart.write(gps_uart_id, body)
  70. local offset = 1
  71. local size = #body
  72. while offset < size do
  73. -- 前两个字符是F1D9
  74. if body:byte(offset) == 0xF1 and body:byte(offset + 1) == 0xD9 then
  75. -- log.info("hdgnss", "星历数据", body:sub(1, 16):toHex())
  76. local len = body:byte(offset + 4) + body:byte(offset + 5) * 256
  77. local tmp = body:sub(offset, offset + len + 7)
  78. -- log.info("hdgnss", "写入星历片段", offset, len, #tmp, tmp:toHex())
  79. uart.write(gps_uart_id, tmp)
  80. offset = offset + len + 8
  81. sys.wait(20)
  82. else
  83. log.warn("hdgnss", "分隔出错了", offset, size)
  84. break
  85. end
  86. end
  87. end
  88. sys.wait(20)
  89. end
  90. local function exec_agnss()
  91. for i = 1, 3 do
  92. local ip = socket.localIP()
  93. if ip and ip ~= "0.0.0.0" then
  94. break
  95. end
  96. sys.waitUntil("IP_READY", 3000)
  97. end
  98. socket.sntp()
  99. sys.waitUntil("NTP_UPDATE", 1000)
  100. -- 注入当前时间
  101. if os.date("*t").year > 2023 then
  102. hdgnss.aidtime()
  103. sys.wait(100)
  104. end
  105. -- 读取之前的位置信息
  106. local lat, lng
  107. local gnssloc = io.readFile("/hdloc")
  108. if gnssloc then
  109. log.info("hdgnss", "最后已知位置信息", gnssloc)
  110. local tmp = gnssloc:split(",")
  111. if tmp and #tmp == 2 then
  112. lat = tonumber(tmp[1])
  113. lng = tonumber(tmp[2])
  114. end
  115. end
  116. -- 写入参考位置
  117. if lat and lng and lat ~= 0 and lng ~= 0 then
  118. hdgnss.aidpos(lat, lng)
  119. sys.wait(100)
  120. else
  121. log.info("hdgnss", "当前无辅助位置信息")
  122. end
  123. -- 发起基站定位, 暂时禁用
  124. if mobile and false then
  125. mobile.reqCellInfo(6)
  126. sys.waitUntil("CELL_INFO_UPDATE", 6000)
  127. local lat2, lng2, t = lbsLoc2.request(5000)
  128. log.info("hdgnss", "基站定位结果", lat2, lng2)
  129. if lat2 and lng2 then
  130. lat2 = tonumber(lat2:sub(1, 3) .. lat2:sub(5))
  131. lng2 = tonumber(lng2:sub(1, 3) .. lng2:sub(5))
  132. if lat2 and lng2 then
  133. lat = lat
  134. lng = lng
  135. log.info("hdgnss", "基站定位结果", lat, lng)
  136. hdgnss.aidpos(lat, lng)
  137. end
  138. end
  139. end
  140. hdgnss.aideph()
  141. -- sys.wait(1000)
  142. end
  143. function hdgnss.aidpos(lat, lng)
  144. local gps_uart_id = hdgnss.opts.uart_id
  145. -- AID-POS
  146. local str = string.char(
  147. 0xF1, 0xD9, -- 帧头
  148. 0x0B, 0x10, 0x11, 0x00, -- 指令ID: 0x0B 0x11, 载荷17字节
  149. 0x01 -- LLA 1, ECEF 0
  150. )
  151. -- lat = 234068458 1132310388
  152. -- 234072543 1132310160
  153. log.info("hdgnss", "参考坐标(单位1/10000000度)", lat, lng)
  154. str = str .. pack.pack("<IIII", lat, lng, 5000, 0)
  155. str = str .. hdcrc(str)
  156. log.info("hdgnss", "写入AID-POS", str:toHex())
  157. uart.write(gps_uart_id, str)
  158. end
  159. function hdgnss.aidtime()
  160. local gps_uart_id = hdgnss.opts.uart_id
  161. local date = os.date("!*t")
  162. if date.year > 2023 then
  163. -- AID-TIME, 时间精度要在3秒以内
  164. log.info("hdgnss", "当前时间", date.year, date.month, date.day, date.hour, date.min, date.sec)
  165. local str = string.char(
  166. 0xF1, 0xD9, -- 帧头
  167. 0x0B, 0x11, 0x14, 0x00, -- 指令ID: 0x0B 0x11, 载荷20字节
  168. 0x00, -- UTC 0, TNOW 1
  169. 0x00, -- 保留参数,填0
  170. 0x11, -- 闰秒
  171. date.year & 0xFF, date.year >> 8, -- 年
  172. date.month, -- 月
  173. date.day, -- 日
  174. date.hour, -- 小时
  175. date.min, -- 分钟
  176. date.sec, -- 秒
  177. 0x00, 0x00, 0x00, 0x00, -- 亚毫秒
  178. 0x00, 0x00, -- 时间精度(秒)
  179. 0x00, 0x00, 0x00, 0x00 -- 时间精度(亚毫秒)
  180. )
  181. str = str .. hdcrc(str)
  182. log.info("hdgnss", "写入AID-TIME", str:toHex())
  183. uart.write(gps_uart_id, str)
  184. -- sys.wait(20)
  185. end
  186. end
  187. function hdgnss.setup(opts)
  188. if not opts then
  189. opts = {}
  190. end
  191. if not opts.uart_id then
  192. opts.uart_id = 2
  193. end
  194. hdgnss.opts = opts
  195. end
  196. function hdgnss.start()
  197. log.debug("提醒", "室内无GNSS信号,定位不会成功, 要到空旷的室外,起码要看得到天空")
  198. local gps_uart_id = hdgnss.opts.uart_id
  199. local uart_forward = hdgnss.opts.uart_forward
  200. log.info("hdgnss", "start")
  201. libgnss.on("raw", function(data)
  202. -- sys.publish("uplink", nmea_topic, data, 1)
  203. if data:byte(1) == 0xF1 then
  204. log.info("hdgnss", "二进制协议数据", data:toHex())
  205. end
  206. end)
  207. uart.setup(gps_uart_id, 9600)
  208. if uart_forward then
  209. uart.setup(uart_forward, 115200)
  210. end
  211. pm.power(pm.GPS, true)
  212. sys.wait(250) -- GPNSS芯片启动需要时间,大概250ms
  213. -- 串口配置, 切换到115200
  214. uart.write(gps_uart_id, (string.fromHex("F1D9060008000000000000C20100D1E0")))
  215. sys.wait(20)
  216. uart.close(gps_uart_id)
  217. sys.wait(10)
  218. uart.setup(gps_uart_id, 115200)
  219. -- 调试日志,可选
  220. libgnss.debug(hdgnss.opts.debug)
  221. libgnss.bind(gps_uart_id, uart_forward)
  222. if not hdgnss.opts.no_agps then
  223. exec_agnss()
  224. end
  225. hdgnss.running = true
  226. end
  227. function hdgnss.stop()
  228. hdgnss.running = false
  229. if hdgnss.opts and hdgnss.opts.uart_id then
  230. uart.close(hdgnss.opts.uart_id)
  231. end
  232. end
  233. function hdgnss.saveloc()
  234. local rmc = libgnss.getRmc(1)
  235. log.info("hdgnss", "rmc", rmc.lat, rmc.lng)
  236. io.writeFile("/hdloc", string.format("%d,%d", rmc.lat, rmc.lng))
  237. end
  238. -- 订阅GNSS状态编码
  239. sys.subscribe("GNSS_STATE", function(event, ticks)
  240. -- event取值有
  241. -- FIXED 定位成功
  242. -- LOSE 定位丢失
  243. -- ticks是事件发生的时间,一般可以忽略
  244. log.info("hdgnss", "state", event, ticks)
  245. if event == "FIXED" then
  246. hdgnss.saveloc()
  247. end
  248. end)
  249. sys.taskInit(function()
  250. while 1 do
  251. sys.wait(600 * 1000) -- 10分钟检查一次
  252. local fixed = libgnss.isFix()
  253. if not fixed and not hdgnss.opts.no_agps and hdgnss.running then
  254. exec_agnss()
  255. end
  256. if fixed then
  257. hdgnss.saveloc()
  258. end
  259. end
  260. end)
  261. return hdgnss