--- 模块功能:GPS模块管理 -- 注意:此功能模块中的功能接口可以分为四大类: -- 1、GPS开启 -- 2、GPS关闭 -- 3、GPS定位数据读取 -- 4、GPS参数和功能设置 -- 1、2、3是通用功能,除了支持合宙的Air530H模块,理论上也支持其他厂家的串口GPS模块 -- 4是专用功能,仅支持合宙的Air530H和Air82x系列模块 -- @module gpsHxxt -- @author openLuat -- @license MIT -- @copyright openLuat -- @release 2021.6.19 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 = 3,8,uart.PAR_NONE,uart.STOP_1 --搜星模式命令字符串,"$PGKC115," .. gps .. "," .. glonass .. "," .. beidou .. "," .. galieo .. "*" local aerialModeStr,aerialModeSetted = "" --启动模式命令字符串 local startModeStr,startModeSetted = "","" --运行模式命令字符串,"$PGKC105," .. mode .. "," .. rt .. "," .. st .. "*" local runModeStr,runModeSetted = "","" --正常运行模式下NMEA数据上报间隔命令字符串,"$PGKC101," .. interval .. "*" local nmeaReportStr,nmeaReportSetted = "" --每种NEMA数据的输出频率命令字符串 local nmeaReportFreqStr,nmeaReportFreqSetted = "" --NMEA数据处理模式,0表示仅gpsHxxt.lua内部处理,1表示仅用户自己处理,2表示gpsHxxt.lua和用户同时处理 --用户处理一条NMEA数据的回调函数 local nmeaMode,nmeaCbFnc = 0 --NMEA数据输出间隔 local nmeaInterval = 1000 --运行模式 --0,正常运行模式 --1,低功耗模式 local runMode = 0 --gps 的串口线程是否在工作; local taskFlag=false --runMode为1或者2时,GPS运行状态和休眠状态的时长 local runTime,sleepTime --检测gps是否工作正常的定时器ID local workAbnormalTimerId --[[ 函数名: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("gpsHxxt.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 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("gpsHxxt.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 s == "" then uart.on(uartID,"receive",function() coroutine.resume(co) end) coroutine.yield() uart.on(uartID,"receive") else cacheData = cacheData..s 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 function writeData(data) uart.write(uartID,data) log.info("gpsHxxt.writeData",data:toHex()) end -- GPS串口写命令操作 -- @number class,消息类 -- @number is,消息编号 -- @string payload,有效载荷 -- @return nil -- @usage gpsHxxt.writeCmd(cmd) function writeCasic(class,id,payload) local tmp = pack.pack("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("gpsHxxt.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、回调函数[可选] -- 例如gpsHxxt.open(gpsHxxt.TIMERORSUC,{tag="TEST",val=120,cb=testGpsCb}) -- gpsHxxt.TIMERORSUC为GPS应用模式,"TEST"为GPS应用标记,120秒为GPS开启最大时长,testGpsCb为回调函数 -- @number mode GPS应用模式,支持gpsHxxt.DEFAULT,gpsHxxt.TIMERORSUC,gpsHxxt.TIMER三种 -- @param para table类型,GPS应用参数 -- para.tag:string类型,GPS应用标记 -- para.val:number类型,GPS应用开启最大时长,mode参数为gpsHxxt.TIMERORSUC或者gpsHxxt.TIMER时,此值才有意义 -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag) -- @return nil -- @usage gpsHxxt.open(gpsHxxt.DEFAULT,{tag="TEST1",cb=test1Cb}) -- @usage gpsHxxt.open(gpsHxxt.TIMERORSUC,{tag="TEST2",val=60,cb=test2Cb}) -- @usage gpsHxxt.open(gpsHxxt.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"),"gpsHxxt.open para invalid") log.info("gpsHxxt.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 _open() --启动1秒的定时器 if existTimerItem() and not sys.timerIsActive(timerFnc) then sys.timerStart(timerFnc,1000) end end --- 关闭一个“GPS应用” -- 只是从逻辑上关闭一个GPS应用,并不一定真正关闭GPS,是有所有的GPS应用都处于关闭状态,才会去真正关闭GPS -- @number mode GPS应用模式,支持gpsHxxt.DEFAULT,gpsHxxt.TIMERORSUC,gpsHxxt.TIMER三种 -- @param para table类型,GPS应用参数 -- para.tag:string类型,GPS应用标记 -- para.val:number类型,GPS应用开启最大时长,mode参数为gpsHxxt.TIMERORSUC或者gpsHxxt.TIMER时,此值才有意义;使用close接口时,不需要传入此参数 -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用close接口时,不需要传入此参数 -- @return nil -- @usage GPS应用模式和GPS应用标记唯一确定一个“GPS应用”,调用本接口关闭时,mode和para.tag要和gpsHxxt.open打开一个“GPS应用”时传入的mode和para.tag保持一致 -- @usage gpsHxxt.close(gpsHxxt.DEFAULT,{tag="TEST1"}) -- @usage gpsHxxt.close(gpsHxxt.TIMERORSUC,{tag="TEST2"}) -- @usage gpsHxxt.close(gpsHxxt.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"),"gpsHxxt.close para invalid") log.info("gpsHxxt.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 gpsHxxt.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应用模式,支持gpsHxxt.DEFAULT,gpsHxxt.TIMERORSUC,gpsHxxt.TIMER三种 -- @param para table类型,GPS应用参数 -- para.tag:string类型,GPS应用标记 -- para.val:number类型,GPS应用开启最大时长,mode参数为gpsHxxt.TIMERORSUC或者gpsHxxt.TIMER时,此值才有意义;使用isActive接口时,不需要传入此参数 -- para.cb:GPS应用结束时的回调函数,回调函数的调用形式为para.cb(para.tag);使用isActive接口时,不需要传入此参数 -- @return bool result,处于激活状态返回true,否则返回nil -- @usage GPS应用模式和GPS应用标记唯一确定一个“GPS应用”,调用本接口查询状态时,mode和para.tag要和gpsHxxt.open打开一个“GPS应用”时传入的mode和para.tag保持一致 -- @usage gpsHxxt.isActive(gpsHxxt.DEFAULT,{tag="TEST1"}) -- @usage gpsHxxt.isActive(gpsHxxt.TIMERORSUC,{tag="TEST2"}) -- @usage gpsHxxt.isActive(gpsHxxt.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"),"gpsHxxt.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应用前不需要调用此接口进行设置 -- 否则在调用gpsHxxt.open前,使用此接口,传入自定义的供电控制函数cbFnc,GPS开启时,gpsHxxt.lua自动执行cbFnc(true),GPS关闭时,gpsHxxt.lua自动执行cbFnc(false) -- @param cbFnc function类型,用户自定义的GPS供电控制函数 -- @return nil -- @usage gpsHxxt.setPowerCbFnc(cbFnc) function setPowerCbFnc(cbFnc) powerCbFnc = cbFnc end --- 设置GPS模块和GSM模块之间数据通信的串口参数 -- 如果使用的是Air800,或者使用的UART2(波特率115200,数据位8,无检验位,停止位1),则打开GPS应用前不需要调用此接口进行设置 -- 否则在调用gpsHxxt.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 gpsHxxt.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模块搜星模式 -- 同时仅支持配置为一种搜星模式 -- @number H01 设置为GPS L1+SBAS+QZSS联合定位模式 -- @number H10 设置为BDS B1定位 -- @number H101 设置为GPS+GLONASS+GALILEO+SBAS+QZSS联合定位 -- @number H11 设置为GPS+BDS+GALILEO+SBAS+QZSS联合定位 -- @return nil -- @usage gpsHxxt.setAerialMode(nil,nil,1) function setAerialMode(H01,H10,H101,H11) local H01 = H01 or 0 local H10 = H10 or 0 local H101 = H101 or 0 local H11 = H11 or 0 if H01~=0 then rt=H01 end if H10~=0 then rt=H10 end if H101~=0 then rt=H101 end if H11~=0 then rt=H11 end if H01+H10+H101+H11 == 0 then H11=1 end if H01+H10+H101+H11>1 then log.warn("gpsHxxt.setAerialMode"," function input err") return end local tmpStr = "$CFGSYS,"..rt if tmpStr~=aerialModeStr then aerialModeStr,aerialModeSetted = tmpStr end end --- 设置NMEA数据处理模式. -- 如果不调用此接口配置,则默认仅gpsHxxt.lua内部处理NMEA数据 -- @number mode NMEA数据处理模式,0表示仅gpsHxxt.lua内部处理,1表示仅用户自己处理,2表示gpsHxxt.lua和用户同时处理 -- @param cbFnc function类型,用户处理一条NMEA数据的回调函数,mode为1和2时,此值才有意义 -- @return nil -- @usage gpsHxxt.setNmeaMode(0) -- @usage gpsHxxt.setNmeaMode(1,cbFnc) -- @usage gpsHxxt.setNmeaMode(2,cbFnc) function setNmeaMode(mode,cbFnc) nmeaMode,nmeaCbFnc = mode,cbFnc end --- 设置GPS模块的运行模式. -- 如果不调用此接口配置,则默认为正常运行模式 -- @number mode 运行模式 -- 0:正常运行模式 -- 1:低功耗模式 -- @return nil -- @usage gpsHxxt.setRunMode(0) -- @usage gpsHxxt.setRunMode(1) function setRunMode(mode) local tmpStr = "$CFGLOWPOWER,"..mode if tmpStr~=runModeStr then runModeStr,runModeSetted = tmpStr end end --设置NEMA输出语句种类 -- @string date NEMA语句名称 -- @number flag 0关闭1打开 -- @usage gpaHxxt.setNemaReportFreq("GSV",1) -- 开机后需等待250ms+后发送才有效 function setNemaReportFreq(date,flag) local rt="" if date=="RMC" then writeCmd("$CFGMSG,0,4,"..flag) elseif date=="GGA" then writeCmd("$CFGMSG,0,0,"..flag) elseif date=="GSA" then writeCmd("$CFGMSG,0,2,"..flag) elseif date=="VTG" then writeCmd("$CFGMSG,0,5,"..flag) elseif date=="GLL" then writeCmd("$CFGMSG,0,1,"..flag) elseif date=="GSV" then writeCmd("$CFGMSG,0,3,"..flag) end end --- 设置GPS定位成功后经纬度的过滤时间. -- @number[opt=0] seconds 单位秒,GPS定位成功后,丢弃前seconds秒的位置信息 -- @return nil -- @usage gpsHxxt.setLocationFilter(2) function setLocationFilter(seconds) filterSeconds = seconds or 0 end function setFastFix(lat,lng,tm) local tLocation = getLocation() local Altitude = getAltitude() lngType=tLocation.lngType latType=tLocation.latType local tm = os.date("*t") local t = tm.year..","..tm.month..","..tm.day..","..tm.hour..","..tm.min..","..tm.sec..",000" local APos = string.format("%s,%f,%s,%f,%s,%f","$AIDPOS",lat,latType,lng,lngType,Altitude) log.info("gpsHxxt.setFastFix",lat,lng,t) writeCmd("$AIDTIME,"..t) writeCmd(APos) end --- 获取GPS模块是否处于开启状态 -- @return bool result,true表示开启状态,false或者nil表示关闭状态 -- @usage gpsHxxt.isOpen() function isOpen() return openFlag end --- 获取GPS模块是否定位成功 -- @return bool result,true表示定位成功,false或者nil表示定位失败 -- @usage gpsHxxt.isFix() function isFix() return fixFlag end function issFix() fixFlag=false end --- 获取GPS模块是否首次定位成功过 -- @return bool result,true表示曾经定位成功 -- @usage gpsHxxt.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("gpsHxxt.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 gpsHxxt.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 gpsHxxt.getAltitude() function getAltitude() return tonumber(smatch(altitude,"(%d+)") or "0") end --- 获取速度 -- @return number kmSpeed,第一个返回值为公里每小时的速度 -- @return number nmSpeed,第二个返回值为海里每小时的速度 -- @usage gpsHxxt.getSpeed() function getSpeed() local integer = tonumber(smatch(speed,"(%d+)") or "0") return (integer*1852 - (integer*1852 %1000))/1000,integer end --- 获取原始速度,字符串带浮点 -- @return number speed 海里每小时的速度 -- @usage gpsHxxt.getOrgSpeed() function getOrgSpeed() return speed end --- 获取方向角 -- @return number course,方向角 -- @usage gpsHxxt.getCourse() function getCourse() return tonumber(smatch(course,"(%d+)") or "0") end -- 获取所有可见卫星的最大信号强度 -- @return number strength,最大信号强度 -- @usage gpsHxxt.getMaxSignalStrength() function getMaxSignalStrength() return maxSignalStrength end --- 获取可见卫星的个数 -- @return number count,可见卫星的个数 -- @usage gpsHxxt.getViewedSateCnt() function getViewedSateCnt() return tonumber(viewedGpsSateCnt)+tonumber(viewedBdSateCnt) end --- 获取定位使用的卫星个数 -- @return number count,定位使用的卫星个数 -- @usage gpsHxxt.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 gpsHxxt.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 gpsHxxt.getUtcTime() function getUtcTime() return UtcTime end --- 获取定位使用的大地高 -- @return number sep,大地高 -- @usage gpsHxxt.getSep() function getSep() return tonumber(Sep or "0") end --- 获取GSA语句中的可见卫星号 -- 只有同时满足如下两个条件,返回值才有效 -- 1、开启了GPS,并且定位成功 -- 2、调用setParseItem接口,第三个参数设置为true -- @return string viewedSateId,可用卫星号,""表示无效 -- @usage gpsHxxt.getSateSn() function getSateSn() return SateSn or "" end --- 获取GSV语句中的可见卫星的信噪比 -- 只有同时满足如下两个条件,返回值才有效 -- 1、开启了GPS,并且定位成功 -- 2、调用setParseItem接口,第二个参数设置为true -- @return string gsv,信噪比 -- @usage gpsHxxt.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 gpsHxxt.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()