Files
BR_YKC/4G/code/lib/gpsHxxt.lua
2026-03-31 15:46:04 +08:00

928 lines
34 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--- 模块功能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数据
参数
sgNEMA中的一行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("<bbHbbA",0xBA,0xCE,payload:len(),class,id,payload)
local checkSum = bit.lshift(id,24)+bit.lshift(class,16)+payload:len()
for i=1,payload:len(),4 do
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)
end
tmp = tmp..pack.pack("<I",checkSum)
uart.write(uartID,tmp)
--log.info("gpsZkw.writeCasic",tmp)
log.info("gpsHxxt.writeCasic",tmp:toHex())
end
-- GPS串口写命令操作
-- @string cmdGPS指令(cmd格式"$PGKC149,1,115200*"或者"$PGKC149,1,115200*XX\r\n")
-- @bool isFullcmd是否为完整的指令格式包括校验和以及\r\ntrue表示完整false或者nil为不完整
-- @return nil
-- @usage gpsHxxt.writeCmd(cmd)
function writeCmd(cmd,isFull)
local tmp = cmd
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"
tmp = cmd.."\r\n"
end
uart.write(uartID,tmp)
log.info("gpsHxxt.writecmd",tmp)
--log.info("gpsHxxt.writecmd:toHex",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
pm.wake("gpsHxxt.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_VIBR)
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("gpsHxxt._open")
end
local function _close()
if not openFlag then return end
if powerCbFnc then
powerCbFnc(false)
else
pmd.ldoset(0,pmd.LDO_VIBR)
--rtos.sys32k_clk_out(0)
end
uart.close(uartID)
pm.sleep("gpsHxxt.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("gpsHxxt._close")
end
--- GPS应用模式1.
--
-- 打开GPS后GPS定位成功时如果有回调函数会调用回调函数
--
-- 使用此应用模式调用gpsHxxt.open打开的“GPS应用”必须主动调用gpsHxxt.close或者gpsHxxt.closeAll才能关闭此“GPS应用”,主动关闭时,即使有回调函数,也不会调用回调函数
DEFAULT = 1
--- GPS应用模式2.
--
-- 打开GPS后如果在GPS开启最大时长到达时没有定位成功如果有回调函数会调用回调函数然后自动关闭此“GPS应用”
--
-- 打开GPS后如果在GPS开启最大时长内定位成功如果有回调函数会调用回调函数然后自动关闭此“GPS应用”
--
-- 打开GPS后在自动关闭此“GPS应用”前可以调用gpsHxxt.close或者gpsHxxt.closeAll主动关闭此“GPS应用”主动关闭时即使有回调函数也不会调用回调函数
TIMERORSUC = 2
--- GPS应用模式3.
--
-- 打开GPS后在GPS开启最大时长时间到达时无论是否定位成功如果有回调函数会调用回调函数然后自动关闭此“GPS应用”
--
-- 打开GPS后在自动关闭此“GPS应用”前可以调用gpsHxxt.close或者gpsHxxt.closeAll主动关闭此“GPS应用”主动关闭时即使有回调函数也不会调用回调函数
TIMER = 3
--“GPS应用”表
local tList = {}
--[[
函数名delItem
功能 从“GPS应用”表中删除一项“GPS应用”并不是真正的删除只是设置一个无效标志
参数
modeGPS应用模式
para
para.tag“GPS应用”标记
para.valGPS开启最大时长
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应用”表
参数
modeGPS应用模式
para
para.tag“GPS应用”标记
para.valGPS开启最大时长
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("gpsHxxt.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定位成功的消息
参数
evtGPS消息类型
返回值:无
]]
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.DEFAULTgpsHxxt.TIMERORSUCgpsHxxt.TIMER三种
-- @param para table类型GPS应用参数
-- para.tagstring类型GPS应用标记
-- para.valnumber类型GPS应用开启最大时长mode参数为gpsHxxt.TIMERORSUC或者gpsHxxt.TIMER时此值才有意义
-- para.cbGPS应用结束时的回调函数回调函数的调用形式为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.DEFAULTgpsHxxt.TIMERORSUCgpsHxxt.TIMER三种
-- @param para table类型GPS应用参数
-- para.tagstring类型GPS应用标记
-- para.valnumber类型GPS应用开启最大时长mode参数为gpsHxxt.TIMERORSUC或者gpsHxxt.TIMER时此值才有意义使用close接口时不需要传入此参数
-- para.cbGPS应用结束时的回调函数回调函数的调用形式为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.DEFAULTgpsHxxt.TIMERORSUCgpsHxxt.TIMER三种
-- @param para table类型GPS应用参数
-- para.tagstring类型GPS应用标记
-- para.valnumber类型GPS应用开启最大时长mode参数为gpsHxxt.TIMERORSUC或者gpsHxxt.TIMER时此值才有意义使用isActive接口时不需要传入此参数
-- para.cbGPS应用结束时的回调函数回调函数的调用形式为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前使用此接口传入自定义的供电控制函数cbFncGPS开启时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和21表示UART12表示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 resulttrue表示开启状态false或者nil表示关闭状态
-- @usage gpsHxxt.isOpen()
function isOpen()
return openFlag
end
--- 获取GPS模块是否定位成功
-- @return bool resulttrue表示定位成功false或者nil表示定位失败
-- @usage gpsHxxt.isFix()
function isFix()
return fixFlag
end
function issFix()
fixFlag=false
end
--- 获取GPS模块是否首次定位成功过
-- @return bool resulttrue表示曾经定位成功
-- @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"}
-- lngTypestring类型表示经度类型取值"E""W"
-- lngstring类型表示度格式的经度值无效时为""
-- latTypestring类型表示纬度类型取值"N""S"
-- latstring类型表示度格式的纬度值无效时为""
-- @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 utcTimeUTC时间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语句中的卫星IDtrue表示解析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()