gpsZkw.lua 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926
  1. --- 模块功能:GPS模块管理
  2. -- 注意:此功能模块中的功能接口可以分为四大类:
  3. -- 1、GPS开启
  4. -- 2、GPS关闭
  5. -- 3、GPS定位数据读取
  6. -- 4、GPS参数和功能设置
  7. -- 1、2、3是通用功能,除了支持合宙的Air530Z和Air82X系列模块,理论上也支持其他厂家的串口GPS模块
  8. -- 4是专用功能,仅支持合宙的Air530Z和Air82X系列模块
  9. -- @module gpsZkw
  10. -- @author openLuat
  11. -- @license MIT
  12. -- @copyright openLuat
  13. -- @release 2017.10.23
  14. require"pm"
  15. require"utils"
  16. module(..., package.seeall)
  17. local smatch,sfind,slen,ssub,sbyte,sformat,srep = string.match,string.find,string.len,string.sub,string.byte,string.format,string.rep
  18. --GPS开启标志,true表示开启状态,false或者nil表示关闭状态
  19. local openFlag
  20. --GPS定位标志,"2D"表示2D定位,"3D"表示3D定位,其余表示未定位
  21. --GPS定位标志,true表示,其余表示未定位
  22. local fixFlag,fixOnece=nil,nil
  23. --GPS定位成功后,过滤掉前filterSeconds秒的经纬度信息
  24. --是否已经过滤完成
  25. local filterSeconds,filteredFlag = 0
  26. --从定位成功切换到定位失败,连续定位失败的次数
  27. local fixFailCnt = 0
  28. --经纬度类型和数据
  29. local latitudeType,latitude,longitudeType,longitude = "N","","E",""
  30. --海拔,速度,方向角
  31. local altitude,speed,course = "0","0","0"
  32. --参与定位的卫星个数,所有可见卫星的最大信号值,所有可见卫星的最大信号值中间缓存值
  33. local usedSateCnt,maxSignalStrength,maxSignalStrengthVar = "0",0,0
  34. --可见卫星个数
  35. local viewedGpsSateCnt,viewedBdSateCnt = "0","0"
  36. --可用卫星号,UTC时间,信噪比
  37. local SateSn,UtcTime,Gsv
  38. --大地高,度分经度,度分纬度
  39. local Sep,Ggalng,Ggalat
  40. --是否需要解析项
  41. local psUtcTime,psGsv,psSn
  42. --GPS供电设置函数
  43. local powerCbFnc
  44. --串口配置
  45. uartBaudrate = 9600
  46. local uartID,uartDatabits,uartParity,uartStopbits = 3,8,uart.PAR_NONE,uart.STOP_1
  47. --搜星模式命令字符串,"$PGKC115," .. gps .. "," .. glonass .. "," .. beidou .. "," .. galieo .. "*"
  48. local aerialModeStr,aerialModeSetted = ""
  49. --运行模式命令字符串,"$PGKC105," .. mode .. "," .. rt .. "," .. st .. "*"
  50. --local runModeStr,runModeSetted = ""
  51. --正常运行模式下NMEA数据上报间隔命令字符串,"$PGKC101," .. interval .. "*"
  52. local nmeaReportStr,nmeaReportSetted = ""
  53. --每种NEMA数据的输出频率命令字符串
  54. local nmeaReportFreqStr,nmeaReportFreqSetted = ""
  55. --NMEA数据处理模式,0表示仅gps.lua内部处理,1表示仅用户自己处理,2表示gps.lua和用户同时处理
  56. --用户处理一条NMEA数据的回调函数
  57. local nmeaMode,nmeaCbFnc = 0
  58. --NMEA数据输出间隔
  59. local nmeaInterval = 1000
  60. --运行模式
  61. --0,正常运行模式
  62. --1,周期超低功耗跟踪模式
  63. --2,周期低功耗模式
  64. --4,直接进入超低功耗跟踪模式
  65. --8,自动低功耗模式,可以通过串口唤醒
  66. --9, 自动超低功耗跟踪模式,需要force on来唤醒
  67. local runMode = 0
  68. --gps 的串口线程是否在工作;
  69. local taskFlag=false
  70. --runMode为1或者2时,GPS运行状态和休眠状态的时长
  71. local runTime,sleepTime
  72. --检测gps是否工作正常的定时器ID
  73. local workAbnormalTimerId
  74. --[[
  75. 函数名:getstrength
  76. 功能 :解析GSV数据
  77. 参数 :
  78. sg:NEMA中的一行GSV数据
  79. 返回值:无
  80. ]]
  81. local function getstrength(sg)
  82. sg = ssub(sg, 4, #sg)
  83. local d1,d2,curnum,lineno,total,sgv_str = sfind(sg,"GSV,(%d),(%d),(%d+),(.*)%*.*")
  84. if not curnum or not lineno or not total or not sgv_str then
  85. return
  86. end
  87. if lineno == nil then
  88. maxSignalStrengthVar = 0
  89. maxSignalStrength = 0
  90. elseif tonumber(lineno) == 1 then
  91. maxSignalStrength = maxSignalStrengthVar
  92. maxSignalStrengthVar = 0
  93. end
  94. local tmpstr,i = sgv_str
  95. for i=1,4 do
  96. local d1,d2,id,elevation,azimuth,strength = sfind(tmpstr,"(%d+),([%-]*%d*),(%d*),(%d*)")
  97. if id == nil then return end
  98. if strength == "" or not strength then
  99. strength = "00"
  100. end
  101. strength = tonumber(strength)
  102. if strength > maxSignalStrengthVar then
  103. maxSignalStrengthVar = strength
  104. end
  105. local idx,cur,fnd,tmpid = 0,id..","..elevation..","..azimuth..","..strength..",",false
  106. for tmpid in string.gmatch(Gsv,"(%d+),%d*,%d*,%d*,") do
  107. idx = idx + 1
  108. if tmpid == id then fnd = true break end
  109. end
  110. if fnd then
  111. local pattern,i = ""
  112. for i=1,idx do
  113. pattern = pattern.."%d+,%d*,%d*,%d*,"
  114. end
  115. local m1,m2 = sfind(Gsv,"^"..pattern)
  116. if m1 and m2 then
  117. local front = ssub(Gsv,1,m2)
  118. local n1,n2 = sfind(front,"%d+,%d*,%d*,%d*,$")
  119. if n1 and n2 then
  120. Gsv = ssub(Gsv,1,n1-1)..cur..ssub(Gsv,n2+1,-1)
  121. end
  122. end
  123. else
  124. Gsv = Gsv..cur
  125. end
  126. tmpstr = ssub(tmpstr,d2+1,-1)
  127. end
  128. end
  129. local function filterTimerFnc()
  130. log.info("gpsZkw.filterTimerFnc end")
  131. filteredFlag = true
  132. end
  133. local function stopWorkAbnormalTimer()
  134. if workAbnormalTimerId then
  135. sys.timerStop(workAbnormalTimerId)
  136. workAbnormalTimerId = nil
  137. end
  138. end
  139. local function parseNmea(s)
  140. if not s or s=="" then return end
  141. local lat,lng,spd,cog,gpsFind,gpsTime,gpsDate,locSateCnt,hdp,latTyp,lngTyp,altd
  142. local fixed,workAbnormal
  143. if smatch(s,"GGA") then
  144. lat,latTyp,lng,lngTyp,gpsFind,locSateCnt,hdp,altd,sep = smatch(s,"GGA,%d+%.%d+,(%d+%.%d+),([NS]),(%d+%.%d+),([EW]),(%d),(%d+),([%d%.]*),(.*),M,(.*),M")
  145. if (gpsFind=="1" or gpsFind=="2" or gpsFind=="4") and altd then
  146. --fixed = true
  147. altitude = altd
  148. latitudeType,longitudeType,latitude,longitude = latTyp,lngTyp,lat,lng
  149. usedSateCnt = locSateCnt
  150. Ggalng,Ggalat = (lngTyp=="W" and "-" or "")..lng,(latTyp=="S" and "-" or "")..lat
  151. Sep = sep
  152. else
  153. fixed = false
  154. end
  155. elseif smatch(s,"RMC") then
  156. gpsTime,gpsFind,lat,latTyp,lng,lngTyp,spd,cog,gpsDate = smatch(s,"RMC,(%d%d%d%d%d%d)%.%d+,(%w),(%d*%.*%d*),([NS]*),(%d*%.*%d*),([EW]*),(.-),(.-),(%d%d%d%d%d%d),")
  157. if gpsFind=="A" and cog then
  158. fixed = true
  159. latitudeType,longitudeType,latitude,longitude = latTyp,lngTyp,lat,lng
  160. speed = spd
  161. course = cog
  162. else
  163. fixed = false
  164. end
  165. if psUtcTime and gpsFind == "A" and gpsTime and gpsDate and gpsTime ~= "" and gpsDate ~= "" then
  166. local yy,mm,dd,h,m,s = tonumber(ssub(gpsDate,5,6)),tonumber(ssub(gpsDate,3,4)),tonumber(ssub(gpsDate,1,2)),tonumber(ssub(gpsTime,1,2)),tonumber(ssub(gpsTime,3,4)),tonumber(ssub(gpsTime,5,6))
  167. UtcTime = {year=2000+yy,month=mm,day=dd,hour=h,min=m,sec=s}
  168. end
  169. elseif smatch(s,"GPGSV") then
  170. viewedGpsSateCnt = tonumber(smatch(s,"%d+,%d+,(%d+)") or "0")
  171. if psGsv then getstrength(s) end
  172. elseif smatch(s,"BDGSV") then
  173. viewedBdSateCnt = tonumber(smatch(s,"%d+,%d+,(%d+)") or "0")
  174. if psGsv then getstrength(s) end
  175. elseif smatch(s,"GSA") then
  176. if psSn then
  177. local satesn = smatch(s,"GSA,%w*,%d*,(%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,)") or ""
  178. if slen(satesn) > 0 and smatch(satesn,"%d+,") then
  179. SateSn = satesn
  180. end
  181. end
  182. else
  183. workAbnormal = true
  184. end
  185. if not workAbnormal then
  186. stopWorkAbnormalTimer()
  187. end
  188. if filterSeconds>0 and fixed and not fixFlag and not filteredFlag then
  189. if not sys.timerIsActive(filterTimerFnc) then
  190. log.info("gpsZkw.filterTimerFnc begin")
  191. sys.publish("GPS_STATE","LOCATION_FILTER")
  192. sys.timerStart(filterTimerFnc,filterSeconds*1000)
  193. end
  194. return
  195. end
  196. --定位成功
  197. if fixed then
  198. if not fixFlag then
  199. fixFlag,filteredFlag = true,true
  200. fixOnece=true
  201. fixFailCnt = 0
  202. sys.publish("GPS_STATE","LOCATION_SUCCESS")
  203. end
  204. elseif fixed==false then
  205. if fixFlag then
  206. fixFailCnt = fixFailCnt+1
  207. if fixFailCnt>=20 then
  208. fixFlag,filteredFlag = false
  209. sys.timerStop(filterTimerFnc)
  210. sys.publish("GPS_STATE","LOCATION_FAIL")
  211. end
  212. end
  213. end
  214. end
  215. local function taskRead()
  216. local cacheData = ""
  217. local co = coroutine.running()
  218. while true do
  219. local s =""
  220. if openFlag then
  221. s= uart.read(uartID, "*l")
  222. end
  223. if s == "" then
  224. uart.on(uartID,"receive",function() coroutine.resume(co) end)
  225. coroutine.yield()
  226. uart.on(uartID,"receive")
  227. else
  228. cacheData = cacheData..s
  229. local d1,d2,nemaStr = sfind(cacheData,"\r\n")
  230. while d1 do
  231. writePendingCmds()
  232. nemaStr = ssub(cacheData,1,d2)
  233. cacheData = ssub(cacheData,d2+1,-1)
  234. if nmeaMode==0 or nmeaMode==2 then
  235. --解析一行NEMA数据
  236. parseNmea(nemaStr)
  237. end
  238. if (nmeaMode==1 or nmeaMode==2) and nmeaCbFnc then
  239. nmeaCbFnc(nemaStr)
  240. end
  241. d1,d2 = sfind(cacheData,"\r\n")
  242. end
  243. end
  244. end
  245. end
  246. function writeData(data)
  247. uart.write(uartID,data)
  248. log.info("gpsZkw.writeData",data:toHex())
  249. end
  250. -- GPS串口写命令操作
  251. -- @number class,消息类
  252. -- @number is,消息编号
  253. -- @string payload,有效载荷
  254. -- @return nil
  255. -- @usage gps.writeCmd(cmd)
  256. function writeCasic(class,id,payload)
  257. local tmp = pack.pack("<bbHbbA",0xBA,0xCE,payload:len(),class,id,payload)
  258. local checkSum = bit.lshift(id,24)+bit.lshift(class,16)+payload:len()
  259. for i=1,payload:len(),4 do
  260. checkSum = checkSum + payload:byte(i) + bit.lshift(payload:byte(i+1),8) + bit.lshift(payload:byte(i+2),16) + bit.lshift(payload:byte(i+3),24)
  261. end
  262. tmp = tmp..pack.pack("<I",checkSum)
  263. uart.write(uartID,tmp)
  264. --log.info("gpsZkw.writeCasic",tmp)
  265. log.info("gpsZkw.writeCasic",tmp:toHex())
  266. end
  267. -- GPS串口写命令操作
  268. -- @string cmd,GPS指令(cmd格式:"$PCAS04,7*XX\r\n")
  269. -- @bool isFull,cmd是否为完整的指令格式,包括校验和以及\r\n;true表示完整,false或者nil为不完整
  270. -- @return nil
  271. -- @usage gps.writeCmd(cmd)
  272. function writeCmd(cmd,isFull)
  273. local tmp = cmd
  274. if not isFull then
  275. tmp = 0
  276. for i=2,cmd:len()-1 do
  277. tmp = bit.bxor(tmp,cmd:byte(i))
  278. end
  279. tmp = cmd..(string.format("%02X",tmp)):upper().."\r\n"
  280. end
  281. uart.write(uartID,tmp)
  282. log.info("gpsZkw.writecmd",tmp)
  283. --log.info("gpsZkw.writeCmd",tmp:toHex())
  284. end
  285. function writePendingCmds()
  286. if not aerialModeSetted and aerialModeStr~="" then writeCmd(aerialModeStr) aerialModeSetted=true end
  287. --if not runModeSetted and runModeStr~="" then writeCmd(runModeStr) runModeSetted=true end
  288. if not nmeaReportSetted and nmeaReportStr~="" then writeCmd(nmeaReportStr) nmeaReportSetted=true end
  289. if not nmeaReportFreqSetted and nmeaReportFreqStr~="" then writeCmd(nmeaReportFreqStr) nmeaReportFreqSetted=true end
  290. end
  291. local function _open()
  292. if openFlag then return end
  293. pm.wake("gps.lua")
  294. uart.setup(uartID,uartBaudrate,uartDatabits,uartParity,uartStopbits)
  295. if not taskFlag then
  296. taskFlag =true
  297. sys.taskInit(taskRead)
  298. end
  299. if powerCbFnc then
  300. powerCbFnc(true)
  301. else
  302. pmd.ldoset(10,pmd.LDO_VIBR)
  303. rtos.sys32k_clk_out(1)
  304. end
  305. openFlag = true
  306. workAbnormalTimerId = sys.timerStart(sys.publish,8000,"GPS_WORK_ABNORMAL_IND")
  307. sys.publish("GPS_STATE","OPEN")
  308. fixFlag,filteredFlag = false
  309. Ggalng,Ggalat,Gsv,Sep = "","",""
  310. log.info("gpsZkw._open")
  311. end
  312. local function _close()
  313. if not openFlag then return end
  314. if powerCbFnc then
  315. powerCbFnc(false)
  316. else
  317. pmd.ldoset(0,pmd.LDO_VIBR)
  318. rtos.sys32k_clk_out(0)
  319. end
  320. uart.close(uartID)
  321. pm.sleep("gps.lua")
  322. openFlag = false
  323. sys.publish("GPS_STATE","CLOSE",fixFlag)
  324. stopWorkAbnormalTimer()
  325. fixFlag,filteredFlag = false
  326. sys.timerStop(filterTimerFnc)
  327. Ggalng,Ggalat,Gsv,Sep = "","",""
  328. aerialModeSetted,runModeSetted,nmeaReportSetted,nmeaReportFreqSetted = nil
  329. log.info("gpsZkw._close")
  330. end
  331. --- GPS应用模式1.
  332. --
  333. -- 打开GPS后,GPS定位成功时,如果有回调函数,会调用回调函数
  334. --
  335. -- 使用此应用模式调用gpsZkw.open打开的“GPS应用”,必须主动调用gpsZkw.close或者gpsZkw.closeAll才能关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  336. DEFAULT = 1
  337. --- GPS应用模式2.
  338. --
  339. -- 打开GPS后,如果在GPS开启最大时长到达时,没有定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“GPS应用”
  340. --
  341. -- 打开GPS后,如果在GPS开启最大时长内,定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“GPS应用”
  342. --
  343. -- 打开GPS后,在自动关闭此“GPS应用”前,可以调用gpsZkw.close或者gpsZkw.closeAll主动关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  344. TIMERORSUC = 2
  345. --- GPS应用模式3.
  346. --
  347. -- 打开GPS后,在GPS开启最大时长时间到达时,无论是否定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“GPS应用”
  348. --
  349. -- 打开GPS后,在自动关闭此“GPS应用”前,可以调用gpsZkw.close或者gpsZkw.closeAll主动关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
  350. TIMER = 3
  351. --“GPS应用”表
  352. local tList = {}
  353. --[[
  354. 函数名:delItem
  355. 功能 :从“GPS应用”表中删除一项“GPS应用”,并不是真正的删除,只是设置一个无效标志
  356. 参数 :
  357. mode:GPS应用模式
  358. para:
  359. para.tag:“GPS应用”标记
  360. para.val:GPS开启最大时长
  361. para.cb:回调函数
  362. 返回值:无
  363. ]]
  364. local function delItem(mode,para)
  365. for i=1,#tList do
  366. --标志有效 并且 GPS应用模式相同 并且 “GPS应用”标记相同
  367. if tList[i].flag and tList[i].mode==mode and tList[i].para.tag==para.tag then
  368. --设置无效标志
  369. tList[i].flag,tList[i].delay = false
  370. break
  371. end
  372. end
  373. end
  374. --[[
  375. 函数名:addItem
  376. 功能 :新增一项“GPS应用”到“GPS应用”表
  377. 参数 :
  378. mode:GPS应用模式
  379. para:
  380. para.tag:“GPS应用”标记
  381. para.val:GPS开启最大时长
  382. para.cb:回调函数
  383. 返回值:无
  384. ]]
  385. local function addItem(mode,para)
  386. --删除相同的“GPS应用”
  387. delItem(mode,para)
  388. local item,i,fnd = {flag=true, mode=mode, para=para}
  389. --如果是TIMERORSUC或者TIMER模式,初始化GPS工作剩余时间
  390. if mode==TIMERORSUC or mode==TIMER then item.para.remain = para.val end
  391. for i=1,#tList do
  392. --如果存在无效的“GPS应用”项,直接使用此位置
  393. if not tList[i].flag then
  394. tList[i] = item
  395. fnd = true
  396. break
  397. end
  398. end
  399. --新增一项
  400. if not fnd then table.insert(tList,item) end
  401. end
  402. local function existTimerItem()
  403. for i=1,#tList do
  404. if tList[i].flag and (tList[i].mode==TIMERORSUC or tList[i].mode==TIMER or tList[i].para.delay) then return true end
  405. end
  406. end
  407. local function timerFnc()
  408. for i=1,#tList do
  409. if tList[i].flag then
  410. log.info("gpsZkw.timerFnc@"..i,tList[i].mode,tList[i].para.tag,tList[i].para.val,tList[i].para.remain,tList[i].para.delay)
  411. local rmn,dly,md,cb = tList[i].para.remain,tList[i].para.delay,tList[i].mode,tList[i].para.cb
  412. if rmn and rmn>0 then
  413. tList[i].para.remain = rmn-1
  414. end
  415. if dly and dly>0 then
  416. tList[i].para.delay = dly-1
  417. end
  418. rmn = tList[i].para.remain
  419. if isFix() and md==TIMER and rmn==0 and not tList[i].para.delay then
  420. tList[i].para.delay = 1
  421. end
  422. dly = tList[i].para.delay
  423. if isFix() then
  424. if dly and dly==0 then
  425. if cb then cb(tList[i].para.tag) end
  426. if md == DEFAULT then
  427. tList[i].para.delay = nil
  428. else
  429. close(md,tList[i].para)
  430. end
  431. end
  432. else
  433. if rmn and rmn == 0 then
  434. if cb then cb(tList[i].para.tag) end
  435. close(md,tList[i].para)
  436. end
  437. end
  438. end
  439. end
  440. if existTimerItem() then sys.timerStart(timerFnc,1000) end
  441. end
  442. --[[
  443. 函数名:statInd
  444. 功能 :处理GPS定位成功的消息
  445. 参数 :
  446. evt:GPS消息类型
  447. 返回值:无
  448. ]]
  449. local function statInd(evt)
  450. --定位成功的消息
  451. if evt == "LOCATION_SUCCESS" then
  452. for i=1,#tList do
  453. log.info("gpsZkw.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)
  454. if tList[i].flag then
  455. if tList[i].mode ~= TIMER then
  456. tList[i].para.delay = 1
  457. if tList[i].mode == DEFAULT then
  458. if existTimerItem() then sys.timerStart(timerFnc,1000) end
  459. end
  460. end
  461. end
  462. end
  463. end
  464. end
  465. --- 打开一个“GPS应用”
  466. -- “GPS应用”:指的是使用GPS功能的一个应用
  467. -- 例如,假设有如下3种需求,要打开GPS,则一共有3个“GPS应用”:
  468. -- “GPS应用1”:每隔1分钟打开一次GPS
  469. -- “GPS应用2”:设备发生震动时打开GPS
  470. -- “GPS应用3”:收到一条特殊短信时打开GPS
  471. -- 只有所有“GPS应用”都关闭了,才会去真正关闭GPS
  472. -- 每个“GPS应用”打开或者关闭GPS时,最多有4个参数,其中 GPS应用模式和GPS应用标记 共同决定了一个唯一的“GPS应用”:
  473. -- 1、GPS应用模式(必选)
  474. -- 2、GPS应用标记(必选)
  475. -- 3、GPS开启最大时长[可选]
  476. -- 4、回调函数[可选]
  477. -- 例如gpsZkw.open(gpsZkw.TIMERORSUC,{tag="TEST",val=120,cb=testGpsCb})
  478. -- gpsZkw.TIMERORSUC为GPS应用模式,"TEST"为GPS应用标记,120秒为GPS开启最大时长,testGpsCb为回调函数
  479. -- @number mode GPS应用模式,支持gpsZkw.DEFAULT,gpsZkw.TIMERORSUC,gpsZkw.TIMER三种
  480. -- @param para table类型,GPS应用参数
  481. -- para.tag:string类型,GPS应用标记
  482. -- para.val:number类型,GPS应用开启最大时长,mode参数为gpsZkw.TIMERORSUC或者gpsZkw.TIMER时,此值才有意义
  483. -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag)
  484. -- @return nil
  485. -- @usage gpsZkw.open(gpsZkw.DEFAULT,{tag="TEST1",cb=test1Cb})
  486. -- @usage gpsZkw.open(gpsZkw.TIMERORSUC,{tag="TEST2",val=60,cb=test2Cb})
  487. -- @usage gpsZkw.open(gpsZkw.TIMER,{tag="TEST3",val=120,cb=test3Cb})
  488. -- @see DEFAULT,TIMERORSUC,TIMER
  489. function open(mode,para)
  490. assert((para and type(para) == "table" and para.tag and type(para.tag) == "string"),"gps.open para invalid")
  491. log.info("gpsZkw.open",mode,para.tag,para.val,para.cb)
  492. --如果GPS定位成功
  493. if isFix() then
  494. if mode~=TIMER then
  495. --执行回调函数
  496. if para.cb then para.cb(para.tag) end
  497. if mode==TIMERORSUC then return end
  498. end
  499. end
  500. addItem(mode,para)
  501. --真正去打开GPS
  502. _open()
  503. --启动1秒的定时器
  504. if existTimerItem() and not sys.timerIsActive(timerFnc) then
  505. sys.timerStart(timerFnc,1000)
  506. end
  507. end
  508. --- 关闭一个“GPS应用”
  509. -- 只是从逻辑上关闭一个GPS应用,并不一定真正关闭GPS,是有所有的GPS应用都处于关闭状态,才会去真正关闭GPS
  510. -- @number mode GPS应用模式,支持gps.DEFAULT,gps.TIMERORSUC,gps.TIMER三种
  511. -- @param para table类型,GPS应用参数
  512. -- para.tag:string类型,GPS应用标记
  513. -- para.val:number类型,GPS应用开启最大时长,mode参数为gps.TIMERORSUC或者gps.TIMER时,此值才有意义;使用close接口时,不需要传入此参数
  514. -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用close接口时,不需要传入此参数
  515. -- @return nil
  516. -- @usage GPS应用模式和GPS应用标记唯一确定一个“GPS应用”,调用本接口关闭时,mode和para.tag要和gpsZkw.open打开一个“GPS应用”时传入的mode和para.tag保持一致
  517. -- @usage gpsZkw.close(gpsZkw.DEFAULT,{tag="TEST1"})
  518. -- @usage gpsZkw.close(gpsZkw.TIMERORSUC,{tag="TEST2"})
  519. -- @usage gpsZkw.close(gpsZkw.TIMER,{tag="TEST3"})
  520. -- @see open,DEFAULT,TIMERORSUC,TIMER
  521. function close(mode,para)
  522. assert((para and type(para)=="table" and para.tag and type(para.tag)=="string"),"gps.close para invalid")
  523. log.info("gpsZkw.close",mode,para.tag,para.val,para.cb)
  524. --删除此“GPS应用”
  525. delItem(mode,para)
  526. local valid,i
  527. for i=1,#tList do
  528. if tList[i].flag then
  529. valid = true
  530. end
  531. end
  532. --如果没有一个“GPS应用”有效,则关闭GPS
  533. if not valid then _close() end
  534. end
  535. --- 关闭所有“GPS应用”
  536. -- @return nil
  537. -- @usage gpsZkw.closeAll()
  538. -- @see open,DEFAULT,TIMERORSUC,TIMER
  539. function closeAll()
  540. for i=1,#tList do
  541. if tList[i].flag and tList[i].para.cb then tList[i].para.cb(tList[i].para.tag) end
  542. close(tList[i].mode,tList[i].para)
  543. end
  544. end
  545. --- 判断一个“GPS应用”是否处于激活状态
  546. -- @number mode GPS应用模式,支持gps.DEFAULT,gps.TIMERORSUC,gps.TIMER三种
  547. -- @param para table类型,GPS应用参数
  548. -- para.tag:string类型,GPS应用标记
  549. -- para.val:number类型,GPS应用开启最大时长,mode参数为gpsZkw.TIMERORSUC或者gpsZkw.TIMER时,此值才有意义;使用isActive接口时,不需要传入此参数
  550. -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用isActive接口时,不需要传入此参数
  551. -- @return bool result,处于激活状态返回true,否则返回nil
  552. -- @usage GPS应用模式和GPS应用标记唯一确定一个“GPS应用”,调用本接口查询状态时,mode和para.tag要和gpsZkw.open打开一个“GPS应用”时传入的mode和para.tag保持一致
  553. -- @usage gpsZkw.isActive(gpsZkw.DEFAULT,{tag="TEST1"})
  554. -- @usage gpsZkw.isActive(gpsZkw.TIMERORSUC,{tag="TEST2"})
  555. -- @usage gpsZkw.isActive(gpsZkw.TIMER,{tag="TEST3"})
  556. -- @see open,DEFAULT,TIMERORSUC,TIMER
  557. function isActive(mode,para)
  558. assert((para and type(para)=="table" and para.tag and type(para.tag)=="string"),"gps.isActive para invalid")
  559. for i=1,#tList do
  560. if tList[i].flag and tList[i].mode==mode and tList[i].para.tag==para.tag then return true end
  561. end
  562. end
  563. --- 设置GPS模块供电控制的回调函数
  564. -- 如果使用的是Air800,或者供电控制使用的是LDO_VCAM,则打开GPS应用前不需要调用此接口进行设置
  565. -- 否则在调用gpsZkw.open前,使用此接口,传入自定义的供电控制函数cbFnc,GPS开启时,gpsZkw.lua自动执行cbFnc(true),GPS关闭时,gpsZkw.lua自动执行cbFnc(false)
  566. -- @param cbFnc function类型,用户自定义的GPS供电控制函数
  567. -- @return nil
  568. -- @usage gpsZkw.setPowerCbFnc(cbFnc)
  569. function setPowerCbFnc(cbFnc)
  570. powerCbFnc = cbFnc
  571. end
  572. --- 设置GPS模块和GSM模块之间数据通信的串口参数
  573. -- 如果使用的是Air800,或者使用的UART2(波特率115200,数据位8,无检验位,停止位1),则打开GPS应用前不需要调用此接口进行设置
  574. -- 否则在调用gpsZkw.open前,使用此接口,传入UART参数
  575. -- @number id UART ID,支持1和2,1表示UART1,2表示UART2
  576. -- @number baudrate 波特率,支持1200,2400,4800,9600,10400,14400,19200,28800,38400,57600,76800,115200,230400,460800,576000,921600,1152000,4000000
  577. -- @number databits 数据位,支持7,8
  578. -- @number parity 校验位,支持uart.PAR_NONE,uart.PAR_EVEN,uart.PAR_ODD
  579. -- @number stopbits 停止位,支持uart.STOP_1,uart.STOP_2
  580. -- @return nil
  581. -- @usage gpsZkw.setUart(2,115200,8,uart.PAR_NONE,uart.STOP_1)
  582. function setUart(id,baudrate,databits,parity,stopbits)
  583. uartID,uartBaudrate,uartDatabits,uartParity,uartStopbits = id,baudrate,databits,parity,stopbits
  584. end
  585. --- 设置GPS模块搜星模式.
  586. -- 如果使用的是Air820,不调用此接口配置,则默认同时开启GPS、北斗和glonass定位
  587. -- @number gps GPS定位系统,1是打开,0是关闭
  588. -- @number beidou 中国北斗定位系统,1是打开,0是关闭
  589. -- @number glonass 俄罗斯Glonass定位系统,1是打开,0是关闭
  590. -- @return nil
  591. -- @usage gpsZkw.setAeriaMode(1,1,0)
  592. function setAerialMode(gps,beidou,glonass)
  593. local gps = gps or 0
  594. local beidou = (beidou or 0)*2
  595. local glonass = (glonass or 0)*4
  596. local tmpStr = "$PCAS04,"..(gps+beidou+glonass).."*"
  597. if tmpStr~=aerialModeStr then
  598. aerialModeStr,aerialModeSetted = tmpStr
  599. end
  600. end
  601. --- 设置NMEA数据处理模式.
  602. -- 如果不调用此接口配置,则默认仅gpsZkw.lua内部处理NMEA数据
  603. -- @number mode NMEA数据处理模式,0表示仅gpsZkw.lua内部处理,1表示仅用户自己处理,2表示gpsZkw.lua和用户同时处理
  604. -- @param cbFnc function类型,用户处理一条NMEA数据的回调函数,mode为1和2时,此值才有意义
  605. -- @return nil
  606. -- @usage gpsZkw.setNmeaMode(0)
  607. -- @usage gpsZkw.setNmeaMode(1,cbFnc)
  608. -- @usage gpsZkw.setNmeaMode(2,cbFnc)
  609. function setNmeaMode(mode,cbFnc)
  610. nmeaMode,nmeaCbFnc = mode,cbFnc
  611. end
  612. --[[
  613. -- 设置GPS模块的运行模式.
  614. -- 如果不调用此接口配置,则默认为正常运行模式
  615. -- @number mode,运行模式
  616. -- 0:正常运行模式
  617. -- 1:周期超低功耗跟踪模式
  618. -- 2:周期低功耗模式
  619. -- 4:直接进入超低功耗跟踪模式
  620. -- 8:自动低功耗模式,可以通过串口唤醒
  621. -- 9:自动超低功耗跟踪模式,需要force on来唤醒
  622. -- @number runTm,单位毫秒,mode为0时表示NEMA数据的上报间隔,mode为1或者2时表示运行时长,其余mode时此值无意义
  623. -- @number sleepTm,单位毫秒,mode为1或者2时表示运行时长,其余mode时此值无意义
  624. -- @return nil
  625. -- @usage gps.setRunMode(0,1000)
  626. -- @usage gps.setRunMode(1,5000,2000)
  627. function setRunMode(mode,runTm,sleepTm)
  628. local rt,st = runTm or "",sleepTm or ""
  629. if mode==0 and rt then
  630. if rt>10000 then rt=10000 end
  631. if rt<200 then rt=200 end
  632. nmeaReportStr = "$PGKC101,"..rt.."*"
  633. end
  634. local tmpStr = "$PGKC105,"..mode..((mode==1 or mode==2) and (","..rt..","..st) or "").."*"
  635. if tmpStr~=runModeStr then
  636. runModeStr,runModeSetted = tmpStr
  637. end
  638. end
  639. ]]
  640. --- 设置NEMA语句的输出频率.
  641. -- @number[opt=1] rmc 单位秒,RMC语句输出频率,取值范围0到9之间的整数,0表示不输出
  642. -- @number[opt=1] gga 单位秒,GGA语句输出频率,取值范围0到9之间的整数,0表示不输出
  643. -- @number[opt=1] gsa 单位秒,GSA语句输出频率,取值范围0到9之间的整数,0表示不输出
  644. -- @number[opt=1] gsv 单位秒,GSV语句输出频率,取值范围0到9之间的整数,0表示不输出
  645. -- @number[opt=0] vtg 单位秒,VTG语句输出频率,取值范围0到9之间的整数,0表示不输出
  646. -- @number[opt=0] gll 单位秒,GLL语句输出频率,取值范围0到9之间的整数,0表示不输出
  647. -- @return nil
  648. -- @usage gpsZkw.setNemaReportFreq(5,0,0,0,0,0)
  649. function setNemaReportFreq(rmc,gga,gsa,gsv,vtg,gll)
  650. tmpStr = "$PCAS03,,,,,,,,,,,1*"
  651. if tmpStr~=nmeaReportFreqStr then
  652. nmeaReportFreqStr,nmeaReportFreqSetted = tmpStr
  653. end
  654. end
  655. --- 设置GPS定位成功后经纬度的过滤时间.
  656. -- @number[opt=0] seconds 单位秒,GPS定位成功后,丢弃前seconds秒的位置信息
  657. -- @return nil
  658. -- @usage gpsZkw.setLocationFilter(2)
  659. function setLocationFilter(seconds)
  660. filterSeconds = seconds or 0
  661. end
  662. function setFastFix(lat,lng,tm)
  663. local t = tm.year..","..tm.month..","..tm.day..","..tm.hour..","..tm.min..","..tm.sec.."*"
  664. log.info("gpsZkw.setFastFix",lat,lng,t)
  665. log.info("gpsZkw.setFastFix",lat,lng, json.encode(tm))
  666. if zkw530z and zkw530z.settime and zkw530z.setlocation and zkw530z.getaidini ~= nil then
  667. if lng~=nil and lat~=nil and lng~="" and lat ~="" then
  668. zkw530z.settime(tm.year,tm.month,tm.day,tm.hour,tm.min,tm.sec)
  669. zkw530z.setlocation(lat,lng)--参数:lat,lon
  670. local tmpbuf = zkw530z.getaidini()
  671. writeData(tmpbuf)
  672. log.info("gpsZkw.writecmd",tmpbuf:toHex())
  673. end
  674. else
  675. log.info("zkw530z.settime is not supported!")
  676. end
  677. end
  678. --- 获取GPS模块是否处于开启状态
  679. -- @return bool result,true表示开启状态,false或者nil表示关闭状态
  680. -- @usage gpsZkw.isOpen()
  681. function isOpen()
  682. return openFlag
  683. end
  684. --- 获取GPS模块是否定位成功
  685. -- @return bool result,true表示定位成功,false或者nil表示定位失败
  686. -- @usage gpsZkw.isFix()
  687. function isFix()
  688. return fixFlag
  689. end
  690. --- 获取GPS模块是否首次定位成功过
  691. -- @return bool result,true表示曾经定位成功
  692. -- @usage gpsZkw.isOnece()
  693. function isOnece()
  694. return fixOnece
  695. end
  696. -- 度分格式转换为度格式
  697. -- @string inStr 度分格式的位置
  698. -- @return string,度格式的位置
  699. -- @usage degreeMinuteToDegree("3114.50931")--->"31.2418218",31度14.50931分转换为31.2418218度
  700. -- @usage degreeMinuteToDegree("12128.44954")--->"121.4741590",121度28.44954分转换为121.4741590度
  701. local function degreeMinuteToDegree(inStr)
  702. local integer,fraction = smatch(inStr,"(%d+)%.(%d+)")
  703. if integer and fraction then
  704. local intLen = slen(integer)
  705. if intLen~=4 and intLen~=5 then log.error("gps.degreeMinuteToDegree integer error",inStr) return "" end
  706. if slen(fraction)<5 then fraction = fraction..srep("0",5-slen(fraction)) end
  707. fraction = ssub(fraction,1,5)
  708. local temp = tonumber(ssub(integer,intLen-1,intLen)..fraction)*10
  709. fraction = tostring((temp-(temp%6))/6)
  710. local fracLen = slen(fraction)
  711. if fracLen>7 then
  712. fraction = ssub(fraction,1,7)
  713. elseif fracLen<7 then
  714. fraction = srep("0",7-fracLen)..fraction
  715. end
  716. return ssub(integer,1,intLen-2).."."..fraction
  717. end
  718. return ""
  719. end
  720. --- 获取度格式的经纬度信息
  721. -- @string[opt=nil] typ 返回的经纬度格式,typ为"DEGREE_MINUTE"时表示返回度分格式,其余表示返回度格式
  722. -- @return table location
  723. -- 例如typ为"DEGREE_MINUTE"时返回{lngType="E",lng="12128.44954",latType="N",lat="3114.50931"}
  724. -- 例如typ不是"DEGREE_MINUTE"时返回{lngType="E",lng="121.123456",latType="N",lat="31.123456"}
  725. -- lngType:string类型,表示经度类型,取值"E","W"
  726. -- lng:string类型,表示度格式的经度值,无效时为""
  727. -- latType:string类型,表示纬度类型,取值"N","S"
  728. -- lat:string类型,表示度格式的纬度值,无效时为""
  729. -- @usage gpsZkw.getLocation()
  730. function getLocation(typ)
  731. return {
  732. lngType=longitudeType,
  733. lng=isFix() and (typ=="DEGREE_MINUTE" and longitude or degreeMinuteToDegree(longitude)) or "",
  734. latType=latitudeType,
  735. lat=isFix() and (typ=="DEGREE_MINUTE" and latitude or degreeMinuteToDegree(latitude)) or ""
  736. }
  737. end
  738. function getLastLocation(typ)
  739. if typ=="DEGREE_MINUTE" then
  740. return {
  741. lngType=longitudeType,
  742. lng=longitude,
  743. latType=latitudeType,
  744. lat=latitude
  745. }
  746. else
  747. return (longitude and longitude~="") and degreeMinuteToDegree(longitude) or "", (latitude and latitude~="") and degreeMinuteToDegree(latitude) or ""
  748. end
  749. end
  750. --- 获取海拔
  751. -- @return number altitude,海拔,单位米
  752. -- @usage gpsZkw.getAltitude()
  753. function getAltitude()
  754. return tonumber(smatch(altitude,"(%d+)") or "0")
  755. end
  756. --- 获取速度
  757. -- @return number kmSpeed,第一个返回值为公里每小时的速度
  758. -- @return number nmSpeed,第二个返回值为海里每小时的速度
  759. -- @usage gpsZkw.getSpeed()
  760. function getSpeed()
  761. local integer = tonumber(smatch(speed,"(%d+)") or "0")
  762. return (integer*1852 - (integer*1852 %1000))/1000,integer
  763. end
  764. --- 获取原始速度,字符串带浮点
  765. -- @return number speed 海里每小时的速度
  766. -- @usage gpsZkw.getOrgSpeed()
  767. function getOrgSpeed()
  768. return speed
  769. end
  770. --- 获取方向角
  771. -- @return number course,方向角
  772. -- @usage gpsZkw.getCourse()
  773. function getCourse()
  774. return tonumber(smatch(course,"(%d+)") or "0")
  775. end
  776. -- 获取所有可见卫星的最大信号强度
  777. -- @return number strength,最大信号强度
  778. -- @usage gpsZkw.getMaxSignalStrength()
  779. function getMaxSignalStrength()
  780. return maxSignalStrength
  781. end
  782. --- 获取可见卫星的个数
  783. -- @return number count,可见卫星的个数
  784. -- @usage gpsZkw.getViewedSateCnt()
  785. function getViewedSateCnt()
  786. return tonumber(viewedGpsSateCnt)+tonumber(viewedBdSateCnt)
  787. end
  788. --- 获取定位使用的卫星个数
  789. -- @return number count,定位使用的卫星个数
  790. -- @usage gpsZkw.getUsedSateCnt()
  791. function getUsedSateCnt()
  792. return tonumber(usedSateCnt)
  793. end
  794. --- 获取GGA语句中度分格式的经纬度信息
  795. -- @return string lng,度分格式的经度值(dddmm.mmmm),西经会添加一个-前缀,无效时为"";例如"12112.3456"表示东经121度12.3456分,"-12112.3456"表示西经121度12.3456分
  796. -- @return string lat,度分格式的纬度值(ddmm.mmmm),南纬会添加一个-前缀,无效时为"";例如"3112.3456"表示北纬31度12.3456分,"-3112.3456"表示南纬31度12.3456分
  797. -- @usage gpsZkw.getGgaloc()
  798. function getGgaloc()
  799. return Ggalng or "",Ggalat or ""
  800. end
  801. --- 获取RMC语句中的UTC时间
  802. -- 只有同时满足如下两个条件,返回值才有效
  803. -- 1、开启了GPS,并且定位成功
  804. -- 2、调用setParseItem接口,第一个参数设置为true
  805. -- @return table utcTime,UTC时间,nil表示无效,例如{year=2018,month=4,day=24,hour=11,min=52,sec=10}
  806. -- @usage gpsZkw.getUtcTime()
  807. function getUtcTime()
  808. return UtcTime
  809. end
  810. --- 获取定位使用的大地高
  811. -- @return number sep,大地高
  812. -- @usage gpsZkw.getSep()
  813. function getSep()
  814. return tonumber(Sep or "0")
  815. end
  816. --- 获取GSA语句中的可见卫星号
  817. -- 只有同时满足如下两个条件,返回值才有效
  818. -- 1、开启了GPS,并且定位成功
  819. -- 2、调用setParseItem接口,第三个参数设置为true
  820. -- @return string viewedSateId,可用卫星号,""表示无效
  821. -- @usage gpsZkw.getSateSn()
  822. function getSateSn()
  823. return SateSn or ""
  824. end
  825. --- 获取GSV语句中的可见卫星的信噪比
  826. -- 只有同时满足如下两个条件,返回值才有效
  827. -- 1、开启了GPS,并且定位成功
  828. -- 2、调用setParseItem接口,第二个参数设置为true
  829. -- @return string gsv,信噪比
  830. -- @usage gpsZkw.getGsv()
  831. function getGsv()
  832. return Gsv or ""
  833. end
  834. --- 设置是否需要解析的字段
  835. -- @bool[opt=nil] utcTime 是否解析RMC语句中的UTC时间,true表示解析,false或者nil不解析
  836. -- @bool[opt=nil] gsv 是否解析GSV语句,true表示解析,false或者nil不解析
  837. -- @bool[opt=nil] gsaId 是否解析GSA语句中的卫星ID,true表示解析,false或者nil不解析
  838. -- @usage gpsZkw.setParseItem(true,true,true)
  839. function setParseItem(utcTime,gsv,gsaId)
  840. psUtcTime,psGsv,psSn = utcTime,gsv,gsaId
  841. end
  842. function init()
  843. sys.subscribe("GPS_STATE",statInd)
  844. end
  845. function unInit()
  846. sys.unsubscribe("GPS_STATE",statInd)
  847. closeAll()
  848. end
  849. init()