| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933 |
- --- 模块功能:GPS模块管理
- -- 注意:此功能模块中的功能接口可以分为四大类:
- -- 1、GPS开启
- -- 2、GPS关闭
- -- 3、GPS定位数据读取
- -- 4、GPS参数和功能设置
- -- 1、2、3是通用功能,除了支持合宙的Air512G、Air551G、Air552G模块,理论上也支持其他厂家的串口GPS模块
- -- 4是专用功能,仅支持合宙的Air512G、Air551G、Air552G模块
- -- @module gps9701
- -- @author openLuat
- -- @license MIT
- -- @copyright openLuat
- -- @release 2017.10.23
- require"pm"
- require"utils"
- module(..., package.seeall)
- local smatch,sfind,slen,ssub,sbyte,sformat,srep = string.match,string.find,string.len,string.sub,string.byte,string.format,string.rep
- --GPS开启标志,true表示开启状态,false或者nil表示关闭状态
- local openFlag
- --GPS定位标志,"2D"表示2D定位,"3D"表示3D定位,其余表示未定位
- --GPS定位标志,true表示,其余表示未定位
- local fixFlag,fixOnece=nil,nil
- --GPS定位成功后,过滤掉前filterSeconds秒的经纬度信息
- --是否已经过滤完成
- local filterSeconds,filteredFlag = 0
- --从定位成功切换到定位失败,连续定位失败的次数
- local fixFailCnt = 0
- --经纬度类型和数据
- local latitudeType,latitude,longitudeType,longitude = "N","","E",""
- --海拔,速度,方向角
- local altitude,speed,course = "0","0","0"
- --参与定位的卫星个数,所有可见卫星的最大信号值,所有可见卫星的最大信号值中间缓存值
- local usedSateCnt,maxSignalStrength,maxSignalStrengthVar = "0",0,0
- --可见卫星个数
- local viewedGpsSateCnt,viewedBdSateCnt = "0","0"
- --可用卫星号,UTC时间,信噪比
- local SateSn,UtcTime,Gsv
- --大地高,度分经度,度分纬度
- local Sep,Ggalng,Ggalat
- --是否需要解析项
- local psUtcTime,psGsv,psSn
- --GPS供电设置函数
- local powerCbFnc
- --串口配置
- uartBaudrate = 115200
- local uartID,uartDatabits,uartParity,uartStopbits = 2,8,uart.PAR_NONE,uart.STOP_1
- --搜星模式命令字符串,"$PGKC115," .. gps .. "," .. glonass .. "," .. beidou .. "," .. galieo .. "*"
- local aerialModeStr,aerialModeSetted = ""
- --运行模式命令字符串,"$PGKC105," .. mode .. "," .. rt .. "," .. st .. "*"
- local runModeStr,runModeSetted = ""
- --正常运行模式下NMEA数据上报间隔命令字符串,"$PGKC101," .. interval .. "*"
- local nmeaReportStr,nmeaReportSetted = ""
- --每种NEMA数据的输出频率命令字符串
- local nmeaReportFreqStr,nmeaReportFreqSetted = ""
- --NMEA数据处理模式,0表示仅gps.lua内部处理,1表示仅用户自己处理,2表示gps.lua和用户同时处理
- --用户处理一条NMEA数据的回调函数
- local nmeaMode,nmeaCbFnc = 0
- --NMEA数据输出间隔
- local nmeaInterval = 1000
- --运行模式
- --0,正常运行模式
- --1,周期超低功耗跟踪模式
- --2,周期低功耗模式
- --4,直接进入超低功耗跟踪模式
- --8,自动低功耗模式,可以通过串口唤醒
- --9, 自动超低功耗跟踪模式,需要force on来唤醒
- local runMode = 0
- --gps 的串口线程是否在工作;
- local taskFlag=false
- --runMode为1或者2时,GPS运行状态和休眠状态的时长
- local runTime,sleepTime
- --检测gps是否工作正常的定时器ID
- local workAbnormalTimerId
- local agpsver = nil
- checkdatapack = false
- local testcoro = nil
- local i = 0
- --[[
- 函数名:getstrength
- 功能 :解析GSV数据
- 参数 :
- sg:NEMA中的一行GSV数据
- 返回值:无
- ]]
- local function getstrength(sg)
- sg = ssub(sg, 4, #sg)
- local d1,d2,curnum,lineno,total,sgv_str = sfind(sg,"GSV,(%d),(%d),(%d+),(.*)%*.*")
- if not curnum or not lineno or not total or not sgv_str then
- return
- end
- if lineno == nil then
- maxSignalStrengthVar = 0
- maxSignalStrength = 0
- elseif tonumber(lineno) == 1 then
- maxSignalStrength = maxSignalStrengthVar
- maxSignalStrengthVar = 0
- end
-
- local tmpstr,i = sgv_str
- for i=1,4 do
- local d1,d2,id,elevation,azimuth,strength = sfind(tmpstr,"(%d+),([%-]*%d*),(%d*),(%d*)")
- if id == nil then return end
- if strength == "" or not strength then
- strength = "00"
- end
- strength = tonumber(strength)
- if strength > maxSignalStrengthVar then
- maxSignalStrengthVar = strength
- end
- local idx,cur,fnd,tmpid = 0,id..","..elevation..","..azimuth..","..strength..",",false
- for tmpid in string.gmatch(Gsv,"(%d+),%d*,%d*,%d*,") do
- idx = idx + 1
- if tmpid == id then fnd = true break end
- end
- if fnd then
- local pattern,i = ""
- for i=1,idx do
- pattern = pattern.."%d+,%d*,%d*,%d*,"
- end
- local m1,m2 = sfind(Gsv,"^"..pattern)
- if m1 and m2 then
- local front = ssub(Gsv,1,m2)
- local n1,n2 = sfind(front,"%d+,%d*,%d*,%d*,$")
- if n1 and n2 then
- Gsv = ssub(Gsv,1,n1-1)..cur..ssub(Gsv,n2+1,-1)
- end
- end
- else
- Gsv = Gsv..cur
- end
- tmpstr = ssub(tmpstr,d2+1,-1)
- end
- end
- local function filterTimerFnc()
- log.info("gps.filterTimerFnc end")
- filteredFlag = true
- end
- local function stopWorkAbnormalTimer()
- if workAbnormalTimerId then
- sys.timerStop(workAbnormalTimerId)
- workAbnormalTimerId = nil
- end
- end
- local function parseNmea(s)
- if not s or s=="" then return end
- local lat,lng,spd,cog,gpsFind,gpsTime,gpsDate,locSateCnt,hdp,latTyp,lngTyp,altd
- local hexStr = s:toHex()
- if smatch(hexStr,"AAF00D0001009500039A00AA0F") then
- sys.publish("GPS_STATE","BINARY_CMD_ACK")
- agpsver = true
- stopWorkAbnormalTimer()
- i= i+1
- return
- elseif smatch(hexStr,"AAF00D000300") then
- sys.publish("GPS_STATE",smatch(hexStr,"^AAF00D000300FFFF") and "WRITE_EPH_END_ACK" or "WRITE_EPH_ACK")
- stopWorkAbnormalTimer()
- return
- end
- local fixed,workAbnormal
- if smatch(s,"GGA") then
- 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")
- if (gpsFind=="1" or gpsFind=="2" or gpsFind=="4") and altd then
- --fixed = true
- altitude = altd
- latitudeType,longitudeType,latitude,longitude = latTyp,lngTyp,lat,lng
- usedSateCnt = locSateCnt
- Ggalng,Ggalat = (lngTyp=="W" and "-" or "")..lng,(latTyp=="S" and "-" or "")..lat
- Sep = sep
- else
- fixed = false
- end
- elseif smatch(s,"RMC") then
- 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),")
- if gpsFind=="A" and cog then
- fixed = true
- latitudeType,longitudeType,latitude,longitude = latTyp,lngTyp,lat,lng
- speed = spd
- course = cog
- else
- fixed = false
- end
- if psUtcTime and gpsFind == "A" and gpsTime and gpsDate and gpsTime ~= "" and gpsDate ~= "" then
- 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))
- UtcTime = {year=2000+yy,month=mm,day=dd,hour=h,min=m,sec=s}
- end
- elseif smatch(s,"GPGSV") then
- viewedGpsSateCnt = tonumber(smatch(s,"%d+,%d+,(%d+)") or "0")
- if psGsv then getstrength(s) end
- elseif smatch(s,"BDGSV") then
- viewedBdSateCnt = tonumber(smatch(s,"%d+,%d+,(%d+)") or "0")
- if psGsv then getstrength(s) end
- elseif smatch(s,"GSA") then
- if psSn then
- local satesn = smatch(s,"GSA,%w*,%d*,(%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,%d*,)") or ""
- if slen(satesn) > 0 and smatch(satesn,"%d+,") then
- SateSn = satesn
- end
- end
- else
- workAbnormal = true
- end
-
- if not workAbnormal then
- stopWorkAbnormalTimer()
- end
-
- if filterSeconds>0 and fixed and not fixFlag and not filteredFlag then
- if not sys.timerIsActive(filterTimerFnc) then
- log.info("gps.filterTimerFnc begin")
- sys.publish("GPS_STATE","LOCATION_FILTER")
- sys.timerStart(filterTimerFnc,filterSeconds*1000)
- end
- return
- end
- --定位成功
- if fixed then
- if not fixFlag then
- fixFlag,filteredFlag = true,true
- fixOnece=true
- fixFailCnt = 0
- sys.publish("GPS_STATE","LOCATION_SUCCESS")
- end
- elseif fixed==false then
- if fixFlag then
- fixFailCnt = fixFailCnt+1
- if fixFailCnt>=20 then
- fixFlag,filteredFlag = false
- sys.timerStop(filterTimerFnc)
- sys.publish("GPS_STATE","LOCATION_FAIL")
- end
- end
- end
- end
- local function taskRead()
- local cacheData = ""
- local co = coroutine.running()
- while true do
- local s =""
- if openFlag then
- s= uart.read(uartID, "*l")
- end
- if i==2 then
- agpsver =false
- i = 0
- end
- if agpsver then
- if s=="" then
- checkdatapack = true
- else
- sys.publish("NOEMAL_RECE")
- end
- end
- if s == "" then
- uart.on(uartID,"receive",function() coroutine.resume(co) end)
- coroutine.yield()
- uart.on(uartID,"receive")
- else
- cacheData = cacheData..s
- if cacheData:toHex()=="AAF00D0001009500039A00AA0F" or smatch(cacheData:toHex(),"AAF00D000300") then
- cacheData = cacheData.."\r\n"
- end
- local d1,d2,nemaStr = sfind(cacheData,"\r\n")--截取串口收到的数据
- while d1 do
- writePendingCmds()
- nemaStr = ssub(cacheData,1,d2)
- cacheData = ssub(cacheData,d2+1,-1)
- if nmeaMode==0 or nmeaMode==2 then
- --解析一行NEMA数据
- parseNmea(nemaStr)
- end
- if (nmeaMode==1 or nmeaMode==2) and nmeaCbFnc then
- nmeaCbFnc(nemaStr)
- end
- d1,d2 = sfind(cacheData,"\r\n")
- end
- end
- end
- end
- -- GPS串口写命令操作
- -- @string cmd,GPS指令(cmd格式:"$PGKC149,1,115200*"或者"$PGKC149,1,115200*XX\r\n")
- -- @bool isFull,cmd是否为完整的指令格式,包括校验和以及\r\n;true表示完整,false或者nil为不完整
- -- @return nil
- -- @usage gps.writeCmd(cmd)
- function writeCmd(cmd,isFull)
- local tmp = cmd
- -- log.info("星历数据5",tmp:toHex())
- if not isFull then
- tmp = 0
- for i=2,cmd:len()-1 do
- tmp = bit.bxor(tmp,cmd:byte(i))
- end
- tmp = cmd..(string.format("%02X",tmp)):upper().."\r\n"
- end
- -- sys.timerStart(function() uart.write(uartID,tmp) end, 100)
- uart.write(uartID,tmp)
- -- log.info("gps.writecmd",tmp)
- log.info("gps.writecmd:toHex",uartID, tmp:toHex())
- end
- function writePendingCmds()
- if not aerialModeSetted and aerialModeStr~="" then writeCmd(aerialModeStr) aerialModeSetted=true end
- if not runModeSetted and runModeStr~="" then writeCmd(runModeStr) runModeSetted=true end
- if not nmeaReportSetted and nmeaReportStr~="" then writeCmd(nmeaReportStr) nmeaReportSetted=true end
- if not nmeaReportFreqSetted and nmeaReportFreqStr~="" then writeCmd(nmeaReportFreqStr) nmeaReportFreqSetted=true end
- end
- local function _open()
- if openFlag then return end--gps开启状态
- pm.wake("gps.lua")
- uart.setup(uartID,uartBaudrate,uartDatabits,uartParity,uartStopbits)
- if not taskFlag then --串口线程
- taskFlag =true
- sys.taskInit(taskRead)
- end
- if powerCbFnc then
- powerCbFnc(true)
- else
- pmd.ldoset(15, pmd.LDO_VMMC)
- rtos.sys32k_clk_out(1)
- end
- openFlag = true
- workAbnormalTimerId = sys.timerStart(sys.publish,8000,"GPS_WORK_ABNORMAL_IND")
- sys.publish("GPS_STATE","OPEN")
- fixFlag,filteredFlag = false
- Ggalng,Ggalat,Gsv,Sep = "","",""
- log.info("gps._open")
- end
- local function _close()
- if not openFlag then return end
- if powerCbFnc then
- powerCbFnc(false)
- else
- pmd.ldoset(0,pmd.LDO_VMMC)
- rtos.sys32k_clk_out(0)
- end
- uart.close(uartID)
- pm.sleep("gps.lua")
- openFlag = false
- sys.publish("GPS_STATE","CLOSE",fixFlag)
- stopWorkAbnormalTimer()
- fixFlag,filteredFlag = false
- sys.timerStop(filterTimerFnc)
- Ggalng,Ggalat,Gsv,Sep = "","",""
- aerialModeSetted,runModeSetted,nmeaReportSetted,nmeaReportFreqSetted = nil
- log.info("gps._close")
- end
- --- GPS应用模式1.
- --
- -- 打开GPS后,GPS定位成功时,如果有回调函数,会调用回调函数
- --
- -- 使用此应用模式调用gps9701.open打开的“GPS应用”,必须主动调用gps9701.close或者gps9701.closeAll才能关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
- DEFAULT = 1
- --- GPS应用模式2.
- --
- -- 打开GPS后,如果在GPS开启最大时长到达时,没有定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“GPS应用”
- --
- -- 打开GPS后,如果在GPS开启最大时长内,定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“GPS应用”
- --
- -- 打开GPS后,在自动关闭此“GPS应用”前,可以调用gps9701.close或者gps9701.closeAll主动关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
- TIMERORSUC = 2
- --- GPS应用模式3.
- --
- -- 打开GPS后,在GPS开启最大时长时间到达时,无论是否定位成功,如果有回调函数,会调用回调函数,然后自动关闭此“GPS应用”
- --
- -- 打开GPS后,在自动关闭此“GPS应用”前,可以调用gps9701.close或者gps9701.closeAll主动关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
- TIMER = 3
- --“GPS应用”表
- local tList = {}
- --[[
- 函数名:delItem
- 功能 :从“GPS应用”表中删除一项“GPS应用”,并不是真正的删除,只是设置一个无效标志
- 参数 :
- mode:GPS应用模式
- para:
- para.tag:“GPS应用”标记
- para.val:GPS开启最大时长
- para.cb:回调函数
- 返回值:无
- ]]
- local function delItem(mode,para)
- for i=1,#tList do
- --标志有效 并且 GPS应用模式相同 并且 “GPS应用”标记相同
- if tList[i].flag and tList[i].mode==mode and tList[i].para.tag==para.tag then
- --设置无效标志
- tList[i].flag,tList[i].delay = false
- break
- end
- end
- end
- --[[
- 函数名:addItem
- 功能 :新增一项“GPS应用”到“GPS应用”表
- 参数 :
- mode:GPS应用模式
- para:
- para.tag:“GPS应用”标记
- para.val:GPS开启最大时长
- para.cb:回调函数
- 返回值:无
- ]]
- local function addItem(mode,para)
- --删除相同的“GPS应用”
- delItem(mode,para)
- local item,i,fnd = {flag=true, mode=mode, para=para}
- --如果是TIMERORSUC或者TIMER模式,初始化GPS工作剩余时间
- if mode==TIMERORSUC or mode==TIMER then item.para.remain = para.val end
- for i=1,#tList do
- --如果存在无效的“GPS应用”项,直接使用此位置
- if not tList[i].flag then
- tList[i] = item
- fnd = true
- break
- end
- end
- --新增一项
- if not fnd then table.insert(tList,item) end
- end
- local function existTimerItem()
- for i=1,#tList do
- if tList[i].flag and (tList[i].mode==TIMERORSUC or tList[i].mode==TIMER or tList[i].para.delay) then return true end
- end
- end
- local function timerFnc()
- for i=1,#tList do
- if tList[i].flag then
- log.info("gps.timerFnc@"..i,tList[i].mode,tList[i].para.tag,tList[i].para.val,tList[i].para.remain,tList[i].para.delay)
- local rmn,dly,md,cb = tList[i].para.remain,tList[i].para.delay,tList[i].mode,tList[i].para.cb
- if rmn and rmn>0 then
- tList[i].para.remain = rmn-1
- end
- if dly and dly>0 then
- tList[i].para.delay = dly-1
- end
- rmn = tList[i].para.remain
- if isFix() and md==TIMER and rmn==0 and not tList[i].para.delay then
- tList[i].para.delay = 1
- end
- dly = tList[i].para.delay
- if isFix() then
- if dly and dly==0 then
- if cb then cb(tList[i].para.tag) end
- if md == DEFAULT then
- tList[i].para.delay = nil
- else
- close(md,tList[i].para)
- end
- end
- else
- if rmn and rmn == 0 then
- if cb then cb(tList[i].para.tag) end
- close(md,tList[i].para)
- end
- end
- end
- end
- if existTimerItem() then sys.timerStart(timerFnc,1000) end
- end
- --[[
- 函数名:statInd
- 功能 :处理GPS定位成功的消息
- 参数 :
- evt:GPS消息类型
- 返回值:无
- ]]
- local function statInd(evt)
- --定位成功的消息
- if evt == "LOCATION_SUCCESS" then
- for i=1,#tList do
- log.info("gps.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)
- if tList[i].flag then
- if tList[i].mode ~= TIMER then
- tList[i].para.delay = 1
- if tList[i].mode == DEFAULT then
- if existTimerItem() then sys.timerStart(timerFnc,1000) end
- end
- end
- end
- end
- end
- end
- --- 打开一个“GPS应用”
- -- “GPS应用”:指的是使用GPS功能的一个应用
- -- 例如,假设有如下3种需求,要打开GPS,则一共有3个“GPS应用”:
- -- “GPS应用1”:每隔1分钟打开一次GPS
- -- “GPS应用2”:设备发生震动时打开GPS
- -- “GPS应用3”:收到一条特殊短信时打开GPS
- -- 只有所有“GPS应用”都关闭了,才会去真正关闭GPS
- -- 每个“GPS应用”打开或者关闭GPS时,最多有4个参数,其中 GPS应用模式和GPS应用标记 共同决定了一个唯一的“GPS应用”:
- -- 1、GPS应用模式(必选)
- -- 2、GPS应用标记(必选)
- -- 3、GPS开启最大时长[可选]
- -- 4、回调函数[可选]
- -- 例如gps9701.open(gps9701.TIMERORSUC,{tag="TEST",val=120,cb=testGpsCb})
- -- gps9701.TIMERORSUC为GPS应用模式,"TEST"为GPS应用标记,120秒为GPS开启最大时长,testGpsCb为回调函数
- -- @number mode GPS应用模式,支持gps9701.DEFAULT,gps9701.TIMERORSUC,gps9701.TIMER三种
- -- @param para table类型,GPS应用参数
- -- para.tag:string类型,GPS应用标记
- -- para.val:number类型,GPS应用开启最大时长,mode参数为gps9701.TIMERORSUC或者gps9701.TIMER时,此值才有意义
- -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag)
- -- @return nil
- -- @usage gps9701.open(gps9701.DEFAULT,{tag="TEST1",cb=test1Cb})
- -- @usage gps9701.open(gps9701.TIMERORSUC,{tag="TEST2",val=60,cb=test2Cb})
- -- @usage gps9701.open(gps9701.TIMER,{tag="TEST3",val=120,cb=test3Cb})
- -- @see DEFAULT,TIMERORSUC,TIMER
- function open(mode,para)
- assert((para and type(para) == "table" and para.tag and type(para.tag) == "string"),"gps.open para invalid")
- log.info("gps.open",mode,para.tag,para.val,para.cb)
- --如果GPS定位成功
- if isFix() then
- if mode~=TIMER then
- --执行回调函数
- if para.cb then para.cb(para.tag) end
- if mode==TIMERORSUC then return end
- end
- end
- addItem(mode,para)--gps应用
- --真正去打开GPS
- _open()
- --启动1秒的定时器
- if existTimerItem() and not sys.timerIsActive(timerFnc) then
- sys.timerStart(timerFnc,1000)
- end
- end
- --- 关闭一个“GPS应用”
- -- 只是从逻辑上关闭一个GPS应用,并不一定真正关闭GPS,是有所有的GPS应用都处于关闭状态,才会去真正关闭GPS
- -- @number mode GPS应用模式,支持gps9701.DEFAULT,gps9701.TIMERORSUC,gps9701.TIMER三种
- -- @param para table类型,GPS应用参数
- -- para.tag:string类型,GPS应用标记
- -- para.val:number类型,GPS应用开启最大时长,mode参数为gps9701.TIMERORSUC或者gps9701.TIMER时,此值才有意义;使用close接口时,不需要传入此参数
- -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用close接口时,不需要传入此参数
- -- @return nil
- -- @usage GPS应用模式和GPS应用标记唯一确定一个“GPS应用”,调用本接口关闭时,mode和para.tag要和gps9701.open打开一个“GPS应用”时传入的mode和para.tag保持一致
- -- @usage gps9701.close(gps9701.DEFAULT,{tag="TEST1"})
- -- @usage gps9701.close(gps9701.TIMERORSUC,{tag="TEST2"})
- -- @usage gps9701.close(gps9701.TIMER,{tag="TEST3"})
- -- @see open,DEFAULT,TIMERORSUC,TIMER
- function close(mode,para)
- assert((para and type(para)=="table" and para.tag and type(para.tag)=="string"),"gps.close para invalid")
- log.info("gps.close",mode,para.tag,para.val,para.cb)
- --删除此“GPS应用”
- delItem(mode,para)
- local valid,i
- for i=1,#tList do
- if tList[i].flag then
- valid = true
- end
- end
- --如果没有一个“GPS应用”有效,则关闭GPS
- if not valid then _close() end
- end
- --- 关闭所有“GPS应用”
- -- @return nil
- -- @usage gps9701.closeAll()
- -- @see open,DEFAULT,TIMERORSUC,TIMER
- function closeAll()
- for i=1,#tList do
- if tList[i].flag and tList[i].para.cb then tList[i].para.cb(tList[i].para.tag) end
- close(tList[i].mode,tList[i].para)
- end
- end
- --- 判断一个“GPS应用”是否处于激活状态
- -- @number mode GPS应用模式,支持gps9701.DEFAULT,gps9701.TIMERORSUC,gps9701.TIMER三种
- -- @param para table类型,GPS应用参数
- -- para.tag:string类型,GPS应用标记
- -- para.val:number类型,GPS应用开启最大时长,mode参数为gps9701.TIMERORSUC或者gps9701.TIMER时,此值才有意义;使用isActive接口时,不需要传入此参数
- -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用isActive接口时,不需要传入此参数
- -- @return bool result,处于激活状态返回true,否则返回nil
- -- @usage GPS应用模式和GPS应用标记唯一确定一个“GPS应用”,调用本接口查询状态时,mode和para.tag要和gps9701.open打开一个“GPS应用”时传入的mode和para.tag保持一致
- -- @usage gps9701.isActive(gps9701.DEFAULT,{tag="TEST1"})
- -- @usage gps9701.isActive(gps9701.TIMERORSUC,{tag="TEST2"})
- -- @usage gps9701.isActive(gps9701.TIMER,{tag="TEST3"})
- -- @see open,DEFAULT,TIMERORSUC,TIMER
- function isActive(mode,para)
- assert((para and type(para)=="table" and para.tag and type(para.tag)=="string"),"gps.isActive para invalid")
- for i=1,#tList do
- if tList[i].flag and tList[i].mode==mode and tList[i].para.tag==para.tag then return true end
- end
- end
- --- 设置GPS模块供电控制的回调函数
- -- 如果使用的是Air800,或者供电控制使用的是LDO_VCAM,则打开GPS应用前不需要调用此接口进行设置
- -- 否则在调用gps9701.open前,使用此接口,传入自定义的供电控制函数cbFnc,GPS开启时,gps9701.lua自动执行cbFnc(true),GPS关闭时,gps9701.lua自动执行cbFnc(false)
- -- @param cbFnc function类型,用户自定义的GPS供电控制函数
- -- @return nil
- -- @usage gps9701.setPowerCbFnc(cbFnc)
- function setPowerCbFnc(cbFnc)
- powerCbFnc = cbFnc
- end
- --- 设置GPS模块和GSM模块之间数据通信的串口参数
- -- 如果使用的是Air800,或者使用的UART2(波特率115200,数据位8,无检验位,停止位1),则打开GPS应用前不需要调用此接口进行设置
- -- 否则在调用gps9701.open前,使用此接口,传入UART参数
- -- @number id UART ID,支持1和2,1表示UART1,2表示UART2
- -- @number baudrate 波特率,支持1200,2400,4800,9600,10400,14400,19200,28800,38400,57600,76800,115200,230400,460800,576000,921600,1152000,4000000
- -- @number databits 数据位,支持8
- -- @number parity 校验位,支持uart.PAR_NONE,uart.PAR_EVEN,uart.PAR_ODD
- -- @number stopbits 停止位,支持uart.STOP_1,uart.STOP_2
- -- @return nil
- -- @usage gps9701.setUart(2,115200,8,uart.PAR_NONE,uart.STOP_1)
- function setUart(id,baudrate,databits,parity,stopbits)
- uartID,uartBaudrate,uartDatabits,uartParity,uartStopbits = id,baudrate,databits,parity,stopbits
- end
- --- 设置GPS模块搜星模式.
- -- 如果使用的是Air800或者Air530,不调用此接口配置,则默认同时开启GPS和北斗定位
- -- @number gps GPS定位系统,1是打开,0是关闭
- -- @number beidou 中国北斗定位系统,1是打开,0是关闭
- -- @number glonass 俄罗斯Glonass定位系统,1是打开,0是关闭
- -- @number galieo 欧盟伽利略定位系统,1是打开,0是关闭
- -- @return nil
- -- @usage gps9701.setAeriaMode(1,1,0,0)
- function setAerialMode(gps,beidou,glonass,galieo)
- local gps = gps or 0
- local glonass = glonass or 0
- local beidou = beidou or 0
- local galieo = galieo or 0
- if gps+glonass+beidou+galieo == 0 then gps=1 beidou=1 end
- if gps==1 then gps=1 end
- if glonass==1 then glonass=4 end
- if beidou==1 then beidou= 8 end
- if galieo==1 then galieo= 2 end
- local searchstar=gps+glonass+beidou+galieo
- searchstar = string.format("%X",searchstar)
- log.info("搜星",searchstar)
- --local tmpStr = "$PGKC115,"..gps..","..glonass..","..beidou..","..galieo.."*"
- local tmpStr = "$PGKC121,0,"..searchstar..",0*"
- if tmpStr~=aerialModeStr then
- aerialModeStr,aerialModeSetted = tmpStr
- end
- end
- --- 设置NMEA数据处理模式.
- -- 如果不调用此接口配置,则默认仅gps.lua内部处理NMEA数据
- -- @number mode NMEA数据处理模式,0表示仅gps.lua内部处理,1表示仅用户自己处理,2表示gps.lua和用户同时处理
- -- @param cbFnc function类型,用户处理一条NMEA数据的回调函数,mode为1和2时,此值才有意义
- -- @return nil
- -- @usage gps9701.setNmeaMode(0)
- -- @usage gps9701.setNmeaMode(1,cbFnc)
- -- @usage gps9701.setNmeaMode(2,cbFnc)
- function setNmeaMode(mode,cbFnc)
- nmeaMode,nmeaCbFnc = mode,cbFnc
- end
- --- 设置GPS模块的运行模式.
- -- 如果不调用此接口配置,则默认为正常运行模式
- -- @number mode 运行模式
- -- 0:正常运行模式
- -- 1:周期超低功耗跟踪模式
- -- 4:直接进入超低功耗跟踪模式
- -- 8:低功耗模式,可以通过串口发送命令唤醒
- -- @number runTm 单位毫秒,mode为0时表示NEMA数据的上报间隔,mode为1时表示运行时长,其余mode时此值无意义
- -- @number sleepTm 单位毫秒,mode为1时表示运行时长,其余mode时此值无意义
- -- @return nil
- -- @usage gps9701.setRunMode(0,1000)
- -- @usage gps9701.setRunMode(1,5000,2000)
- function setRunMode(mode,runTm,sleepTm)
- local rt,st = runTm or "",sleepTm or ""
- if mode==0 and rt then
- if rt>10000 then rt=10000 end
- if rt<100 then rt=100 end
- nmeaReportStr = "$PGKC101,"..rt.."*"
- end
- local tmpStr = "$PGKC105,"..mode..((mode==1) and (","..rt..","..st) or "").."*"
- if tmpStr~=runModeStr then
- runModeStr,runModeSetted = tmpStr
- end
- end
- --- 设置NEMA语句的输出频率.
- -- @number[opt=1] rmc 单位秒,RMC语句输出频率,取值范围0到10之间的整数,0表示不输出
- -- @number[opt=1] gga 单位秒,GGA语句输出频率,取值范围0到10之间的整数,0表示不输出
- -- @number[opt=1] gsa 单位秒,GSA语句输出频率,取值范围0到10之间的整数,0表示不输出
- -- @number[opt=1] gsv 单位秒,GSV语句输出频率,取值范围0到10之间的整数,0表示不输出
- -- @number[opt=1] vtg 单位秒,VTG语句输出频率,取值范围0到10之间的整数,0表示不输出
- -- @number[opt=0] gll 单位秒,GLL语句输出频率,取值范围0到10之间的整数,0表示不输出
- -- @return nil
- -- @usage gps9701.setNemaReportFreq(5,0,0,0,0,0)
- function setNemaReportFreq(rmc,gga,gsa,gsv,vtg,gll)
- local tmpStr = "$PGKC242,"..(gll or 0)..","..(rmc or 1)..","..(vtg or 1)..","..(gga or 1)..","..(gsa or 1)..","..(gsv or 1)..",0,0,0,0,0,0,0,0,0,0,0,0,0".."*"
- if tmpStr~=nmeaReportFreqStr then
- nmeaReportFreqStr,nmeaReportFreqSetted = tmpStr
- end
- end
- --- 设置GPS定位成功后经纬度的过滤时间.
- -- @number[opt=0] seconds 单位秒,GPS定位成功后,丢弃前seconds秒的位置信息
- -- @return nil
- -- @usage gps9701.setLocationFilter(2)
- function setLocationFilter(seconds)
- filterSeconds = seconds or 0
- end
- function setFastFix(lat,lng,tm)
- local t = tm.year..","..tm.month..","..tm.day..","..tm.hour..","..tm.min..","..tm.sec.."*"
- log.info("gps.setFastFix",lat,lng,t)
- -- writeCmd("$PGKC634,"..t)
- writeCmd("$PGKC639,"..lat..","..lng..",0,"..t)
- end
- --- 获取GPS模块是否处于开启状态
- -- @return bool result,true表示开启状态,false或者nil表示关闭状态
- -- @usage gps9701.isOpen()
- function isOpen()
- return openFlag
- end
- --- 获取GPS模块是否定位成功
- -- @return bool result,true表示定位成功,false或者nil表示定位失败
- -- @usage gps9701.isFix()
- function isFix()
- return fixFlag
- end
- --- 获取GPS模块是否首次定位成功过
- -- @return bool result,true表示曾经定位成功
- -- @usage gps9701.isOnece()
- function isOnece()
- return fixOnece
- end
- -- 度分格式转换为度格式
- -- @string inStr 度分格式的位置
- -- @return string,度格式的位置
- -- @usage degreeMinuteToDegree("3114.50931")--->"31.2418218",31度14.50931分转换为31.2418218度
- -- @usage degreeMinuteToDegree("12128.44954")--->"121.4741590",121度28.44954分转换为121.4741590度
- local function degreeMinuteToDegree(inStr)
- local integer,fraction = smatch(inStr,"(%d+)%.(%d+)")
- if integer and fraction then
- local intLen = slen(integer)
- if intLen~=4 and intLen~=5 then log.error("gps.degreeMinuteToDegree integer error",inStr) return "" end
- if slen(fraction)<5 then fraction = fraction..srep("0",5-slen(fraction)) end
- fraction = ssub(fraction,1,5)
- local temp = tonumber(ssub(integer,intLen-1,intLen)..fraction)*10
- fraction = tostring((temp-(temp%6))/6)
- local fracLen = slen(fraction)
- if fracLen>7 then
- fraction = ssub(fraction,1,7)
- elseif fracLen<7 then
- fraction = srep("0",7-fracLen)..fraction
- end
- return ssub(integer,1,intLen-2).."."..fraction
- end
- return ""
- end
- --- 获取度格式的经纬度信息
- -- @string[opt=nil] typ 返回的经纬度格式,typ为"DEGREE_MINUTE"时表示返回度分格式,其余表示返回度格式
- -- @return table location
- -- 例如typ为"DEGREE_MINUTE"时返回{lngType="E",lng="12128.44954",latType="N",lat="3114.50931"}
- -- 例如typ不是"DEGREE_MINUTE"时返回{lngType="E",lng="121.123456",latType="N",lat="31.123456"}
- -- lngType:string类型,表示经度类型,取值"E","W"
- -- lng:string类型,表示度格式的经度值,无效时为""
- -- latType:string类型,表示纬度类型,取值"N","S"
- -- lat:string类型,表示度格式的纬度值,无效时为""
- -- @usage gps9701.getLocation()
- function getLocation(typ)
- return {
- lngType=longitudeType,
- lng=isFix() and (typ=="DEGREE_MINUTE" and longitude or degreeMinuteToDegree(longitude)) or "",
- latType=latitudeType,
- lat=isFix() and (typ=="DEGREE_MINUTE" and latitude or degreeMinuteToDegree(latitude)) or ""
- }
- end
- function getLastLocation(typ)
- if typ=="DEGREE_MINUTE" then
- return {
- lngType=longitudeType,
- lng=longitude,
- latType=latitudeType,
- lat=latitude
- }
- else
- return (longitude and longitude~="") and degreeMinuteToDegree(longitude) or "", (latitude and latitude~="") and degreeMinuteToDegree(latitude) or ""
- end
- end
- --- 获取海拔
- -- @return number altitude,海拔,单位米
- -- @usage gps9701.getAltitude()
- function getAltitude()
- return tonumber(smatch(altitude,"(%d+)") or "0")
- end
- --- 获取速度
- -- @return number kmSpeed,第一个返回值为公里每小时的速度
- -- @return number nmSpeed,第二个返回值为海里每小时的速度
- -- @usage gps9701.getSpeed()
- function getSpeed()
- local integer = tonumber(smatch(speed,"(%d+)") or "0")
- return (integer*1852 - (integer*1852 %1000))/1000,integer
- end
- --- 获取原始速度,字符串带浮点
- -- @return number speed 海里每小时的速度
- -- @usage gps9701.getOrgSpeed()
- function getOrgSpeed()
- return speed
- end
- --- 获取方向角
- -- @return number course,方向角
- -- @usage gps9701.getCourse()
- function getCourse()
- return tonumber(smatch(course,"(%d+)") or "0")
- end
- -- 获取所有可见卫星的最大信号强度
- -- @return number strength,最大信号强度
- -- @usage gps9701.getMaxSignalStrength()
- function getMaxSignalStrength()
- return maxSignalStrength
- end
- --- 获取可见卫星的个数
- -- @return number count,可见卫星的个数
- -- @usage gps9701.getViewedSateCnt()
- function getViewedSateCnt()
- return tonumber(viewedGpsSateCnt)+tonumber(viewedBdSateCnt)
- end
- --- 获取定位使用的卫星个数
- -- @return number count,定位使用的卫星个数
- -- @usage gps9701.getUsedSateCnt()
- function getUsedSateCnt()
- return tonumber(usedSateCnt)
- end
- --- 获取GGA语句中度分格式的经纬度信息
- -- @return string lng,度分格式的经度值(dddmm.mmmm),西经会添加一个-前缀,无效时为"";例如"12112.3456"表示东经121度12.3456分,"-12112.3456"表示西经121度12.3456分
- -- @return string lat,度分格式的纬度值(ddmm.mmmm),南纬会添加一个-前缀,无效时为"";例如"3112.3456"表示北纬31度12.3456分,"-3112.3456"表示南纬31度12.3456分
- -- @usage gps9701.getGgaloc()
- function getGgaloc()
- return Ggalng or "",Ggalat or ""
- end
- --- 获取RMC语句中的UTC时间
- -- 只有同时满足如下两个条件,返回值才有效
- -- 1、开启了GPS,并且定位成功
- -- 2、调用setParseItem接口,第一个参数设置为true
- -- @return table utcTime,UTC时间,nil表示无效,例如{year=2018,month=4,day=24,hour=11,min=52,sec=10}
- -- @usage gps9701.getUtcTime()
- function getUtcTime()
- return UtcTime
- end
- --- 获取定位使用的大地高
- -- @return number sep,大地高
- -- @usage gps9701.getSep()
- function getSep()
- return tonumber(Sep or "0")
- end
- --- 获取GSA语句中的可见卫星号
- -- 只有同时满足如下两个条件,返回值才有效
- -- 1、开启了GPS,并且定位成功
- -- 2、调用setParseItem接口,第三个参数设置为true
- -- @return string viewedSateId,可用卫星号,""表示无效
- -- @usage gps9701.getSateSn()
- function getSateSn()
- return SateSn or ""
- end
- --- 获取GSV语句中的可见卫星的信噪比
- -- 只有同时满足如下两个条件,返回值才有效
- -- 1、开启了GPS,并且定位成功
- -- 2、调用setParseItem接口,第二个参数设置为true
- -- @return string gsv,信噪比
- -- @usage gps9701.getGsv()
- function getGsv()
- return Gsv or ""
- end
- --- 设置是否需要解析的字段
- -- @bool[opt=nil] utcTime 是否解析RMC语句中的UTC时间,true表示解析,false或者nil不解析
- -- @bool[opt=nil] gsv 是否解析GSV语句,true表示解析,false或者nil不解析
- -- @bool[opt=nil] gsaId 是否解析GSA语句中的卫星ID,true表示解析,false或者nil不解析
- -- @usage gps.setParseItem(true,true,true)
- function setParseItem(utcTime,gsv,gsaId)
- psUtcTime,psGsv,psSn = utcTime,gsv,gsaId
- end
- function init()
- sys.subscribe("GPS_STATE",statInd)
- end
- function unInit()
- sys.unsubscribe("GPS_STATE",statInd)
- closeAll()
- end
- init()
|