exgnss.lua 41 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. --[[
  2. @module exgnss
  3. @summary exgnss扩展库
  4. @version 1.0
  5. @date 2025.07.16
  6. @author 李源龙
  7. @usage
  8. -- 用法实例
  9. -- 注意:exgnss.lua适用的产品范围,只能用于合宙内部集成GNSS功能的产品,目前有Air780EGH,Air8000系列
  10. -- 提醒: 本库输出的坐标,均为 WGS84 坐标系
  11. -- 如需要在国内地图使用, 要转换成对应地图的坐标系, 例如 GCJ02 BD09
  12. -- 相关链接: https://lbsyun.baidu.com/index.php?title=coordinate
  13. -- 相关链接: https://www.openluat.com/GPS-Offset.html
  14. --关于exgnss的三种应用场景:
  15. exgnss.DEFAULT:
  16. --- exgnss应用模式1.
  17. -- 打开gnss后,gnss定位成功时,如果有回调函数,会调用回调函数
  18. -- 使用此应用模式调用exgnss.open打开的“gnss应用”,必须主动调用exgnss.close
  19. -- 或者exgnss.close_all才能关闭此“gnss应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  20. -- 通俗点说就是一直打开,除非自己手动关闭掉
  21. exgnss.TIMERORSUC:
  22. --- exgnss应用模式2.
  23. -- 打开gnss后,如果在gnss开启最大时长到达时,没有定位成功,如果有回调函数,
  24. -- 会调用回调函数,然后自动关闭此“gnss应用”
  25. -- 打开gnss后,如果在gnss开启最大时长内,定位成功,如果有回调函数,
  26. -- 会调用回调函数,然后自动关闭此“gnss应用”
  27. -- 打开gnss后,在自动关闭此“gnss应用”前,可以调用exgnss.close或者
  28. -- exgnss.close_all主动关闭此“gnss应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  29. -- 通俗点说就是设置规定时间打开,如果规定时间内定位成功就会自动关闭此应用,
  30. -- 如果没有定位成功,时间到了也会自动关闭此应用
  31. exgnss.TIMER:
  32. --- exgnss应用模式3.
  33. -- 打开gnss后,在gnss开启最大时长时间到达时,无论是否定位成功,如果有回调函数,
  34. -- 会调用回调函数,然后自动关闭此“gnss应用”
  35. -- 打开gnss后,在自动关闭此“gnss应用”前,可以调用exgnss.close或者exgnss.close_all
  36. -- 主动关闭此“gnss应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  37. -- 通俗点说就是设置规定时间打开,无论是否定位成功,到了时间都会自动关闭此应用,
  38. -- 和第二种的区别在于定位成功之后不会自动关闭,到时间之后才会自动关闭
  39. exgnss=require("exgnss")
  40. local function mode1_cb(tag)
  41. log.info("TAGmode1_cb+++++++++",tag)
  42. log.info("nmea", "rmc", json.encode(exgnss.rmc(2)))
  43. end
  44. local function mode2_cb(tag)
  45. log.info("TAGmode2_cb+++++++++",tag)
  46. log.info("nmea", "rmc", json.encode(exgnss.rmc(2)))
  47. end
  48. local function mode3_cb(tag)
  49. log.info("TAGmode3_cb+++++++++",tag)
  50. log.info("nmea", "rmc", json.encode(exgnss.rmc(2)))
  51. end
  52. local function gnss_fnc()
  53. local gnssotps={
  54. gnssmode=1, --1为卫星全定位,2为单北斗
  55. agps_enable=true, --是否使用AGPS,开启AGPS后定位速度更快,会访问服务器下载星历,星历时效性为北斗1小时,GPS4小时,默认下载星历的时间为1小时,即一小时内只会下载一次
  56. debug=true, --是否输出调试信息
  57. -- uart=2, --使用的串口,780EGH和8000默认串口2
  58. -- uartbaud=115200, --串口波特率,780EGH和8000默认115200
  59. -- bind=1, --绑定uart端口进行GNSS数据读取,是否设置串口转发,指定串口号
  60. -- rtc=false --定位成功后自动设置RTC true开启,flase关闭
  61. ----因为GNSS使用辅助定位的逻辑,是模块下载星历文件,然后把数据发送给GNSS芯片,
  62. ----芯片解析星历文件需要10-30s,默认GNSS会开启20s,该逻辑如果不执行,会导致下一次GNSS开启定位是冷启动,
  63. ----定位速度慢,大概35S左右,所以默认开启,如果可以接受下一次定位是冷启动,可以把auto_open设置成false
  64. ----需要注意的是热启动在定位成功之后,需要再开启3s左右才能保证本次的星历获取完成,如果对定位速度有要求,建议这么处理
  65. -- auto_open=false
  66. }
  67. --设置gnss参数
  68. exgnss.setup(gnssotps)
  69. --开启gnss应用
  70. exgnss.open(exgnss.TIMER,{tag="MODE1",val=60,cb=mode1_cb})
  71. exgnss.open(exgnss.DEFAULT,{tag="MODE2",cb=mode2_cb})
  72. exgnss.open(exgnss.TIMERORSUC,{tag="MODE3",val=60,cb=mode3_cb})
  73. sys.wait(40000)
  74. log.info("关闭一个gnss应用,然后查看下所有应用的状态")
  75. --关闭一个gnss应用
  76. exgnss.close(exgnss.TIMER,{tag="MODE1"})
  77. --查询3个gnss应用状态
  78. log.info("gnss应用状态1",exgnss.is_active(exgnss.TIMER,{tag="MODE1"}))
  79. log.info("gnss应用状态2",exgnss.is_active(exgnss.DEFAULT,{tag="MODE2"}))
  80. log.info("gnss应用状态3",exgnss.is_active(exgnss.TIMERORSUC,{tag="MODE3"}))
  81. sys.wait(10000)
  82. --关闭所有gnss应用
  83. exgnss.close_all()
  84. --查询3个gnss应用状态
  85. log.info("gnss应用状态1",exgnss.is_active(exgnss.TIMER,{tag="MODE1"}))
  86. log.info("gnss应用状态2",exgnss.is_active(exgnss.DEFAULT,{tag="MODE2"}))
  87. log.info("gnss应用状态3",exgnss.is_active(exgnss.TIMERORSUC,{tag="MODE3"}))
  88. --查询最后一次定位结果
  89. local loc= exgnss.last_loc()
  90. if loc then
  91. log.info("lastloc", loc.lat,loc.lng)
  92. end
  93. end
  94. sys.taskInit(gnss_fnc)
  95. --GNSS定位状态的消息处理函数:
  96. local function gnss_state(event, ticks)
  97. -- event取值有
  98. -- "FIXED":string类型 定位成功
  99. -- "LOSE": string类型 定位丢失
  100. -- "CLOSE": string类型 GNSS关闭,仅配合使用gnss.lua有效
  101. -- ticks number类型 是事件发生的时间,一般可以忽略
  102. log.info("exgnss", "state", event)
  103. end
  104. sys.subscribe("GNSS_STATE",gnss_state)
  105. ]]
  106. local exgnss = {}
  107. --gnss开启标志,true表示开启状态,false或者nil表示关闭状态
  108. local openFlag
  109. --gnss定位标志,true表示,其余表示未定位
  110. local fixFlag=nil
  111. --串口配置
  112. local uart_baudrate = 115200
  113. local uart_id = 2
  114. --gnss 的串口线程是否在工作;
  115. local taskFlag=false
  116. local agpsFlag=false
  117. local timeres=false
  118. --保存经纬度到文件区
  119. local function save_loc(lat,lng)
  120. if not lat or not lng then
  121. if libgnss.isFix() then
  122. local rmc = libgnss.getRmc(0)
  123. if rmc then
  124. lat, lng = rmc.lat, rmc.lng
  125. end
  126. end
  127. end
  128. if lat and lng then
  129. -- log.info("待保存的GPS位置", lat, lng)
  130. local locStr = string.format('{"lat":%.5f,"lng":%.5f}', lat, lng)
  131. -- log.info("gnss", "保存GPS位置", locStr)
  132. io.writeFile("/hxxtloc", locStr)
  133. end
  134. if timeres then
  135. local now = os.time()
  136. io.writeFile("/hxxt_tm", tostring(now))
  137. timeres=false
  138. -- log.info("now", now)
  139. end
  140. end
  141. local tid
  142. local timetid
  143. local function timer_fnc()
  144. timeres=true
  145. local now = os.time()
  146. io.writeFile("/hxxt_tm", tostring(now))
  147. end
  148. sys.subscribe("GNSS_STATE", function(event)
  149. -- log.info("libagps","libagps is "..event)
  150. if event == "FIXED" then
  151. save_loc()
  152. tid=sys.timerLoopStart(save_loc,600000)
  153. timetid=sys.timerStart(timer_fnc,10000)
  154. if exgnss.opts.rtc==true then
  155. sys.publish("NTP_UPDATE")
  156. end
  157. elseif event == "LOSE" or event == "CLOSE" then
  158. -- log.info("libagps","libagps is close")
  159. sys.timerStop(tid)
  160. sys.timerStop(timetid)
  161. end
  162. end)
  163. --agps操作,联网访问服务器获取星历数据
  164. local function agps()
  165. local lat, lng
  166. --此逻辑在agps定位成功之后,还会继续开启10s-15s,
  167. --原因是因为如果第一次冷启动之后,定位成功之后,
  168. --如果直接关闭gnss会导致gnss芯片的星历没有解析完毕,会影响下一次的定位为冷启动
  169. --如果对功耗有需求,需要定位快,可以每次都使用agps,不需要这句,直接屏蔽掉即可
  170. --代价是每次定位都会进行基站定位,
  171. if exgnss.opts.auto_open~= false then
  172. log.info("libagps","libagps is open")
  173. exgnss.open(exgnss.TIMER,{tag="libagps",val=20})
  174. else
  175. end
  176. -- 判断星历时间和下载星历
  177. local now = os.time()
  178. local agps_time = tonumber(io.readFile("/hxxt_tm") or "0") or 0
  179. log.info("os.time",now)
  180. log.info("agps_time",agps_time)
  181. if now - agps_time > 3600 or io.fileSize("/hxxt.dat") < 1024 then
  182. local url = exgnss.opts.url
  183. if not exgnss.opts.url then
  184. if exgnss.opts.gnssmode and 2 == exgnss.opts.gnssmode then
  185. -- 单北斗
  186. url = "http://download.openluat.com/9501-xingli/HXXT_BDS_AGNSS_DATA.dat"
  187. else
  188. url = "http://download.openluat.com/9501-xingli/HXXT_GPS_BDS_AGNSS_DATA.dat"
  189. end
  190. end
  191. local code = http.request("GET", url, nil, nil, {dst="/hxxt.dat"}).wait()
  192. if code and code == 200 then
  193. log.info("exgnss.opts", "下载星历成功", url)
  194. io.writeFile("/hxxt_tm", tostring(now))
  195. else
  196. log.info("exgnss.opts", "下载星历失败", code)
  197. end
  198. else
  199. log.info("exgnss.opts", "星历不需要更新", now - agps_time)
  200. end
  201. --进行基站定位,给到gnss芯片一个大概的位置
  202. if mobile then
  203. local lbsLoc2 = require("lbsLoc2")
  204. lat, lng = lbsLoc2.request(5000)
  205. -- local lat, lng, t = lbsLoc2.request(5000, "bs.openluat.com")
  206. -- log.info("lbsLoc2", lat, lng)
  207. if lat and lng then
  208. lat = tonumber(lat)
  209. lng = tonumber(lng)
  210. log.info("lbsLoc2", lat, lng)
  211. -- 转换单位
  212. local lat_dd,lat_mm = math.modf(lat)
  213. local lng_dd,lng_mm = math.modf(lng)
  214. lat = lat_dd * 100 + lat_mm * 60
  215. lng = lng_dd * 100 + lng_mm * 60
  216. end
  217. elseif wlan then
  218. -- wlan.scan()
  219. -- sys.waitUntil("WLAN_SCAN_DONE", 5000)
  220. end
  221. --获取基站定位失败则使用本地之前保存的位置
  222. if not lat then
  223. -- 获取最后的本地位置
  224. local locStr = io.readFile("/hxxtloc")
  225. if locStr then
  226. local jdata = json.decode(locStr)
  227. if jdata and jdata.lat then
  228. lat = jdata.lat
  229. lng = jdata.lng
  230. end
  231. end
  232. end
  233. local gps_uart_id = uart_id
  234. -- 写入星历
  235. local agps_data = io.readFile("/hxxt.dat")
  236. if agps_data and #agps_data > 1024 then
  237. log.info("exgnss.opts", "写入星历数据", "长度", #agps_data)
  238. for offset=1,#agps_data,512 do
  239. log.info("exgnss", "AGNSS", "write >>>", #agps_data:sub(offset, offset + 511))
  240. uart.write(gps_uart_id, agps_data:sub(offset, offset + 511))
  241. sys.wait(100) -- 等100ms反而更成功
  242. end
  243. -- uart.write(gps_uart_id, agps_data)
  244. else
  245. log.info("exgnss.opts", "没有星历数据")
  246. return
  247. end
  248. -- "lat":23.4068813,"min":27,"valid":true,"day":27,"lng":113.2317505
  249. --如果没有经纬度的话,定位时间会变长,大概10-20s左右
  250. if not lat or not lng then
  251. -- lat, lng = 23.4068813, 113.2317505
  252. log.info("exgnss.opts", "没有GPS坐标", lat, lng)
  253. return --暂时不写入参考位置
  254. else
  255. log.info("exgnss.opts", "写入GPS坐标", lat, lng)
  256. end
  257. --写入时间
  258. local date = os.date("!*t")
  259. if date.year > 2023 then
  260. local str = string.format("$AIDTIME,%d,%d,%d,%d,%d,%d,000", date["year"], date["month"], date["day"],
  261. date["hour"], date["min"], date["sec"])
  262. log.info("exgnss.opts", "参考时间", str)
  263. uart.write(gps_uart_id, str .. "\r\n")
  264. sys.wait(20)
  265. end
  266. -- 写入参考位置
  267. local str = string.format("$AIDPOS,%.7f,%s,%.7f,%s,1.0\r\n",
  268. lat > 0 and lat or (0 - lat), lat > 0 and 'N' or 'S',
  269. lng > 0 and lng or (0 - lng), lng > 0 and 'E' or 'W')
  270. log.info("exgnss.opts", "写入AGPS参考位置", str)
  271. uart.write(gps_uart_id, str)
  272. -- 结束
  273. exgnss.opts.agps_tm = now
  274. agpsFlag=true
  275. end
  276. --执行agps操作判断
  277. local function is_agps()
  278. -- 如果不是强制写入AGPS信息, 而且是已经定位成功的状态,那就没必要了
  279. if libgnss.isFix() then return end
  280. -- 先判断一下时间
  281. while not socket.adapter() do
  282. log.warn("gnss_agps", "wait IP_READY")
  283. -- 在此处阻塞等待WIFI连接成功的消息"IP_READY"
  284. -- 或者等待30秒超时退出阻塞等待状态
  285. local result=sys.waitUntil("IP_READY", 30000)
  286. if result == false then
  287. log.warn("gnss_agps", "wait IP_READY timeout")
  288. return
  289. end
  290. end
  291. if not exgnss.opts.agps_tm then
  292. socket.sntp()
  293. sys.waitUntil("NTP_UPDATE", 5000)
  294. end
  295. local now = os.time()
  296. local agps_time = tonumber(io.readFile("/hxxt_tm") or "0") or 0
  297. -- if ((not exgnss.opts.agps_tm) and (now - agps_time > 300)) or now - agps_time > 3600 then
  298. if not exgnss.opts.agps_tm or now - agps_time > 3600 then
  299. -- 执行AGPS
  300. log.info("exgnss.opts", "开始执行AGPS")
  301. sys.taskInit(agps)
  302. else
  303. log.info("exgnss.opts", "暂不需要写入AGPS")
  304. end
  305. end
  306. --打开gnss,内部函数使用,不推荐给脚本层使用
  307. local function fnc_open()
  308. if openFlag then return end
  309. libgnss.clear() -- 清空数据,兼初始化
  310. uart.setup(uart_id, uart_baudrate)
  311. -- pm.power(pm.GPS, false)
  312. pm.power(pm.GPS, true)
  313. if exgnss.opts.gnssmode==1 then
  314. --默认全开启
  315. log.info("全卫星开启")
  316. elseif exgnss.opts.gnssmode==2 then
  317. --默认开启单北斗
  318. sys.timerStart(function()
  319. uart.write(uart_id, "$CFGSYS,h10\r\n")
  320. end,200)
  321. log.info("单北斗开启")
  322. end
  323. if exgnss.opts.debug==true then
  324. log.info("debug开启")
  325. libgnss.debug(true)
  326. end
  327. if type(exgnss.opts.bind)=="number" then
  328. log.info("绑定bind事件")
  329. libgnss.bind(uart_id,exgnss.opts.bind)
  330. else
  331. libgnss.bind(uart_id)
  332. end
  333. if exgnss.opts.rtc==true then
  334. log.info("rtc开启")
  335. libgnss.rtcAuto(true)
  336. end
  337. if exgnss.opts.agps_enable==true then
  338. log.info("agps开启")
  339. sys.taskInit(is_agps)
  340. end
  341. --设置输出VTG内容
  342. sys.timerStart(function()
  343. uart.write(uart_id,"$CFGMSG,0,5,1,1\r\n")
  344. end,800)
  345. --设置输出ZDA内容
  346. sys.timerStart(function()
  347. uart.write(uart_id,"$CFGMSG,0,6,1,1\r\n")
  348. end,900)
  349. openFlag = true
  350. sys.publish("GNSS_STATE","OPEN")
  351. log.info("exgnss._open")
  352. end
  353. --关闭gnss,内部函数使用,不推荐给脚本层使用
  354. local function fnc_close()
  355. if not openFlag then return end
  356. save_loc()
  357. pm.power(pm.GPS, false)
  358. uart.close(uart_id)
  359. openFlag = false
  360. fixFlag = false
  361. timeres=false
  362. sys.publish("GNSS_STATE","CLOSE",fixFlag)
  363. log.info("exgnss._close")
  364. libgnss.clear()
  365. end
  366. --- gnss应用模式1.
  367. --
  368. -- 打开gnss后,gnss定位成功时,如果有回调函数,会调用回调函数
  369. --
  370. -- 使用此应用模式调用gnss.open打开的“gnss应用”,必须主动调用gnss.close或者gnss.close_all才能关闭此“gnss应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  371. exgnss.DEFAULT = 1
  372. --- gnss应用模式2.
  373. --
  374. -- 打开gnss后,如果在gnss开启最大时长到达时,没有定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“gnss应用”
  375. --
  376. -- 打开gnss后,如果在gnss开启最大时长内,定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“gnss应用”
  377. --
  378. -- 打开gnss后,在自动关闭此“gnss应用”前,可以调用gnss.close或者gnss.close_all主动关闭此“gnss应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  379. exgnss.TIMERORSUC = 2
  380. --- gnss应用模式3.
  381. --
  382. -- 打开gnss后,在gnss开启最大时长时间到达时,无论是否定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“gnss应用”
  383. --
  384. -- 打开gnss后,在自动关闭此“gnss应用”前,可以调用gnss.close或者gnss.close_all主动关闭此“gnss应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  385. exgnss.TIMER = 3
  386. --“gnss应用”表
  387. local tList = {}
  388. --[[
  389. 函数名:delItem
  390. 功能 :从“gnss应用”表中删除一项“gnss应用”,并不是真正的删除,只是设置一个无效标志
  391. 参数 :
  392. mode:gnss应用模式
  393. para:
  394. para.tag:“gnss应用”标记
  395. para.val:gnss开启最大时长
  396. para.cb:回调函数
  397. 返回值:无
  398. ]]
  399. local function delItem(mode,para)
  400. for i=1,#tList do
  401. --标志有效 并且 gnss应用模式相同 并且 “gnss应用”标记相同
  402. if tList[i].flag and tList[i].mode==mode and tList[i].para.tag==para.tag then
  403. --设置无效标志
  404. tList[i].flag,tList[i].delay = false
  405. break
  406. end
  407. end
  408. end
  409. --[[
  410. 函数名:addItem
  411. 功能 :新增一项“gnss应用”到“gnss应用”表
  412. 参数 :
  413. mode:gnss应用模式
  414. para:
  415. para.tag:“gnss应用”标记
  416. para.val:gnss开启最大时长
  417. para.cb:回调函数
  418. 返回值:无
  419. ]]
  420. local function addItem(mode,para)
  421. --删除相同的“gnss应用”
  422. delItem(mode,para)
  423. local item,i,fnd = {flag=true, mode=mode, para=para}
  424. --如果是TIMERORSUC或者TIMER模式,初始化gnss工作剩余时间
  425. if mode==exgnss.TIMERORSUC or mode==exgnss.TIMER then item.para.remain = para.val end
  426. for i=1,#tList do
  427. --如果存在无效的“gnss应用”项,直接使用此位置
  428. if not tList[i].flag then
  429. tList[i] = item
  430. fnd = true
  431. break
  432. end
  433. end
  434. --新增一项
  435. if not fnd then table.insert(tList,item) end
  436. end
  437. --退出GNSS定时器
  438. local function existTimerItem()
  439. for i=1,#tList do
  440. if tList[i].flag and (tList[i].mode==exgnss.TIMERORSUC or tList[i].mode==exgnss.TIMER or tList[i].para.delay) then return true end
  441. end
  442. end
  443. --GNSS定时器
  444. local function timerFnc()
  445. for i=1,#tList do
  446. if tList[i].flag then
  447. log.info("exgnss.timerFnc@"..i,tList[i].mode,tList[i].para.tag,tList[i].para.val,tList[i].para.remain,tList[i].para.delay)
  448. local rmn,dly,md,cb = tList[i].para.remain,tList[i].para.delay,tList[i].mode,tList[i].para.cb
  449. if rmn and rmn>0 then
  450. tList[i].para.remain = rmn-1
  451. end
  452. if dly and dly>0 then
  453. tList[i].para.delay = dly-1
  454. end
  455. rmn = tList[i].para.remain
  456. if libgnss.isFix() and md==exgnss.TIMER and rmn==0 and not tList[i].para.delay then
  457. tList[i].para.delay = 1
  458. end
  459. dly = tList[i].para.delay
  460. if libgnss.isFix() then
  461. if dly and dly==0 then
  462. if cb then cb(tList[i].para.tag) end
  463. if md == exgnss.DEFAULT then
  464. tList[i].para.delay = nil
  465. else
  466. exgnss.close(md,tList[i].para)
  467. end
  468. end
  469. else
  470. if rmn and rmn == 0 then
  471. if cb then cb(tList[i].para.tag) end
  472. exgnss.close(md,tList[i].para)
  473. end
  474. end
  475. end
  476. end
  477. if existTimerItem() then sys.timerStart(timerFnc,1000) end
  478. end
  479. --[[
  480. 函数名:statInd
  481. 功能 :处理gnss定位成功的消息
  482. 参数 :
  483. evt:gnss消息类型
  484. 返回值:无
  485. ]]
  486. local function statInd(evt)
  487. --定位成功的消息
  488. if evt == "FIXED" then
  489. fixFlag = true
  490. for i=1,#tList do
  491. log.info("exgnss.statInd@"..i,tList[i].flag,tList[i].mode,tList[i].para.tag,tList[i].para.val,tList[i].para.remain,tList[i].para.delay,tList[i].para.cb)
  492. if tList[i].flag then
  493. if tList[i].mode ~= exgnss.TIMER then
  494. tList[i].para.delay = 1
  495. if tList[i].mode == exgnss.DEFAULT then
  496. if existTimerItem() then sys.timerStart(timerFnc,1000) end
  497. end
  498. end
  499. end
  500. end
  501. end
  502. end
  503. --[[
  504. 设置gnss定位参数
  505. @api exgnss.setup(opts)
  506. @table opts gnss定位参数,可选值gnssmode:定位卫星模式,1为卫星全定位,2为单北斗,默认为卫星全定位
  507. agps_enable:是否启用AGPS,true为启用,false为不启用,默认为false
  508. debug:是否输出调试信息到luatools,true为输出,false为不输出,默认为false
  509. uart:GNSS串口配置,780EGH和8000默认为uart2,可不填
  510. uartbaud:GNSS串口波特率,780EGH和8000默认为115200,可不填
  511. bind:绑定uart端口进行GNSS数据读取,是否设置串口转发,指定串口号,不需要转发可不填
  512. rtc:定位成功后自动设置RTC true开启,flase关闭,默认为flase,不需要可不填
  513. @return nil 无返回值
  514. @usage
  515. local gnssotps={
  516. gnssmode=1, --1为卫星全定位,2为单北斗
  517. agps_enable=true, --是否使用AGPS,开启AGPS后定位速度更快,会访问服务器下载星历,星历时效性为北斗1小时,GPS4小时,默认下载星历的时间为1小时,即一小时内只会下载一次
  518. debug=true, --是否输出调试信息
  519. -- uart=2, --使用的串口,780EGH和8000默认串口2
  520. -- uartbaud=115200, --串口波特率,780EGH和8000默认115200
  521. -- bind=1, --绑定uart端口进行GNSS数据读取,是否设置串口转发,指定串口号
  522. -- rtc=false --定位成功后自动设置RTC true开启,flase关闭
  523. ----因为GNSS使用辅助定位的逻辑,是模块下载星历文件,然后把数据发送给GNSS芯片,
  524. ----芯片解析星历文件需要10-30s,默认GNSS会开启20s,该逻辑如果不执行,会导致下一次GNSS开启定位是冷启动,
  525. ----定位速度慢,大概35S左右,所以默认开启,如果可以接受下一次定位是冷启动,可以把auto_open设置成false
  526. ----需要注意的是热启动在定位成功之后,需要再开启3s左右才能保证本次的星历获取完成,如果对定位速度有要求,建议这么处理
  527. -- auto_open=false
  528. }
  529. exgnss.setup(gnssotps)
  530. ]]
  531. function exgnss.setup(opts)
  532. exgnss.opts=opts
  533. if hmeta.model():find("780EGH") or hmeta.model():find("8000") then
  534. uart_id=2
  535. uart_baudrate=115200
  536. else
  537. if exgnss.opts.uart_id then
  538. uart_id=exgnss.opts.uart_id
  539. else
  540. uart_id=2
  541. end
  542. if exgnss.opts.uartbaud then
  543. uart_baudrate=exgnss.opts.uartbaud
  544. else
  545. uart_baudrate=115200
  546. end
  547. end
  548. end
  549. --[[
  550. 打开一个“gnss应用”
  551. @api exgnss.open(mode,para)
  552. @number mode gnss应用模式,支持gnss.DEFAULT,gnss.TIMERORSUC,gnss.TIMER三种
  553. @param para table类型,gnss应用参数,para.tag:string类型,gnss应用标记,para.val:number类型,gnss应用开启最大时长,单位:秒,mode参数为gnss.TIMERORSUC或者gnss.TIMER时,此值才有意义;使用close接口时,不需要传入此参数,para.cb:gnss应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用close接口时,不需要传入此参数
  554. @return nil 无返回值
  555. @usage
  556. -- “gnss应用”:指的是使用gnss功能的一个应用
  557. -- 例如,假设有如下3种需求,要打开gnss,则一共有3个“gnss应用”:
  558. -- “gnss应用1”:每隔1分钟打开一次gnss
  559. -- “gnss应用2”:设备发生震动时打开gnss
  560. -- “gnss应用3”:收到一条特殊短信时打开gnss
  561. -- 只有所有“gnss应用”都关闭了,才会去真正关闭gnss
  562. -- 每个“gnss应用”打开或者关闭gnss时,最多有4个参数,其中 gnss应用模式和gnss应用标记 共同决定了一个唯一的“gnss应用”:
  563. -- 1、gnss应用模式(必选)
  564. -- 2、gnss应用标记(必选)
  565. -- 3、gnss开启最大时长[可选]
  566. -- 4、回调函数[可选]
  567. -- 例如gnss.open(exgnss.TIMER,{tag="MODE1",val=60,cb=mode1_cb})
  568. -- exgnss.TIMER为gnss应用模式,"MODE1"为gnss应用标记,60秒为gnss开启最大时长,mode1_cb为回调函数
  569. exgnss.open(exgnss.TIMER,{tag="MODE1",val=60,cb=mode1_cb})
  570. exgnss.open(exgnss.DEFAULT,{tag="MODE2",cb=mode2_cb})
  571. exgnss.open(exgnss.TIMERORSUC,{tag="MODE3",val=60,cb=mode3_cb})
  572. ]]
  573. function exgnss.open(mode,para)
  574. assert((para and type(para) == "table" and para.tag and type(para.tag) == "string"),"exgnss.open para invalid")
  575. log.info("exgnss.open",mode,para.tag,para.val,para.cb)
  576. --如果gnss定位成功
  577. if libgnss.isFix() then
  578. if mode~=exgnss.TIMER then
  579. --执行回调函数
  580. if para.cb then para.cb(para.tag) end
  581. if mode==exgnss.TIMERORSUC then return end
  582. end
  583. end
  584. addItem(mode,para)
  585. --真正去打开gnss
  586. fnc_open()
  587. --启动1秒的定时器
  588. if existTimerItem() and not sys.timerIsActive(timerFnc) then
  589. sys.timerStart(timerFnc,1000)
  590. end
  591. end
  592. --[[
  593. 关闭一个“gnss应用”,只是从逻辑上关闭一个gnss应用,并不一定真正关闭gnss,是有所有的gnss应用都处于关闭状态,才会去真正关闭gnss
  594. @api exgnss.close()
  595. @number mode gnss应用模式,支持gnss.DEFAULT,gnss.TIMERORSUC,gnss.TIMER三种
  596. @param para table类型,gnss应用参数,para.tag:string类型,gnss应用标记,para.val:number类型,gnss应用开启最大时长,单位:秒,mode参数为gnss.TIMERORSUC或者gnss.TIMER时,此值才有意义;使用close接口时,不需要传入此参数,para.cb:gnss应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用close接口时,不需要传入此参数
  597. @return nil 无返回值
  598. @usage
  599. exgnss.open(exgnss.TIMER,{tag="MODE1",val=60,cb=mode1_cb})
  600. exgnss.close(exgnss.TIMER,{tag="MODE1"})
  601. ]]
  602. function exgnss.close(mode,para)
  603. assert((para and type(para)=="table" and para.tag and type(para.tag)=="string"),"exgnss.close para invalid")
  604. log.info("exgnss.close",mode,para.tag,para.val,para.cb)
  605. --删除此“gnss应用”
  606. delItem(mode,para)
  607. local valid,i
  608. for i=1,#tList do
  609. if tList[i].flag then
  610. valid = true
  611. end
  612. end
  613. --如果没有一个“gnss应用”有效,则关闭gnss
  614. if not valid then fnc_close() end
  615. end
  616. --[[
  617. 关闭所有“gnss应用”
  618. @api exgnss.close_all()
  619. @return nil 无返回值
  620. @usage
  621. exgnss.open(exgnss.TIMER,{tag="MODE1",val=60,cb=mode1_cb})
  622. exgnss.open(exgnss.DEFAULT,{tag="MODE2",cb=mode2_cb})
  623. exgnss.open(exgnss.TIMERORSUC,{tag="MODE3",val=60,cb=mode3_cb})
  624. exgnss.close_all()
  625. ]]
  626. function exgnss.close_all()
  627. for i=1,#tList do
  628. if tList[i].flag and tList[i].para.cb then tList[i].para.cb(tList[i].para.tag) end
  629. exgnss.close(tList[i].mode,tList[i].para)
  630. end
  631. end
  632. --[[
  633. 判断一个“gnss应用”是否处于激活状态
  634. @api exgnss.is_active(mode,para)
  635. @number mode gnss应用模式,支持gnss.DEFAULT,gnss.TIMERORSUC,gnss.TIMER三种
  636. @param para table类型,gnss应用参数,para.tag:string类型,gnss应用标记,para.val:number类型,gnss应用开启最大时长,单位:秒,mode参数为gnss.TIMERORSUC或者gnss.TIMER时,此值才有意义;使用close接口时,不需要传入此参数,para.cb:gnss应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用close接口时,不需要传入此参数,gnss应用模式和gnss应用标记唯一确定一个“gnss应用”,调用本接口查询状态时,mode和para.tag要和gnss.open打开一个“gnss应用”时传入的mode和para.tag保持一致
  637. @return bool result,处于激活状态返回true,否则返回nil
  638. @usage
  639. exgnss.open(exgnss.TIMER,{tag="MODE1",val=60,cb=mode1_cb})
  640. exgnss.open(exgnss.DEFAULT,{tag="MODE2",cb=mode2_cb})
  641. exgnss.open(exgnss.TIMERORSUC,{tag="MODE3",val=60,cb=mode3_cb})
  642. log.info("gnss应用状态1",exgnss.is_active(exgnss.TIMER,{tag="MODE1"}))
  643. log.info("gnss应用状态2",exgnss.is_active(exgnss.DEFAULT,{tag="MODE2"}))
  644. log.info("gnss应用状态3",exgnss.is_active(exgnss.TIMERORSUC,{tag="MODE3"}))
  645. ]]
  646. function exgnss.is_active(mode,para)
  647. assert((para and type(para)=="table" and para.tag and type(para.tag)=="string"),"exgnss.is_active para invalid")
  648. for i=1,#tList do
  649. if tList[i].flag and tList[i].mode==mode and tList[i].para.tag==para.tag then return true end
  650. end
  651. end
  652. sys.subscribe("GNSS_STATE",statInd)
  653. --[[
  654. 当前是否已经定位成功
  655. @api exgnss.is_fix()
  656. @return boolean true/false,定位成功返回true,否则返回false
  657. @usage
  658. log.info("nmea", "is_fix", exgnss.is_fix())
  659. ]]
  660. function exgnss.is_fix()
  661. return libgnss.isFix()
  662. end
  663. --[[
  664. 获取number类型的位置和速度信息
  665. @api exgnss.int_location(speed_type)
  666. @number 速度单位,默认是m/h,
  667. 0 - m/h 米/小时, 默认值, 整型
  668. 1 - m/s 米/秒, 浮点数
  669. 2 - km/h 千米/小时, 浮点数
  670. 3 - kn/h 英里/小时, 浮点数
  671. @return number lat数据, 格式为 DDDDDDDDD,示例:343482649,DDDDDDDDD格式是由DD.DDDDDDD*10000000转换而来,目的是作为整数,方便某些场景使用
  672. @return number lng数据, 格式为 DDDDDDDDD,示例:1135039700,DDDDDDDDD格式是由DD.DDDDDDD*10000000转换而来,目的是作为整数,方便某些场景使用
  673. @return number speed数据, 单位根据speed_type决定,m/h, m/s, km/h, kn/h
  674. @usage
  675. --DDDDDDDDD格式是由DD.DDDDDDD*10000000转换而来,目的是作为整数,方便某些场景使用,示例:343482649对应的原始值是34.3482649
  676. -- 该数据是通过RMC转换的,如果想获取更详细的可以用exgnss.rmc(1)
  677. -- speed数据默认 米/小时,返回值例如:343482649 1135039700 390m/h
  678. log.info("nmea", "loc", exgnss.int_location())
  679. -- speed数据米/秒,返回值例如:343482649 1135039700 0.1085478m/s
  680. log.info("nmea", "loc", exgnss.int_location(1))
  681. -- speed数据千米/小时,返回值例如:343482649 1135039700 0.3907720km/h
  682. log.info("nmea", "loc", exgnss.int_location(2))
  683. -- speed数据英里/小时,返回值例如:343482649 1135039700 0.2110000kn/h
  684. log.info("nmea", "loc", exgnss.int_location(3))
  685. ]]
  686. function exgnss.int_location(speed_type)
  687. return libgnss.getIntLocation(speed_type)
  688. end
  689. --[[
  690. 获取RMC的信息,经纬度,时间,速度,航向,定位是否有效,磁偏角
  691. @api exgnss.rmc(lnglat_mode)
  692. @number 经纬度数据的格式, 0-ddmm.mmmmm格式, 1-DDDDDDDDD格式, 2-DD.DDDDDDD格式, 3-原始RMC字符串
  693. @return table/string rmc数据
  694. @usage
  695. -- 解析nmea
  696. log.info("nmea", "rmc", json.encode(exgnss.rmc(2)))
  697. -- 实例输出,获取值的解释
  698. -- {
  699. -- "course":344.9920044, // 地面航向,单位为度,从北向起顺时针计算
  700. -- "valid":true, // true定位成功,false定位丢失
  701. -- "lat":34.5804405, // 纬度, 正数为北纬, 负数为南纬
  702. -- "lng":113.8399506, // 经度, 正数为东经, 负数为西经
  703. -- "variation":0, // 磁偏角,固定为0
  704. -- "speed":0.2110000 // 地面速度, 单位为"节"
  705. -- "year":2023, // 年份
  706. -- "month":1, // 月份, 1-12
  707. -- "day":5, // 月份天, 1-31
  708. -- "hour":7, // 小时,0-23
  709. -- "min":23, // 分钟,0-59
  710. -- "sec":20, // 秒,0-59
  711. -- }
  712. --模式0示例:
  713. --json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位,本示例保留5位小数
  714. log.info("nmea", "rmc0", json.encode(exgnss.rmc(0),"5f"))
  715. {"variation":0,"lat":3434.82666,"min":54,"valid":true,"day":17,"lng":11350.39746,"speed":0.21100,"year":2025,"month":7,"sec":30,"hour":11,"course":344.99200}
  716. --模式1示例:
  717. --DDDDDDDDD格式是由DD.DDDDDDD*10000000转换而来,目的是作为整数,方便某些场景使用
  718. log.info("nmea", "rmc1", json.encode(exgnss.rmc(1)))
  719. {"variation":0,"lat":345804414,"min":54,"valid":true,"day":17,"lng":1138399500,"speed":0.2110000,"year":2025,"month":7,"sec":30,"hour":11,"course":344.9920044}
  720. --模式2示例:
  721. --json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位
  722. log.info("nmea", "rmc2", json.encode(exgnss.rmc(2)))
  723. {"variation":0,"lat":34.5804405,"min":54,"valid":true,"day":17,"lng":113.8399506,"speed":0.2110000,"year":2025,"month":7,"sec":30,"hour":11,"course":344.9920044}
  724. --模式3示例:
  725. log.info("nmea", "rmc3", exgnss.rmc(3))
  726. $GNRMC,115430.000,A,3434.82649,N,11350.39700,E,0.211,344.992,170725,,,A,S*02\r
  727. ]]
  728. function exgnss.rmc(lnglat_mode)
  729. return libgnss.getRmc(lnglat_mode)
  730. end
  731. --[[
  732. 获取原始GSV信息
  733. @api exgnss.gsv()
  734. @return table 原始GSV数据
  735. @usage
  736. -- 解析nmea
  737. log.info("nmea", "gsv", json.encode(exgnss.gsv()))
  738. -- 实例输出
  739. -- {
  740. -- "total_sats":24, // 总可见卫星数量
  741. -- "sats":[
  742. -- {
  743. -- "snr":27, // 信噪比
  744. -- "azimuth":278, // 方向角
  745. -- "elevation":59, // 仰角
  746. -- "tp":0, // 0 - GPS, 1 - BD, 2 - GLONASS, 3 - Galileo, 4 - QZSS
  747. -- "nr":4 // 卫星编号
  748. -- },
  749. -- // 这里忽略了22个卫星的信息
  750. -- {
  751. -- "snr":0,
  752. -- "azimuth":107,
  753. -- "elevation":19,
  754. -- "tp":1,
  755. -- "nr":31
  756. -- }
  757. -- ]
  758. -- }
  759. ]]
  760. function exgnss.gsv()
  761. return libgnss.getGsv()
  762. end
  763. --[[
  764. 获取原始GSA信息
  765. @api exgnss.gsa(data_mode)
  766. @number 模式,默认为0 -所有卫星系统全部输出在一起,1 - 每个卫星系统单独分开输出
  767. @return table 原始GSA数据
  768. @usage
  769. -- 获取
  770. log.info("nmea", "gsa", json.encode(exgnss.gsa()))
  771. -- 示例数据(模式0, 也就是默认模式)
  772. --sysid:1为GPS,4为北斗,2为GLONASS,3为Galileo
  773. {"pdop":1.1770000, 位置精度因子,0.00 - 99.99,不定位时值为 99.99
  774. "sats":[15,13,5,18,23,20,24,30,24,13,33,38,8,14,28,41,6,39,25,16,32,27], // 正在使用的卫星编号
  775. "vdop":1.0160000, 垂直精度因子,0.00 - 99.99,不定位时值为 99.99
  776. "hdop":0.5940000, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
  777. "sysid":1, // 卫星系统编号1为GPS,4为北斗,2为GLONASS,3为Galileo
  778. "fix_type":3 // 定位模式, 1-未定位, 2-2D定位, 3-3D定位
  779. }
  780. --模式1
  781. log.info("nmea", "gsa", json.encode(exgnss.gsa()))
  782. [{"pdop":1.1770000,"sats":[15,13,5,18,23,20,24],"vdop":1.0160000,"hdop":0.5940000,"sysid":1,"fix_type":3},
  783. {"pdop":1.1770000,"sats":[30,24,13,33,38,8,14,28,41,6,39,25],"vdop":1.0160000,"hdop":0.5940000,"sysid":4,"fix_type":3},
  784. {"pdop":1.1770000,"sats":[16,32,27],"vdop":1.0160000,"hdop":0.5940000,"sysid":4,"fix_type":3},
  785. {"pdop":1.1770000,"sats":{},"vdop":1.0160000,"hdop":0.5940000,"sysid":2,"fix_type":3},
  786. {"pdop":1.1770000,"sats":{},"vdop":1.0160000,"hdop":0.5940000,"sysid":3,"fix_type":3}]
  787. ]]
  788. function exgnss.gsa(data_mode)
  789. return libgnss.getGsa(data_mode)
  790. end
  791. --[[
  792. 获取VTG速度信息
  793. @api exgnss.vtg(data_mode)
  794. @number 可选, 3-原始字符串, 不传或者传其他值, 则返回浮点值
  795. @return table/string 原始VTG数据
  796. @usage
  797. -- 解析nmea
  798. log.info("nmea", "vtg", json.encode(exgnss.vtg()))
  799. -- 示例
  800. {
  801. "speed_knots":0, // 速度, 英里/小时
  802. "true_track_degrees":0, // 真北方向角
  803. "magnetic_track_degrees":0, // 磁北方向角
  804. "speed_kph":0 // 速度, 千米/小时
  805. }
  806. --模式3
  807. log.info("nmea", "vtg", exgnss.vtg(3))
  808. -- 返回值:$GNVTG,0.000,T,,M,0.000,N,0.000,K,A*13\r
  809. -- 提醒: 在速度<5km/h时, 不会返回方向角
  810. ]]
  811. function exgnss.vtg(data_mode)
  812. return libgnss.getVtg(data_mode)
  813. end
  814. --获取原始ZDA时间和日期信息
  815. --[[
  816. 获取原始ZDA时间和日期信息
  817. @api exgnss.zda()
  818. @return table 原始zda数据
  819. @usage
  820. log.info("nmea", "zda", json.encode(exgnss.zda()))
  821. -- 实例输出
  822. -- {
  823. -- "minute_offset":0, // 本地时区的分钟, 一般固定输出0
  824. -- "hour_offset":0, // 本地时区的小时, 一般固定输出0
  825. -- "year":2023 // UTC 年,四位数字
  826. -- "month":1, // UTC 月,两位,01 ~ 12
  827. -- "day":5, // UTC 日,两位数字,01 ~ 31
  828. -- "hour":7, // 小时
  829. -- "min":50, // 分
  830. -- "sec":14, // 秒
  831. -- }
  832. ]]
  833. function exgnss.zda()
  834. return libgnss.getZda()
  835. end
  836. --[[
  837. 获取GGA数据
  838. @api exgnss.gga(lnglat_mode)
  839. @number 经纬度数据的格式, 0-ddmm.mmmmm格式, 1-DDDDDDDDD格式, 2-DD.DDDDDDD格式, 3-原始GGA字符串
  840. @return table GGA数据, 若如不存在会返回nil
  841. @usage
  842. local gga = exgnss.gga(2)
  843. log.info("GGA", json.encode(gga, "11g"))
  844. --实例输出,获取值的解释:
  845. -- {
  846. -- "dgps_age":0, // 差分校正时延,单位为秒
  847. -- "fix_quality":1, // 定位状态标识 0 - 无效,1 - 单点定位,2 - 差分定位
  848. -- "satellites_tracked":14, // 参与定位的卫星数量
  849. -- "altitude":0.255, // 海平面分离度, 或者成为海拔, 单位是米,
  850. -- "hdop":0.0335, // 水平精度因子,0.00 - 99.99,不定位时值为 99.99
  851. -- "longitude":113.231, // 经度, 正数为东经, 负数为西经
  852. -- "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
  853. -- "height":0 // 椭球高,固定输出 1 位小数
  854. -- }
  855. 模式0示例:
  856. json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位,本示例保留5位小数
  857. local gga = exgnss.gga(0)
  858. if gga then
  859. log.info("GGA0", json.encode(gga, "5f"))
  860. end
  861. {"longitude":11419.19531,"dgps_age":0,"altitude":86.40000,"hdop":0.59400,"height":-13.70000,"fix_quality":1,"satellites_tracked":22,"latitude":3447.86914}
  862. 模式1示例:
  863. DDDDDDDDD格式是由DD.DDDDDDD*10000000转换而来,目的是作为整数,方便某些场景使用
  864. local gga1 = exgnss.gga(1)
  865. if gga1 then
  866. log.info("GGA1", json.encode(gga1))
  867. end
  868. {"longitude":1143199103,"dgps_age":0,"altitude":86.4000015,"hdop":0.5940000,"height":-13.6999998,"fix_quality":1,"satellites_tracked":22,"latitude":347978178}
  869. 模式2示例:
  870. json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位
  871. local gga2 = exgnss.gga(2)
  872. if gga2 then
  873. log.info("GGA2", json.encode(gga2))
  874. end
  875. {"longitude":114.3199081,"dgps_age":0,"altitude":86.4000015,"hdop":0.5940000,"height":-13.6999998,"fix_quality":1,"satellites_tracked":22,"latitude":34.7978172}
  876. 模式3示例:
  877. local gga3 = exgnss.gga(3)
  878. if gga3 then
  879. log.info("GGA3", gga3)
  880. end
  881. $GNGGA,131241.000,3434.81372,N,11350.39930,E,1,05,4.924,165.5,M,-15.2,M,,*6D\r
  882. ]]
  883. function exgnss.gga(lnglat_mode)
  884. return libgnss.getGga(lnglat_mode)
  885. end
  886. --[[
  887. 获取GLL数据
  888. @api exgnss.gll(data_mode)
  889. @number 经纬度数据的格式, 0-ddmm.mmmmm格式, 1-DDDDDDDDD格式, 2-DD.DDDDDDD格式
  890. @return table GLL数据, 若如不存在会返回nil
  891. @usage
  892. local gll = exgnss.gll(2)
  893. if gll then
  894. log.info("GLL", json.encode(gll, "11g"))
  895. end
  896. -- 实例数据,获取值的解释:
  897. -- {
  898. -- "status":"A", // 定位状态, A有效, B无效
  899. -- "mode":"A", // 定位模式, V无效, A单点解, D差分解
  900. -- "sec":20, // 秒, UTC时间为准
  901. -- "min":23, // 分钟, UTC时间为准
  902. -- "hour":7, // 小时, UTC时间为准
  903. -- "longitude":113.231, // 经度, 正数为东经, 负数为西经
  904. -- "latitude":23.4067, // 纬度, 正数为北纬, 负数为南纬
  905. -- "us":0 // 微妙数, 通常为0
  906. -- }
  907. --模式0示例:
  908. --json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位,本示例保留5位小数
  909. local gll = exgnss.gll(0)
  910. if gll then
  911. log.info("GLL0", json.encode(gll, "5f"))
  912. end
  913. {"longitude":11419.19531,"sec":14,"min":32,"mode":"A","hour":6,"us":0,"status":"A","latitude":3447.86914}
  914. --模式1示例:
  915. --DDDDDDDDD格式是由DD.DDDDDDD*10000000转换而来,目的是作为整数,方便某些场景使用
  916. local gll1 = exgnss.gll(1)
  917. if gll1 then
  918. log.info("GLL1", json.encode(gll1))
  919. end
  920. {"longitude":1143199103,"sec":14,"min":32,"mode":"A","hour":6,"us":0,"status":"A","latitude":347978178}
  921. 模式2示例:
  922. --json.encode默认输出"7f"格式保留7位小数,可以根据自己需要的格式调整小数位
  923. local gll2 = exgnss.gll(2)
  924. if gll2 then
  925. log.info("GLL2", json.encode(gll2))
  926. end
  927. {"longitude":114.3199081,"sec":14,"min":32,"mode":"A","hour":6,"us":0,"status":"A","latitude":34.7978172}
  928. ]]
  929. function exgnss.gll(data_mode)
  930. return libgnss.getGll(data_mode)
  931. end
  932. --[[
  933. 获取最后的经纬度数据
  934. @api exgnss.last_loc()
  935. @return table 经纬度数据,表里面的内容:{lat=ddmm.mmmmm0000,lng=ddmm.mmmmm0000},返回nil表示没有数据,此数据在定位成功,关闭gps时,会自动保存到文件系统中,定位成功之后每10分钟如果还处于定位成功状态会更新
  936. @usage
  937. local loc= exgnss.last_loc()
  938. if loc then
  939. log.info("lastloc", loc.lat,loc.lng)
  940. end
  941. 日志输出内容示例:
  942. 3447.8679200000 11419.196290000
  943. ]]
  944. function exgnss.last_loc()
  945. local locStr = io.readFile("/hxxtloc")
  946. if locStr then
  947. local jdata = json.decode(locStr)
  948. return jdata
  949. end
  950. end
  951. return exgnss