gpsv2.lua 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  1. --- 模块功能:GPS模块管理
  2. -- @module gpsv2
  3. -- @author openLuat
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2018.08.28
  7. require "pm"
  8. require "httpv2"
  9. require "utils"
  10. require "lbsLoc"
  11. module(..., package.seeall)
  12. local ver = rtos.get_version():upper()
  13. local is8955 = ver:find("8955")
  14. local is1802 = ver:find("1802")
  15. local is8910 = ver:find("8910")
  16. -- 浮点支持
  17. local float = ver:find("FLOAT")
  18. -- GPS任务线程ID
  19. local GPS_CO
  20. --串口配置
  21. local uartID, uartBaudrate = 2, 115200
  22. -- 星历的保存地址
  23. local GPD_FILE = "/ephdat.bin"
  24. -- 下载超时设置单位分钟
  25. local timeout = 5 * 60000
  26. -- 设置星历和基站定位的循环定时器时间
  27. local EPH_UPDATE_INTERVAL = 4 * 3600
  28. -- 星历写入标记
  29. local ephFlag = false
  30. --GPS开启标志,true表示开启状态,false或者nil表示关闭状态
  31. local openFlag
  32. --GPS定位标志,true表示,其余表示未定位,hdop 水平精度
  33. local fixFlag, hdop = false, "0"
  34. -- 经纬度类型和数据
  35. local latitudeType, latitude, longitudeType, longitude = "N", "", "E", ""
  36. -- 海拔,速度,时速,方向角
  37. local altitude, speed, kmHour, azimuth = "0", "0", "0", "0"
  38. -- 参与定位的卫星个数,GPS和北斗可见卫星个数
  39. local usedSateCnt, viewedGpsSateCnt, viewedBdSateCnt = "0", "0", "0"
  40. -- 可用卫星号,UTC时间
  41. local SateSn, UtcTime, utcStamp = {}, {}, 0
  42. -- 大地高,度分经度,度分纬度
  43. local Sep, Ggalng, Ggalat
  44. -- GPS和北斗GSV解析保存的表
  45. local gpgsvTab, bdgsvTab = {}, {}
  46. -- GPGSV解析后的CNO信息
  47. local gsvCnoTab = {}
  48. -- 基站定位坐标
  49. local lbs_lat, lbs_lng
  50. -- 日志开关
  51. local isLog = false
  52. --解析GPS模块返回的信息
  53. local function parseNmea(s)
  54. if not s or s == "" then return end
  55. if isLog then log.warn("gpsv2.parseNmea", "parse nmea:", s) end
  56. local lat, lng, spd, cog, gpsFind, gpsTime, gpsDate, locSateCnt, hdp, latTyp, lngTyp, altd
  57. if s:match("GGA") then
  58. lat, latTyp, lng, lngTyp, gpsFind, locSateCnt, hdp, altd, sep = s:match("GGA,%d+%.%d+,(%d+%.%d+),([NS]),(%d+%.%d+),([EW]),(%d),(%d+),([%d%.]*),(.*),M,(.*),M")
  59. if (gpsFind == "1" or gpsFind == "2" or gpsFind == "4") and altd then
  60. altitude = altd
  61. usedSateCnt = locSateCnt
  62. Sep = sep
  63. hdop = hdp
  64. end
  65. Ggalng, Ggalat = (lngTyp == "W" and "-" or "") .. lng, (latTyp == "S" and "-" or "") .. lat
  66. latitudeType, longitudeType, latitude, longitude = latTyp, lngTyp, lat, lng
  67. --log.info("gpsv2.parseNmea", "parse GGA:", latitudeType, longitudeType, latitude, longitude)
  68. elseif s:match("GSA") then
  69. local satesn = s:match("GSA,%w*,%d*,(%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,)") or ""
  70. if #satesn > 0 and s:match("%d+,") then SateSn = satesn end
  71. elseif s:match("GPGSV") then
  72. local curnum, lineno, sateNum, gsv_str = s:match("GPGSV,(%d),(%d),(%d+),(.*)%*.*")
  73. if curnum and lineno and sateNum and gsv_str then
  74. if tonumber(lineno) == 1 then
  75. gpgsvTab = {}
  76. gsvCnoTab = {}
  77. gpgsvTab.sateNum = sateNum
  78. gpgsvTab.sateType = "GPS"
  79. end
  80. for i = 1, 4 do
  81. local msg = {id, elevation, azimuth, cno}
  82. -- 找到的字符串的开始位置,结束位置,仰角,方位角,载波信噪比
  83. msg.id, msg.elevation, msg.azimuth, msg.cno, gsv_str = gsv_str:match("(%d+),([%-]*%d*),(%d*),(%d*)(.*)")
  84. if not msg.id then break end
  85. msg.id, msg.elevation, msg.azimuth, msg.cno = tonumber(msg.id) or 0, tonumber(msg.elevation) or 0, tonumber(msg.azimuth) or 0, tonumber(msg.cno) or 0
  86. table.insert(gpgsvTab, msg)
  87. table.insert(gsvCnoTab, msg.cno)
  88. end
  89. viewedGpsSateCnt = sateNum or "0"
  90. end
  91. -- log.info("GPGSV is value:", json.encode(gsvCnoTab))
  92. elseif s:match("BDGSV") then
  93. local curnum, lineno, sateNum, gsv_str = s:match("GPGSV,(%d),(%d),(%d+),(.*)%*.*")
  94. if curnum and lineno and sateNum and gsv_str then
  95. if tonumber(lineno) == 1 then
  96. bdgsvTab = {}
  97. bdgsvTab.sateNum = sateNum
  98. bdgsvTab.sateType = "BD"
  99. end
  100. -- 将同一消息编号的归类插入同一个编号中
  101. for i = 1, 4 do
  102. local msg = {id, elevation, azimuth, cno}
  103. -- 找到的字符串的开始位置,结束位置,仰角,方位角,载波信噪比
  104. msg.id, msg.elevation, msg.azimuth, msg.cno, gsv_str = gsv_str:match("(%d+),([%-]*%d*),(%d*),(%d*)(.*)")
  105. if not msg.id then break end
  106. msg.id, msg.elevation, msg.azimuth, msg.cno = tonumber(msg.id) or 0, tonumber(msg.elevation) or 0, tonumber(msg.azimuth) or 0, tonumber(msg.cno) or 0
  107. table.insert(bdgsvTab, msg)
  108. end
  109. end
  110. viewedBdSateCnt = sateNum or "0"
  111. elseif s:match("RMC") then
  112. gpsTime, gpsFind, lat, latTyp, lng, lngTyp, spd, cog, gpsDate = s:match("RMC,(%d%d%d%d%d%d)%.%d+,(%w),(%d*%.*%d*),([NS]*),(%d*%.*%d*),([EW]*),(.-),(.-),(%d%d%d%d%d%d),")
  113. if gpsFind == "A" and cog then
  114. fixFlag = true
  115. speed = spd
  116. azimuth = cog
  117. else
  118. fixFlag = false
  119. end
  120. latitudeType, longitudeType, latitude, longitude = latTyp, lngTyp, lat, lng
  121. --log.info("gpsv2.parseNmea", "parse RMC:", latitudeType, longitudeType, latitude, longitude)
  122. if gpsFind == "A" and gpsTime and gpsDate and gpsTime ~= "" and gpsDate ~= "" then
  123. local yy, mm, dd, h, m, s = tonumber(gpsDate:sub(5, 6)), tonumber(gpsDate:sub(3, 4)), tonumber(gpsDate:sub(1, 2)), tonumber(gpsTime:sub(1, 2)), tonumber(gpsTime:sub(3, 4)), tonumber(gpsTime:sub(5, 6))
  124. utcStamp = os.time({year = 2000 + yy, month = mm, day = dd, hour = h, min = m, sec = s})
  125. UtcTime = os.date("*t", os.time({year = 2000 + yy, month = mm, day = dd, hour = h, min = m, sec = s}) + 28800)
  126. -- misc.setClock(UtcTime)
  127. sys.publish("GPS_TIMING_SUCCEED", UtcTime)
  128. end
  129. elseif s:match("VTG") then
  130. kmHour = s:match("VTG,%d*%.*%d*,%w*,%d*%.*%d*,%w*,%d*%.*%d*,%w*,(%d*%.*%d*)")
  131. -- if fixFlag then sys.publish("GPS_MSG_REPORT", 1) else sys.publish("GPS_MSG_NOREPORT", 0) end
  132. sys.publish("GPS_MSG_REPORT", fixFlag and 1 or 0)
  133. end
  134. end
  135. -- 阻塞模式读取串口数据,需要线程支持
  136. -- @return 返回以\r\n结尾的一行数据
  137. -- @usage local str = gpsv2.read()
  138. local function read()
  139. --log.info("gpsv2.read", "read uartID:",uartID)
  140. local cache_data = ""
  141. local co = coroutine.running()
  142. while true do
  143. local s = uart.read(uartID, "*l")
  144. if s == "" then
  145. uart.on(uartID, "receive", function()coroutine.resume(co) end)
  146. coroutine.yield()
  147. uart.on(uartID, "receive")
  148. else
  149. cache_data = cache_data .. s
  150. if cache_data:find("\r\n") then return cache_data end
  151. end
  152. end
  153. end
  154. -- GPS串口写命令操作
  155. -- @string cmd,GPS指令(cmd格式:"$PGKC149,1,115200*"或者"$PGKC149,1,115200*XX\r\n")
  156. -- @bool isFull,cmd是否为完整的指令格式,包括校验和以及\r\n;true表示完整,false或者nil为不完整
  157. -- @return nil
  158. -- @usage gpsv2.writeCmd(cmd)
  159. local function writeCmd(cmd, isFull)
  160. local tmp = cmd
  161. if not isFull then
  162. tmp = 0
  163. for i = 2, cmd:len() - 1 do
  164. tmp = bit.bxor(tmp, cmd:byte(i))
  165. end
  166. tmp = cmd .. (string.format("%02X", tmp)):upper() .. "\r\n"
  167. end
  168. uart.write(uartID, tmp)
  169. -- log.info("gpsv2.writecmd", tmp)
  170. end
  171. -- GPS串口写数据操作
  172. -- @string str,HEX形式的字符串
  173. -- @return 无
  174. -- @usage gpsv2.writeData(str)
  175. local function writeData(str)
  176. uart.write(uartID, (str:fromHex()))
  177. --log.info("gpsv2.writeData", str)
  178. end
  179. -- AIR530的校验和算法
  180. local function hexCheckSum(str)
  181. local sum = 0
  182. for i = 5, str:len(), 2 do
  183. sum = bit.bxor(sum, tonumber(str:sub(i, i + 1), 16))
  184. end
  185. return string.upper(string.format("%02X", sum))
  186. end
  187. local function setFastFix(lat, lng)
  188. if not lat or not lng or not openFlag or os.time() < 1514779200 then return end
  189. local tm = os.date("*t")
  190. tm = common.timeZoneConvert(tm.year, tm.month, tm.day, tm.hour, tm.min, tm.sec, 8, 0)
  191. t = tm.year .. "," .. tm.month .. "," .. tm.day .. "," .. tm.hour .. "," .. tm.min .. "," .. tm.sec .. "*"
  192. log.info("gpsv2.setFastFix", "写入秒定位需要的坐标和时间:", lat, lng, t)
  193. writeCmd("$PGKC634," .. t)
  194. writeCmd("$PGKC634," .. t)
  195. writeCmd("$PGKC635," .. lat .. "," .. lng .. ",0," .. t)
  196. end
  197. -- 定时自动下载坐标和星历的任务
  198. local function getlbs(result, lat, lng, addr)
  199. log.info("gpsv2.getlbs", "----------->result, lat, lng, addr", result, lat, lng, addr)
  200. if result and lat and lng then
  201. lbs_lat, lbs_lng = lat, lng
  202. setFastFix(lat, lng)
  203. else
  204. log.warn("gpsv2.getlbs", "-----------> 快速定位失败!")
  205. end
  206. end
  207. local function saveEph(timeout)
  208. sys.taskInit(function()
  209. while true do
  210. log.info("gpsv2.saveEph", "开始下载星历数据")
  211. local code, head, data = httpv2.request("GET", "download.openluat.com/9501-xingli/brdcGPD.dat_rda", timeout)
  212. if tonumber(code) and tonumber(code) == 200 then
  213. log.info("gpsv2.saveEph", "保存下载的星历:", io.writeFile(GPD_FILE, data))
  214. ephFlag = false
  215. break
  216. else
  217. log.warn("gpsv2.saveEph", "下载星历数据失败")
  218. end
  219. end
  220. end)
  221. end
  222. --- 打开GPS模块
  223. -- @number id,UART ID,支持1和2,1表示UART1,2表示UART2
  224. -- @number baudrate,波特率,支持1200,2400,4800,9600,10400,14400,19200,28800,38400,57600,76800,115200,230400,460800,576000,921600,1152000,4000000
  225. -- @nunber mode,功耗模式0正常功耗,2周期唤醒
  226. -- @number sleepTm,间隔唤醒的时间 秒
  227. -- @param fnc,外部模块使用的电源管理函数
  228. -- @return 无
  229. -- @usage gpsv2.open()
  230. -- @usage gpsv2.open(2, 115200, 0, 1) -- 打开GPS,串口2,波特率115200,正常功耗模式,1秒1个点
  231. -- @usage gpsv2.open(2, 115200, 2, 5) -- 打开GPS,串口2,波特率115200,周期低功耗模式1秒输出,5秒睡眠
  232. function open(id, baudrate, mode, sleepTm, fnc)
  233. uartID, uartBaudrate = tonumber(id) or uartID, tonumber(baudrate) or uartBaudrate
  234. mode, sleepTm = tonumber(mode) or 0, tonumber(sleepTm) and sleepTm * 1000 or 1000
  235. pm.wake("gpsv2.lua")
  236. uart.close(uartID)
  237. uart.setup(uartID, uartBaudrate, 8, uart.PAR_NONE, uart.STOP_1)
  238. if fnc and type(fnc) == "function" then
  239. fnc()
  240. else
  241. if is8955 then
  242. rtos.sys32k_clk_out(1)
  243. pmd.ldoset(7, pmd.LDO_VIB)
  244. pmd.ldoset(7, pmd.LDO_VCAM)
  245. elseif is1802 then
  246. pmd.ldoset(7, pmd.VLDO6)
  247. elseif is8910 then
  248. pmd.ldoset(15, pmd.LDO_VLCD)
  249. pmd.ldoset(15, pmd.LDO_VMMC)
  250. end
  251. end
  252. openFlag = true
  253. local fullPowerMode = false
  254. local wakeFlag = false
  255. ---------------------------------- 初始化GPS任务--------------------------------------------
  256. -- 获取基站定位坐标
  257. lbsLoc.request(getlbs, nil, timeout)
  258. --连接服务器下载星历
  259. saveEph(timeout)
  260. -- 自动定时下载定位坐标
  261. sys.timerLoopStart(function()lbsLoc.request(getlbs, nil, timeout) end, EPH_UPDATE_INTERVAL * 1000)
  262. -- 自动定时下载星历数据
  263. sys.timerLoopStart(saveEph, EPH_UPDATE_INTERVAL * 1000, timeout)
  264. log.info("gpsv2.open", "----------------------------------- GPS OPEN -----------------------------------")
  265. GPS_CO = sys.taskInit(function()
  266. --read()
  267. -- 发送GPD传送结束语句
  268. writeData("AAF00B006602FFFF6F0D0A")
  269. -- 切换为NMEA接收模式
  270. local nmea = "AAF00E00950000" .. (pack.pack("<i", uartBaudrate):toHex())
  271. nmea = nmea .. hexCheckSum(nmea) .. "0D0A"
  272. writeData(nmea)
  273. writeCmd("$PGKC147," .. uartBaudrate .. "*")
  274. setReport(1000)
  275. while openFlag do
  276. if not fixFlag and not ephFlag and io.exists(GPD_FILE) and os.time() > 1514779200 then
  277. local tmp, data, len = "", io.readFile(GPD_FILE):toHex()
  278. log.info("gpsv2.open", "模块写星历数据开始!")
  279. -- 切换到BINARY模式
  280. while read():toHex() ~= "AAF00C0001009500039B0D0A" do writeCmd("$PGKC149,1," .. uartBaudrate .. "*") end
  281. -- 写入星历数据
  282. local cnt = 0 -- 包序号
  283. for i = 1, #data, 1024 do
  284. local tmp = data:sub(i, i + 1023)
  285. if tmp:len() < 1024 then tmp = tmp .. ("F"):rep(1024 - tmp:len()) end
  286. tmp = "AAF00B026602" .. string.format("%04X", cnt):upper() .. tmp
  287. tmp = tmp .. hexCheckSum(tmp) .. "0D0A"
  288. writeData(tmp)
  289. for j = 1, 30 do
  290. local ack, len = read():toHex()
  291. if len == 12 or ack:find("AAF00C0003") then break end
  292. end
  293. cnt = cnt + 1
  294. end
  295. -- 发送GPD传送结束语句
  296. writeData("AAF00B006602FFFF6F0D0A")
  297. -- 切换为NMEA接收模式
  298. while not read():find("$G") do writeData(nmea) end
  299. setFastFix(lbs_lat, lbs_lng)
  300. ephFlag = true
  301. fullPowerMode = true
  302. log.info("gpsv2.open", "模块写星历数据完成!")
  303. end
  304. if tonumber(mode) == 2 then
  305. fixFlag = false
  306. -- setRunMode(0, 1000, sleepTm)
  307. setReport(1000)
  308. while not fixFlag do
  309. parseNmea(read())
  310. end
  311. parseNmea(read())
  312. if fixFlag then end
  313. -- while not read():match("PGKC001,105,(3)") do setRunMode(2, 1000, sleepTm) end
  314. writeCmd("$PGKC051,1*")
  315. sys.wait(sleepTm)
  316. -- while fixFlag do parseNmea(read()) end
  317. else
  318. --log.info("gpsv2.open","-------> parseNmea")
  319. if not wakeFlag then
  320. setRunMode(mode, 1000, sleepTm)
  321. setReport(sleepTm)
  322. wakeFlag = true
  323. end
  324. parseNmea(read())
  325. end
  326. end
  327. sys.publish("GPS_CLOSE_MSG")
  328. log.info("gpsv2.open", "GPS 任务结束退出!")
  329. end)
  330. end
  331. --- 关闭GPS模块
  332. -- @param fnc,外部模块使用的电源管理函数
  333. -- @return 无
  334. -- @usage gpsv2.close()
  335. function close(id, fnc)
  336. openFlag = false
  337. fixFlag = false
  338. while GPS_CO ~= nil and coroutine.status(GPS_CO) ~= "dead" do coroutine.resume(GPS_CO) end
  339. uart.close(tonumber(id) or uartID)
  340. if fnc and type(fnc) == "function" then
  341. fnc()
  342. else
  343. if is8955 then
  344. rtos.sys32k_clk_out(0)
  345. pmd.ldoset(0, pmd.LDO_VIB)
  346. pmd.ldoset(0, pmd.LDO_VCAM)
  347. elseif is1802 then
  348. pmd.ldoset(0, pmd.VLDO6)
  349. elseif is8910 then
  350. pmd.ldoset(0, pmd.LDO_VLCD)
  351. pmd.ldoset(0, pmd.LDO_VMMC)
  352. end
  353. end
  354. pm.sleep("gpsv2.lua")
  355. sys.timerStopAll(restart)
  356. log.info("gpsv2.open", "----------------------------------- GPS CLOSE -----------------------------------")
  357. end
  358. --- 重启GPS模块
  359. -- @number r,重启方式-0:外部电源重置; 1:热启动; 2:温启动; 3:冷启动
  360. -- @return 无
  361. -- @usage gpsv2.restart()
  362. function restart(r)
  363. r = tonumber(r) or 1
  364. if r > 0 and r < 4 then writeCmd("$PGKC030," .. r .. "*") end
  365. end
  366. --- 设置GPS模块搜星模式.
  367. -- 如果使用的是Air800或者Air530,不调用此接口配置,则默认同时开启GPS和北斗定位
  368. -- @number gps,GPS定位系统,1是打开,0是关闭
  369. -- @number beidou,中国北斗定位系统,1是打开,0是关闭
  370. -- @number glonass,俄罗斯Glonass定位系统,1是打开,0是关闭
  371. -- @number galieo,欧盟伽利略定位系统,1是打开,0是关闭
  372. -- @return nil
  373. -- @usage gpsv2.setAeriaMode(1,1,0,0)
  374. function setAerialMode(gps, beidou, glonass, galieo)
  375. local gps = gps or 0
  376. local glonass = glonass or 0
  377. local beidou = beidou or 0
  378. local galieo = galieo or 0
  379. if gps + glonass + beidou + galieo == 0 then gps = 1; beidou = 1 end
  380. if openFlag then writeCmd("$PGKC115," .. gps .. "," .. glonass .. "," .. beidou .. "," .. galieo .. "*") end
  381. end
  382. --- 设置GPS模块的运行模式.
  383. -- 如果不调用此接口配置,则默认为正常运行模式
  384. -- @number mode,运行模式
  385. -- 0:正常运行模式
  386. -- 1:周期超低功耗跟踪模式
  387. -- 2:周期低功耗模式
  388. -- 4:直接进入超低功耗跟踪模式
  389. -- 8:自动低功耗模式,可以通过串口唤醒
  390. -- 9:自动超低功耗跟踪模式,需要force on来唤醒
  391. -- @number runTm,单位毫秒,mode为1或者2时表示运行时长,其余mode时此值无意义
  392. -- @number sleepTm,单位毫秒,mode为1或者2时表示睡眠时长,其余mode时此值无意义
  393. -- @return nil
  394. -- @usage gpsv2.setRunMode(0,1000)
  395. -- @usage gpsv2.setRunMode(1,5000,2000)
  396. function setRunMode(mode, runTm, sleepTm)
  397. local rt, st = tonumber(runTm) or "", tonumber(sleepTm) or ""
  398. if openFlag then
  399. writeCmd("$PGKC105," .. mode .. ((mode == 1 or mode == 2) and ("," .. rt .. "," .. st) or "") .. "*")
  400. end
  401. end
  402. --- 设置NMEA消息上报的间隔
  403. -- @number tm,上报消息的间隔时间
  404. -- @return 无
  405. -- @usage gpsv2.setReport(tm)
  406. function setReport(tm)
  407. if openFlag then
  408. tm = tonumber(tm) or 1000
  409. if tm > 10000 then tm = 10000 end
  410. if tm < 200 then tm = 200 end
  411. writeCmd("$PGKC101," .. tm .. "*")
  412. end
  413. end
  414. --- 获取GPS模块是否处于开启状态
  415. -- @return bool result,true表示开启状态,false或者nil表示关闭状态
  416. -- @usage gpsv2.isOpen()
  417. function isOpen()
  418. return openFlag
  419. end
  420. --- 获取GPS模块是否定位成功
  421. -- @return bool result,true表示定位成功,false或者nil表示定位失败
  422. -- @usage gpsv2.isFix()
  423. function isFix()
  424. return fixFlag
  425. end
  426. --- 获取返回值为度的10&7方的整数值(度*10^7的值)
  427. -- @return number,number,INT32整数型,经度,维度,符号(正东负西,正北负南)
  428. -- @usage gpsv2.getIntLocation()
  429. function getIntLocation()
  430. local lng, lat = "0.0", "0.0"
  431. lng = longitudeType == "W" and ("-" .. longitude) or longitude
  432. lat = latitudeType == "S" and ("-" .. latitude) or latitude
  433. if lng and lat and lng ~= "" and lat ~= "" then
  434. local integer, decimal = lng:match("(%d+).(%d+)")
  435. if tonumber(integer) and tonumber(decimal) then
  436. decimal = decimal:sub(1, 7)
  437. local tmp = (integer % 100) * 10 ^ 7 + decimal * 10 ^ (7 - #decimal)
  438. lng = ((integer - integer % 100) / 100) * 10 ^ 7 + (tmp - tmp % 60) / 60
  439. end
  440. integer, decimal = lat:match("(%d+).(%d+)")
  441. if tonumber(integer) and tonumber(decimal) then
  442. decimal = decimal:sub(1, 7)
  443. tmp = (integer % 100) * 10 ^ 7 + decimal * 10 ^ (7 - #decimal)
  444. lat = ((integer - integer % 100) / 100) * 10 ^ 7 + (tmp - tmp % 60) / 60
  445. end
  446. return lng, lat
  447. end
  448. return 0, 0
  449. end
  450. --- 获取基站定位的经纬度信息dd.dddd
  451. function getDeglbs()
  452. return lbs_lng or "0.0", lbs_lat or "0.0"
  453. end
  454. --- 获取度格式的经纬度信息dd.dddddd
  455. -- @return string,string,固件为非浮点时返回度格式的字符串经度,维度,符号(正东负西,正北负南)
  456. -- @return float,float,固件为浮点的时候,返回浮点类型
  457. -- @usage gpsv2.getLocation()
  458. function getDegLocation()
  459. local lng, lat = getIntLocation()
  460. if float then return lng / 10 ^ 7, lat / 10 ^ 7 end
  461. return string.format("%d.%07d", lng / 10 ^ 7, lng % 10 ^ 7), string.format("%d.%07d", lat / 10 ^ 7, lat % 10 ^ 7)
  462. end
  463. --- 获取度分格式的经纬度信息ddmm.mmmm
  464. -- @return string,string,返回度格式的字符串经度,维度,符号(正东负西,正北负南)
  465. -- @usage gpsv2.getCentLocation()
  466. function getCentLocation()
  467. if float then return tonumber(Ggalng or 0), tonumber(Ggalat or 0) end
  468. return Ggalng or 0, Ggalat or 0
  469. end
  470. --- 获取海拔
  471. -- @return number altitude,海拔,单位米
  472. -- @usage gpsv2.getAltitude()
  473. function getAltitude()
  474. return tonumber(altitude and altitude:match("(%d+)")) or 0
  475. end
  476. --- 获取速度
  477. -- @return number kmSpeed,第一个返回值为公里每小时的速度
  478. -- @return number nmSpeed,第二个返回值为海里每小时的速度
  479. -- @usage gpsv2.getSpeed()
  480. function getSpeed()
  481. local integer = tonumber(speed and speed:match("(%d+)")) or 0
  482. return (integer * 1852 - (integer * 1852 % 1000)) / 1000, integer
  483. end
  484. --- 获取时速(KM/H)的整数型和浮点型(字符串)
  485. function getKmHour()
  486. return tonumber(kmHour and kmHour:match("(%d+)")) or 0, (float and tonumber(kmHour) or kmHour) or "0"
  487. end
  488. --- 获取方向角
  489. -- @return number Azimuth,方位角
  490. -- @usage gpsv2.getAzimuth()
  491. function getAzimuth()
  492. return tonumber(azimuth and azimuth:match("(%d+)")) or 0
  493. end
  494. --- 获取可见卫星的个数
  495. -- @return number count,可见卫星的个数
  496. -- @usage gpsv2.getViewedSateCnt()
  497. function getViewedSateCnt()
  498. return (tonumber(viewedGpsSateCnt) or 0) + (tonumber(viewedBdSateCnt) or 0)
  499. end
  500. --- 获取定位使用的卫星个数
  501. -- @return number count,定位使用的卫星个数
  502. -- @usage gpsv2.getUsedSateCnt()
  503. function getUsedSateCnt()
  504. return tonumber(usedSateCnt) or 0
  505. end
  506. --- 获取RMC语句中的UTC时间
  507. -- 只有同时满足如下两个条件,返回值才有效
  508. -- 1、开启了GPS,并且定位成功
  509. -- 2、调用setParseItem接口,第一个参数设置为true
  510. -- @return table utcTime,UTC时间,nil表示无效,例如{year=2018,month=4,day=24,hour=11,min=52,sec=10}
  511. -- @usage gpsv2.getUtcTime()
  512. function getUtcTime()
  513. return UtcTime
  514. end
  515. --- 获取gps的UTC时间戳
  516. -- @retrun number,时间戳
  517. -- @usage gpsv2.getUtcStamp()
  518. function getUtcStamp()
  519. return utcStamp or 0
  520. end
  521. --- 获取定位使用的大地高
  522. -- @return number sep,大地高
  523. -- @usage gpsv2.getSep()
  524. function getSep()
  525. return tonumber(Sep) or 0
  526. end
  527. --- 获取水平精度
  528. function getHdop()
  529. return tonumber(hdop) or 0
  530. end
  531. --- 获取GSA语句中的可见卫星号
  532. -- 只有同时满足如下两个条件,返回值才有效
  533. -- 1、开启了GPS,并且定位成功
  534. -- 2、调用setParseItem接口,第三个参数设置为true
  535. -- @return string viewedSateId,可用卫星号,""表示无效
  536. -- @usage gpsv2.getSateSn()
  537. function getSateSn()
  538. return tonumber(SateSn) or 0
  539. end
  540. --- 获取BDGSV解析结果
  541. -- @return table, GSV解析后的数组
  542. -- @usage gpsv2.getBDGsv()
  543. function getBDGsv()
  544. return bdgsvTab
  545. end
  546. --- 获取GPGSV解析结果
  547. -- @return table, GSV解析后的数组
  548. -- @usage gpsv2.getGPGsv()
  549. function getGPGsv()
  550. return gpgsvTab
  551. end
  552. --- 获取GPSGSV解析后的CNO数据
  553. function getCno()
  554. return gsvCnoTab
  555. end
  556. --- 是否显示日志
  557. function openLog(v)
  558. isLog = v == nil and true or v
  559. end