gnss.lua 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. --[[
  2. @module gnss
  3. @summary gnss应用测试功能模块
  4. @version 1.0
  5. @date 2025.07.27
  6. @author 李源龙
  7. @usage
  8. 主要功能:
  9. 1、开启gnss定位,使用agps辅助定位
  10. 2、定位成功获取经纬度
  11. ]]
  12. local lbsLoc2 = require("lbsLoc2")
  13. --设置串口2
  14. local gps_uart_id = 2
  15. --设置gnss的模式为1,1为全卫星开启,2为单北斗开启
  16. local gnssmode=1
  17. local function agps()
  18. if libgnss.isFix() then return end
  19. local lat, lng
  20. -- 判断星历时间和下载星历
  21. while not socket.adapter(socket.dft()) do
  22. log.warn("airlbs_multi_cells_wifi_func", "wait IP_READY", socket.dft())
  23. -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
  24. -- 或者等待1秒超时退出阻塞等待状态;
  25. -- 注意:此处的1000毫秒超时不要修改的更长;
  26. -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
  27. -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
  28. -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
  29. local result=sys.waitUntil("IP_READY", 30000)
  30. if result == false then
  31. log.warn("gnss_agps", "wait IP_READY timeout")
  32. return
  33. end
  34. end
  35. socket.sntp()
  36. sys.waitUntil("NTP_UPDATE", 5000)
  37. local now = os.time()
  38. local agps_time = tonumber(io.readFile("/hxxt_tm") or "0") or 0
  39. log.info("os.time",now)
  40. log.info("agps_time",agps_time)
  41. if now - agps_time > 3600 or io.fileSize("/hxxt.dat") < 1024 then
  42. local url
  43. if gnssmode and 2 == gnssmode then
  44. -- 单北斗
  45. url = "http://download.openluat.com/9501-xingli/HXXT_BDS_AGNSS_DATA.dat"
  46. else
  47. url = "http://download.openluat.com/9501-xingli/HXXT_GPS_BDS_AGNSS_DATA.dat"
  48. end
  49. local code = http.request("GET", url, nil, nil, {dst="/hxxt.dat"}).wait()
  50. if code and code == 200 then
  51. log.info("exgnss.opts", "下载星历成功", url)
  52. io.writeFile("/hxxt_tm", tostring(now))
  53. else
  54. log.info("exgnss.opts", "下载星历失败", code)
  55. end
  56. else
  57. log.info("exgnss.opts", "星历不需要更新", now - agps_time)
  58. end
  59. --进行基站定位,给到gnss芯片一个大概的位置
  60. lat, lng = lbsLoc2.request(5000)
  61. -- local lat, lng, t = lbsLoc2.request(5000, "bs.openluat.com")
  62. -- log.info("lbsLoc2", lat, lng)
  63. if lat and lng then
  64. lat = tonumber(lat)
  65. lng = tonumber(lng)
  66. log.info("lbsLoc2", lat, lng)
  67. -- 转换单位
  68. local lat_dd,lat_mm = math.modf(lat)
  69. local lng_dd,lng_mm = math.modf(lng)
  70. lat = lat_dd * 100 + lat_mm * 60
  71. lng = lng_dd * 100 + lng_mm * 60
  72. end
  73. --获取基站定位失败则使用本地之前保存的位置
  74. if not lat then
  75. -- 获取最后的本地位置
  76. local locStr = io.readFile("/hxxtloc")
  77. if locStr then
  78. local jdata = json.decode(locStr)
  79. if jdata and jdata.lat then
  80. lat = jdata.lat
  81. lng = jdata.lng
  82. end
  83. end
  84. end
  85. -- 写入星历
  86. local agps_data = io.readFile("/hxxt.dat")
  87. if agps_data and #agps_data > 1024 then
  88. log.info("exgnss.opts", "写入星历数据", "长度", #agps_data)
  89. for offset=1,#agps_data,512 do
  90. log.info("exgnss", "AGNSS", "write >>>", #agps_data:sub(offset, offset + 511))
  91. uart.write(gps_uart_id, agps_data:sub(offset, offset + 511))
  92. sys.wait(100) -- 等100ms反而更成功
  93. end
  94. -- uart.write(gps_uart_id, agps_data)
  95. else
  96. log.info("exgnss.opts", "没有星历数据")
  97. return
  98. end
  99. -- "lat":23.4068813,"min":27,"valid":true,"day":27,"lng":113.2317505
  100. --如果没有经纬度的话,定位时间会变长,大概10-20s左右
  101. if not lat or not lng then
  102. -- lat, lng = 23.4068813, 113.2317505
  103. log.info("exgnss.opts", "没有GPS坐标", lat, lng)
  104. return --暂时不写入参考位置
  105. else
  106. log.info("exgnss.opts", "写入GPS坐标", lat, lng)
  107. end
  108. --写入时间
  109. local date = os.date("!*t")
  110. if date.year > 2023 then
  111. local str = string.format("$AIDTIME,%d,%d,%d,%d,%d,%d,000", date["year"], date["month"], date["day"],
  112. date["hour"], date["min"], date["sec"])
  113. log.info("exgnss.opts", "参考时间", str)
  114. uart.write(gps_uart_id, str .. "\r\n")
  115. sys.wait(20)
  116. end
  117. -- 写入参考位置
  118. local str = string.format("$AIDPOS,%.7f,%s,%.7f,%s,1.0\r\n",
  119. lat > 0 and lat or (0 - lat), lat > 0 and 'N' or 'S',
  120. lng > 0 and lng or (0 - lng), lng > 0 and 'E' or 'W')
  121. log.info("exgnss.opts", "写入AGPS参考位置", str)
  122. uart.write(gps_uart_id, str)
  123. end
  124. local function gnss_open()
  125. log.info("GPS", "start")
  126. libgnss.clear() -- 清空数据,兼初始化
  127. --设置串口波特率
  128. uart.setup(gps_uart_id, 115200)
  129. -- 打开GPS
  130. pm.power(pm.GPS, true)
  131. -- 绑定uart,底层自动处理GNSS数据
  132. -- 第二个参数是转发到虚拟UART, 方便上位机分析
  133. libgnss.bind(gps_uart_id, uart.VUART_0)
  134. sys.wait(200) -- GPNSS芯片启动需要时间
  135. -- 调试日志,可选
  136. libgnss.debug(true)
  137. -- 增加显示的语句
  138. uart.write(gps_uart_id, "$CFGMSG,0,1,1\r\n") -- GLL
  139. sys.wait(20)
  140. uart.write(gps_uart_id, "$CFGMSG,0,5,1\r\n") -- VTG
  141. sys.wait(20)
  142. uart.write(gps_uart_id, "$CFGMSG,0,6,1\r\n") -- ZDA
  143. sys.wait(20)
  144. sys.taskInit(agps)
  145. end
  146. sys.taskInit(gnss_open)
  147. --GNSS定位状态的消息处理函数:
  148. local function gnss_state(event, ticks)
  149. -- event取值有
  150. -- "FIXED":string类型 定位成功
  151. -- "LOSE": string类型 定位丢失
  152. -- ticks number类型 是事件发生的时间,一般可以忽略
  153. log.info("exgnss", "state", event)
  154. if event=="FIXED" then
  155. --获取rmc数据
  156. --json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位,本示例保留5位小数
  157. log.info("nmea", "rmc0", json.encode(libgnss.getRmc(0),"5f"))
  158. end
  159. end
  160. sys.subscribe("GNSS_STATE",gnss_state)