agps9701.lua 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. --- 模块功能:GPS辅助定位以及星历更新服务.
  2. -- 本功能模块只能配合Air512G、Air551G、Air552G使用;
  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 agps9701
  11. -- @author openLuat
  12. -- @license MIT
  13. -- @copyright openLuat
  14. -- @release 2018.03.26
  15. require"http"
  16. require"lbsLoc"
  17. require"net"
  18. local gps = require"gps9701"
  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 cachepack = ""
  27. local gpsresult = nil
  28. local agpsend = nil
  29. local tasklock = true
  30. --重置写入agps星历包
  31. local function agpsreag()
  32. tasklock = false
  33. sys.taskInit(function()
  34. while true do
  35. if agpsend then
  36. log.info("agpsend")
  37. tasklock = true
  38. agpsend = false
  39. break
  40. end
  41. sys.wait(1000)
  42. if gps.checkdatapack then
  43. while true do
  44. if agpsend then
  45. break
  46. end
  47. gpsresult = sys.waitUntil("NOEMAL_RECE",1000)
  48. if (not gpsresult) and (not agpsend) then
  49. gps.writeCmd(cachepack:fromHex(),true)
  50. end
  51. end
  52. end
  53. end
  54. end)
  55. end
  56. local function runTimer()
  57. sys.timerStart(updateEph,EPH_UPDATE_INTERVAL*1000)
  58. end
  59. local function writeEphEnd()
  60. agpsend = true
  61. log.info("agps.writeEphEnd",pack.pack("<i",gps.uartBaudrate):toHex())
  62. local cmd,sum = (("AAF00F00950000"):fromHex())..pack.pack("<i",gps.uartBaudrate),0
  63. for i=3,cmd:len() do
  64. sum = bit.bxor(sum,cmd:byte(i))
  65. end
  66. local validate = "00AA0F"
  67. gps.writeCmd(cmd..string.char(sum)..validate:fromHex(),true)
  68. sys.timerStart(gps.close,2000,gps.TIMER,{tag="lib.agps.lua.eph"})
  69. writeEphIdx,sEphData,writeEphSta = 0
  70. end
  71. local function writeEph()
  72. log.info("agps.writeEph",writeEphSta)
  73. if writeEphSta=="IDLE" then
  74. if tasklock then
  75. agpsreag()
  76. end
  77. gps.writeCmd("$PGKC149,1,"..gps.uartBaudrate.."*")
  78. writeEphSta = "WAIT_BINARY_CMD_ACK"
  79. elseif writeEphSta=="WAIT_BINARY_CMD_ACK" or writeEphSta=="WAIT_WRITE_EPH_CMD_ACK" then
  80. if sEphData and sEphData:len()>0 then
  81. local hexStr = sEphData:sub(1,1024)
  82. if hexStr:len()<1024 then hexStr = hexStr..("0"):rep(1024-hexStr:len()) end
  83. hexStr = "AAF00C026602"..string.format("%02X",writeEphIdx):upper().."00"..hexStr
  84. local checkSum = 0
  85. local binStr = hexStr:fromHex()
  86. for i=3,binStr:len() do
  87. checkSum = bit.bxor(checkSum,binStr:byte(i))
  88. end
  89. string.format("%02X",checkSum):upper()
  90. hexStr = hexStr..(string.format("%02X",checkSum):upper()).."00".."AA0F"
  91. cachepack = hexStr
  92. gps.writeCmd(hexStr:fromHex(),true)
  93. sEphData = sEphData:sub(1025,-1)
  94. writeEphIdx = writeEphIdx+1
  95. writeEphSta = "WAIT_WRITE_EPH_CMD_ACK"
  96. else
  97. gps.writeCmd(("AAF00C006602FFFF6800AA0F"):fromHex(),true)
  98. writeEphSta = "WAIT_WRITE_EPH_END_CMD_ACK"
  99. end
  100. elseif writeEphSta=="WAIT_WRITE_EPH_END_CMD_ACK" then
  101. io.writeFile(EPH_TIME_FILE,tostring(os.time()))
  102. writeEphEnd()
  103. end
  104. end
  105. -- sys.taskInit(function()
  106. -- sys.waitUntil()
  107. -- while true do
  108. -- if agpsend then
  109. -- log.info("agpsend")
  110. -- break
  111. -- end
  112. -- sys.wait(1000)
  113. -- if gps.checkdatapack then
  114. -- while true do
  115. -- if agpsend then
  116. -- break
  117. -- end
  118. -- gpsresult = sys.waitUntil("NOEMAL_RECE",1000)
  119. -- if (not gpsresult) and (not agpsend) then
  120. -- gps.writeCmd(cachepack:fromHex(),true)
  121. -- end
  122. -- end
  123. -- end
  124. -- end
  125. -- end)
  126. local function writeEphBegin()
  127. writeEphSta = "IDLE"
  128. writeEph()
  129. end
  130. local function downloadEphCb(result,prompt,head,body)
  131. log.info("agps.downloadEphCb",result,prompt,body)
  132. runTimer()
  133. if result and prompt=="200" and body then
  134. io.writeFile(EPH_DATA_FILE,body)
  135. if gps.isFix() then
  136. io.writeFile(EPH_TIME_FILE,tostring(os.time()))
  137. else
  138. fneed_xingli=false
  139. sEphData = body:toHex()
  140. gps.open(gps.TIMER,{tag="lib.agps.lua.eph",val=10,cb=writeEphEnd})
  141. sys.timerStart(writeEphBegin,2000)
  142. return
  143. end
  144. end
  145. end
  146. --连接服务器下载星历
  147. function updateEph()
  148. if gps.isFix() then runTimer() return end
  149. http.request("GET","download.openluat.com/9501-xingli/brdcGPD.dat_rda",nil,nil,nil,20000,downloadEphCb)
  150. end
  151. --JWL在星历的时间范围内,如果有星历文件,重启模块就直接把本地的星历文件写入GPS芯片
  152. --在AGPS_LOCATED 的订阅事件中,调用此接口。
  153. function upd_xingli()
  154. if not gps.isFix() then
  155. local lstm = io.readFile(EPH_TIME_FILE)
  156. if not lstm or lstm=="" then return end
  157. log.info("agps.upd_xingli lstm=",lstm)
  158. if os.time()-tonumber(lstm) < EPH_UPDATE_INTERVAL then
  159. local body = io.readFile(EPH_DATA_FILE)
  160. if body and #body >0 then
  161. log.info("agps.upd_xingli length=",#body)
  162. fneed_xingli=false
  163. sEphData = body:toHex()
  164. gps.open(gps.TIMER,{tag="lib.agps.lua.eph",val=10,cb=writeEphEnd})
  165. sys.timerStart(writeEphBegin,2000)
  166. else
  167. log.info("agps.upd_xingli wanto update xingli data")
  168. updateEph()
  169. end
  170. end
  171. end
  172. end
  173. sys.subscribe("AGPS_LOCATED", function()
  174. sys.timerStart(function()
  175. log.info("agps.want to upd_xingli",fneed_xingli)
  176. if fneed_xingli then
  177. upd_xingli()
  178. end
  179. end,7000)
  180. end)
  181. --检查是否需要更新星历
  182. local function checkEph()
  183. local result
  184. if not gps.isFix() then
  185. lastTm = io.readFile(EPH_TIME_FILE)
  186. if not lastTm or lastTm=="" then return true end
  187. log.info("agps.checkEph",os.time(),tonumber(lastTm)," DELTA=",os.time()-tonumber(lastTm))
  188. result = (os.time()-tonumber(lastTm) >= EPH_UPDATE_INTERVAL)
  189. end
  190. if not result then runTimer() end
  191. return result
  192. end
  193. local function setFastFix(lng,lat,tm)
  194. gps.setFastFix(lat,lng,tm)
  195. if checkEph() then
  196. updateEph()
  197. end
  198. end
  199. local getloc = 0
  200. local lbsLocRequesting
  201. --获取到基站对应的经纬度,写到GPS芯片中
  202. local function getLocCb(result,lat,lng,addr,time)
  203. fneed_xingli=true
  204. log.info("agps.getLocCb",result,lat,lng,time and time:len() or 0)
  205. lbsLocRequesting = false
  206. if result==0 then
  207. lastLbsLng,lastLbsLat = lng,lat
  208. sys.publish("AGPS_LOCATED", lng,lat)
  209. if not gps.isFix() then
  210. local tm = {year=0,month=0,day=0,hour=0,min=0,sec=0}
  211. if time:len()==6 then
  212. 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)}
  213. misc.setClock(tm)
  214. tm = common.timeZoneConvert(tm.year,tm.month,tm.day,tm.hour,tm.min,tm.sec,8,0)
  215. end
  216. gps.open(gps.TIMERORSUC,{tag="lib.agps.lua.fastFix",val=4})
  217. sys.timerStart(setFastFix,2000,lng,lat,tm)
  218. getloc = 1
  219. end
  220. end
  221. if result~=0 or gps.isFix() then
  222. if checkEph() then updateEph() end
  223. end
  224. end
  225. --是否获取到基站对应的经纬度
  226. function isgetloc()
  227. return getloc
  228. end
  229. local function ipReady()
  230. if gps.isFix() then
  231. runTimer()
  232. else
  233. if not lbsLocRequesting then
  234. lbsLocRequesting = true
  235. lbsLoc.request(getLocCb,nil,30000,"0","bs.openluat.com","12412",true)
  236. end
  237. end
  238. end
  239. local function gpsState(evt,para)
  240. log.info("agps.GPS_STATE",evt,para)
  241. if evt=="LOCATION_SUCCESS" or (evt=="CLOSE" and para==true) then
  242. runTimer()
  243. elseif evt=="BINARY_CMD_ACK" or evt=="WRITE_EPH_ACK" or evt=="WRITE_EPH_END_ACK" then
  244. writeEph()
  245. elseif evt=="OPEN" then
  246. local lng,lat = gps.getLastLocation()
  247. if lng=="" or lat=="" then
  248. lng,lat = lastLbsLng,lastLbsLat
  249. end
  250. if lng~="" and lat~="" then
  251. gps.open(gps.TIMERORSUC,{tag="lib.agps.lua.fastFix",val=4})
  252. local tm = os.date("*t")
  253. sys.timerStart(gps.setFastFix,2000,lat,lng,common.timeZoneConvert(tm.year,tm.month,tm.day,tm.hour,tm.min,tm.sec,8,0))
  254. end
  255. end
  256. end
  257. function init()
  258. sys.subscribe("GPS_STATE",gpsState)
  259. sys.subscribe("IP_READY_IND",ipReady)
  260. log.info("agps.init")
  261. end
  262. function unInit()
  263. sys.unsubscribe("GPS_STATE",gpsState)
  264. sys.unsubscribe("IP_READY_IND",ipReady)
  265. log.info("agps.unInit")
  266. end
  267. init()