agps.lua 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. --- 模块功能:GPS辅助定位以及星历更新服务.
  2. -- 本功能模块只能配合Air800或者Air530使用;
  3. -- require"agps"后,会自动开启本功能模块的任务;
  4. -- 开机后,仅获取一次基站对应的经纬度位置和当前时间,把经纬度位置和时间写到GPS芯片中,可以加速GPS定位
  5. -- 会定期更新GPS星历,星历更新算法如下:
  6. -- 从最后一次GPS定位成功的时间算起,每隔4小时连接星历服务器下载一次星历数据(大概4K字节),写入GPS芯片。
  7. -- 例如01:00分开机后,更新了一次星历文件,截止到05:00,“一直没有开启过GPS”或者“开启过GPS,但是GPS从来没有定位成功”,在05:00就会下载星历数据然后写入GPS芯片;
  8. -- 05:00更新星历数据后,在06:00打开了GPS,并且GPS定位成功,然后在07:00关闭了GPS,关闭前GPS仍然处于定位成功状态;
  9. -- 截止到11:00,“一直没有开启过GPS”或者“开启过GPS,但是GPS从来没有定位成功”,在11:00就会下载星历数据然后写入GPS芯片;
  10. -- @module agps
  11. -- @author openLuat
  12. -- @license MIT
  13. -- @copyright openLuat
  14. -- @release 2018.03.26
  15. require"http"
  16. require"lbsLoc"
  17. require"net"
  18. require"gps"
  19. module(..., package.seeall)
  20. local EPH_TIME_FILE = "/ephTime.txt"
  21. local EPH_DATA_FILE = "/ephData.bin"
  22. local writeEphIdx,sEphData,writeEphSta = 0
  23. local EPH_UPDATE_INTERVAL = 4*3600
  24. local lastLbsLng,lastLbsLat = "",""
  25. local fneed_xingli=false
  26. local function runTimer()
  27. sys.timerStart(updateEph,EPH_UPDATE_INTERVAL*1000)
  28. end
  29. local function writeEphEnd()
  30. log.info("agps.writeEphEnd")
  31. local cmd,sum = (("AAF00E00950000"):fromHex())..pack.pack("<i",gps.uartBaudrate),0
  32. for i=3,cmd:len() do
  33. sum = bit.bxor(sum,cmd:byte(i))
  34. end
  35. gps.writeCmd(cmd..string.char(sum).."\r\n")
  36. sys.timerStart(gps.close,2000,gps.TIMER,{tag="lib.agps.lua.eph"})
  37. writeEphIdx,sEphData,writeEphSta = 0
  38. end
  39. local function writeEph()
  40. log.info("agps.writeEph",writeEphSta)
  41. if writeEphSta=="IDLE" then
  42. gps.writeCmd("$PGKC149,1,"..gps.uartBaudrate.."*")
  43. writeEphSta = "WAIT_BINARY_CMD_ACK"
  44. elseif writeEphSta=="WAIT_BINARY_CMD_ACK" or writeEphSta=="WAIT_WRITE_EPH_CMD_ACK" then
  45. if sEphData and sEphData:len()>0 then
  46. local hexStr = sEphData:sub(1,1024)
  47. if hexStr:len()<1024 then hexStr = hexStr..("F"):rep(1024-hexStr:len()) end
  48. hexStr = "AAF00B026602"..string.format("%02X",writeEphIdx):upper().."00"..hexStr
  49. local checkSum = 0
  50. local binStr = hexStr:fromHex()
  51. for i=3,binStr:len() do
  52. checkSum = bit.bxor(checkSum,binStr:byte(i))
  53. end
  54. string.format("%02X",checkSum):upper()
  55. hexStr = hexStr..(string.format("%02X",checkSum):upper()).."0D0A"
  56. gps.writeCmd(hexStr:fromHex(),true)
  57. sEphData = sEphData:sub(1025,-1)
  58. writeEphIdx = writeEphIdx+1
  59. writeEphSta = "WAIT_WRITE_EPH_CMD_ACK"
  60. else
  61. gps.writeCmd(("AAF00B006602FFFF6F0D0A"):fromHex(),true)
  62. writeEphSta = "WAIT_WRITE_EPH_END_CMD_ACK"
  63. end
  64. elseif writeEphSta=="WAIT_WRITE_EPH_END_CMD_ACK" then
  65. io.writeFile(EPH_TIME_FILE,tostring(os.time()))
  66. writeEphEnd()
  67. end
  68. end
  69. local function writeEphBegin()
  70. writeEphSta = "IDLE"
  71. writeEph()
  72. end
  73. local function downloadEphCb(result,prompt,head,body)
  74. log.info("agps.downloadEphCb",result,prompt)
  75. runTimer()
  76. if result and prompt=="200" and body then
  77. io.writeFile(EPH_DATA_FILE,body)
  78. if gps.isFix() then
  79. io.writeFile(EPH_TIME_FILE,tostring(os.time()))
  80. else
  81. fneed_xingli=false
  82. sEphData = body:toHex()
  83. gps.open(gps.TIMER,{tag="lib.agps.lua.eph",val=10,cb=writeEphEnd})
  84. sys.timerStart(writeEphBegin,2000)
  85. return
  86. end
  87. end
  88. end
  89. --连接服务器下载星历
  90. function updateEph()
  91. if gps.isFix() then runTimer() return end
  92. http.request("GET","download.openluat.com/9501-xingli/brdcGPD.dat_rda",nil,nil,nil,20000,downloadEphCb)
  93. end
  94. --JWL在星历的时间范围内,如果有星历文件,重启模块就直接把本地的星历文件写入GPS芯片
  95. --在AGPS_LOCATED 的订阅事件中,调用此接口。
  96. function upd_xingli()
  97. if not gps.isFix() then
  98. local lstm = io.readFile(EPH_TIME_FILE)
  99. if not lstm or lstm=="" then return end
  100. log.info("agps.upd_xingli lstm=",lstm)
  101. if os.time()-tonumber(lstm) < EPH_UPDATE_INTERVAL then
  102. local body = io.readFile(EPH_DATA_FILE)
  103. if body and #body >0 then
  104. log.info("agps.upd_xingli length=",#body)
  105. fneed_xingli=false
  106. sEphData = body:toHex()
  107. gps.open(gps.TIMER,{tag="lib.agps.lua.eph",val=10,cb=writeEphEnd})
  108. sys.timerStart(writeEphBegin,2000)
  109. else
  110. log.info("agps.upd_xingli wanto update xingli data")
  111. updateEph()
  112. end
  113. end
  114. end
  115. end
  116. sys.subscribe("AGPS_LOCATED", function()
  117. sys.timerStart(function()
  118. log.info("agps.want to upd_xingli",fneed_xingli)
  119. if fneed_xingli then
  120. upd_xingli()
  121. end
  122. end,5000)
  123. end)
  124. --检查是否需要更新星历
  125. local function checkEph()
  126. local result
  127. if not gps.isFix() then
  128. lastTm = io.readFile(EPH_TIME_FILE)
  129. if not lastTm or lastTm=="" then return true end
  130. log.info("agps.checkEph",os.time(),tonumber(lastTm)," DELTA=",os.time()-tonumber(lastTm))
  131. result = (os.time()-tonumber(lastTm) >= EPH_UPDATE_INTERVAL)
  132. end
  133. if not result then runTimer() end
  134. return result
  135. end
  136. local function setFastFix(lng,lat,tm)
  137. gps.setFastFix(lat,lng,tm)
  138. if checkEph() then updateEph() end
  139. end
  140. local getloc = 0
  141. local lbsLocRequesting
  142. --获取到基站对应的经纬度,写到GPS芯片中
  143. local function getLocCb(result,lat,lng,addr,time)
  144. fneed_xingli=true
  145. log.info("agps.getLocCb",result,lat,lng,time and time:len() or 0)
  146. lbsLocRequesting = false
  147. if result==0 then
  148. lastLbsLng,lastLbsLat = lng,lat
  149. sys.publish("AGPS_LOCATED", lng,lat)
  150. if not gps.isFix() then
  151. local tm = {year=0,month=0,day=0,hour=0,min=0,sec=0}
  152. if time:len()==6 then
  153. tm = {year=time:byte(1)+2000,month=time:byte(2),day=time:byte(3),hour=time:byte(4),min=time:byte(5),sec=time:byte(6)}
  154. misc.setClock(tm)
  155. tm = common.timeZoneConvert(tm.year,tm.month,tm.day,tm.hour,tm.min,tm.sec,8,0)
  156. end
  157. gps.open(gps.TIMERORSUC,{tag="lib.agps.lua.fastFix",val=4})
  158. sys.timerStart(setFastFix,2000,lng,lat,tm)
  159. getloc = 1
  160. end
  161. end
  162. if result~=0 or gps.isFix() then
  163. if checkEph() then updateEph() end
  164. end
  165. end
  166. --是否获取到基站对应的经纬度
  167. function isgetloc()
  168. return getloc
  169. end
  170. local function ipReady()
  171. if gps.isFix() then
  172. runTimer()
  173. else
  174. if not lbsLocRequesting then
  175. lbsLocRequesting = true
  176. lbsLoc.request(getLocCb,nil,30000,"0","bs.openluat.com","12412",true)
  177. end
  178. end
  179. end
  180. local function gpsState(evt,para)
  181. log.info("agps.GPS_STATE",evt,para)
  182. if evt=="LOCATION_SUCCESS" or (evt=="CLOSE" and para==true) then
  183. runTimer()
  184. elseif evt=="BINARY_CMD_ACK" or evt=="WRITE_EPH_ACK" or evt=="WRITE_EPH_END_ACK" then
  185. writeEph()
  186. elseif evt=="OPEN" then
  187. local lng,lat = gps.getLastLocation()
  188. if lng=="" or lat=="" then
  189. lng,lat = lastLbsLng,lastLbsLat
  190. end
  191. if lng~="" and lat~="" then
  192. gps.open(gps.TIMERORSUC,{tag="lib.agps.lua.fastFix",val=4})
  193. local tm = os.date("*t")
  194. sys.timerStart(gps.setFastFix,2000,lat,lng,common.timeZoneConvert(tm.year,tm.month,tm.day,tm.hour,tm.min,tm.sec,8,0))
  195. end
  196. end
  197. end
  198. function init()
  199. sys.subscribe("GPS_STATE",gpsState)
  200. sys.subscribe("IP_READY_IND",ipReady)
  201. log.info("agps.init")
  202. end
  203. function unInit()
  204. sys.unsubscribe("GPS_STATE",gpsState)
  205. sys.unsubscribe("IP_READY_IND",ipReady)
  206. log.info("agps.unInit")
  207. end
  208. init()