lbsLoc.lua 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. --- 模块功能:根据基站信息查询经纬度
  2. -- @module lbsLoc
  3. -- @author openLuat
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2018.03.25
  7. require"socket"
  8. require"utils"
  9. require"common"
  10. require"misc"
  11. module(..., package.seeall)
  12. local function enCellInfo(s)
  13. local ret,t,mcc,mnc,lac,ci,rssi,k,v,m,n,cntrssi = "",{}
  14. log.info("lbsLoc.enCellInfo",s)
  15. for mcc,mnc,lac,ci,rssi in string.gmatch(s,"(%d+)%.(%d+)%.(%d+)%.(%d+)%.(%d+);") do
  16. mcc,mnc,lac,ci,rssi = tonumber(mcc),tonumber(mnc),tonumber(lac),tonumber(ci),(tonumber(rssi) > 31) and 31 or tonumber(rssi)
  17. local handle = nil
  18. for k,v in pairs(t) do
  19. if v.lac == lac and v.mcc == mcc and v.mnc == mnc then
  20. if #v.rssici < 8 then
  21. table.insert(v.rssici,{rssi=rssi,ci=ci})
  22. end
  23. handle = true
  24. break
  25. end
  26. end
  27. if not handle then
  28. table.insert(t,{mcc=mcc,mnc=mnc,lac=lac,rssici={{rssi=rssi,ci=ci}}})
  29. end
  30. end
  31. for k,v in pairs(t) do
  32. ret = ret .. pack.pack(">HHb",v.lac,v.mcc,v.mnc)
  33. for m,n in pairs(v.rssici) do
  34. cntrssi = bit.bor(bit.lshift(((m == 1) and (#v.rssici-1) or 0),5),n.rssi)
  35. ret = ret .. pack.pack(">bH",cntrssi,n.ci)
  36. end
  37. end
  38. return string.char(#t)..ret
  39. end
  40. local function enWifiInfo(tWifi)
  41. local ret,cnt,k,v = "",0
  42. if tWifi then
  43. for k,v in pairs(tWifi) do
  44. log.info("lbsLoc.enWifiInfo",k,v)
  45. ret = ret..pack.pack("Ab",(k:gsub(":","")):fromHex(),v+255)
  46. cnt = cnt+1
  47. end
  48. end
  49. return (tWifi and string.char(cnt) or "")..ret
  50. end
  51. local function trans(str)
  52. local s = str
  53. if str:len()<10 then
  54. s = str..string.rep("0",10-str:len())
  55. end
  56. return s:sub(1,3).."."..s:sub(4,10)
  57. end
  58. local function taskClient(cbFnc,reqAddr,timeout,productKey,host,port,reqTime,reqWifi)
  59. while not socket.isReady() do
  60. if not sys.waitUntil("IP_READY_IND",timeout) then return cbFnc(1) end
  61. end
  62. local retryCnt,sck = 0
  63. local reqStr = pack.pack("bAbAAAA",
  64. productKey:len(),
  65. productKey,
  66. (reqAddr and 2 or 0)+(reqTime and 4 or 0)+(reqWifi and 16 or 0),
  67. "",
  68. common.numToBcdNum(misc.getImei()),
  69. enCellInfo(net.getCellInfoExt()),
  70. enWifiInfo(reqWifi))
  71. log.info("reqStr",reqStr:toHex())
  72. while true do
  73. sck = socket.udp()
  74. if not sck then cbFnc(6) return end
  75. if sck:connect(host,port) then
  76. while true do
  77. if sck:send(reqStr) then
  78. local result,data = sck:recv(5000)
  79. if result then
  80. sck:close()
  81. log.info("lbcLoc receive",data:toHex())
  82. if data:len()>=11 and (data:byte(1)==0 or data:byte(1)==0xFF) then
  83. cbFnc(0,
  84. trans(common.bcdNumToNum(data:sub(2,6))),
  85. trans(common.bcdNumToNum(data:sub(7,11))),
  86. reqAddr and data:sub(13,12+data:byte(12)) or nil,
  87. data:sub(reqAddr and (13+data:byte(12)) or 12,-1),
  88. (data:byte(1)==0) and "LBS" or "WIFI")
  89. else
  90. log.warn("lbsLoc.query","根据基站查询经纬度失败")
  91. if data:byte(1)==2 then
  92. log.warn("lbsLoc.query","main.lua中的PRODUCT_KEY和此设备在iot.openluat.com中所属项目的ProductKey必须一致,请去检查")
  93. else
  94. log.warn("lbsLoc.query","基站数据库查询不到所有小区的位置信息")
  95. log.warn("lbsLoc.query","在trace中向上搜索encellinfo,然后在电脑浏览器中打开http://bs.openluat.com/,手动查找encellinfo后的所有小区位置")
  96. log.warn("lbsLoc.query","如果手动可以查到位置,则服务器存在BUG,直接向技术人员反映问题")
  97. log.warn("lbsLoc.query","如果手动无法查到位置,则基站数据库还没有收录当前设备的小区位置信息,向技术人员反馈,我们会尽快收录")
  98. end
  99. cbFnc(5)
  100. end
  101. return
  102. else
  103. sck:close()
  104. retryCnt = retryCnt+1
  105. if retryCnt>=3 then return cbFnc(4) end
  106. end
  107. else
  108. sck:close()
  109. retryCnt = retryCnt+1
  110. if retryCnt>=3 then return cbFnc(3) end
  111. break
  112. end
  113. end
  114. else
  115. sck:close()
  116. retryCnt = retryCnt+1
  117. if retryCnt>=3 then return cbFnc(2) end
  118. end
  119. end
  120. end
  121. --- 发送根据基站查询经纬度请求(仅支持中国区域的位置查询)
  122. -- @function cbFnc,用户回调函数,回调函数的调用形式为:
  123. -- cbFnc(result,lat,lng,addr,dateTime,locType)
  124. -- result:number类型
  125. -- 0表示成功
  126. -- 1表示网络环境尚未就绪
  127. -- 2表示连接服务器失败
  128. -- 3表示发送数据失败
  129. -- 4表示接收服务器应答超时
  130. -- 5表示服务器返回查询失败
  131. -- 6表示socket已满,创建socket失败
  132. -- 为0时,后面的5个参数才有意义
  133. -- lat:string类型或者nil,纬度,整数部分3位,小数部分7位,例如"031.2425864"
  134. -- lng:string类型或者nil,经度,整数部分3位,小数部分7位,例如"121.4736522"
  135. -- addr:无意义,保留使用
  136. -- dateTime:无意义,保留使用
  137. -- locType:string类型,位置类型,"LBS"表示基站定位位置,"WIFI"表示WIFI定位位置
  138. -- @bool[opt=nil] reqAddr,此参数无意义,保留
  139. -- @number[opt=20000] timeout,请求超时时间,单位毫秒,默认20000毫秒
  140. -- @string[opt=nil] productKey,IOT网站上的产品证书,此参数可选,用户如果在main.lua中定义了PRODUCT_KEY变量,就不需要传入此参数
  141. -- @string[opt=nil] host,服务器域名,此参数可选,目前仅lib中agps.lua使用此参数。用户脚本中不需要传入此参数
  142. -- @string[opt=nil] port,服务器端口,此参数可选,目前仅lib中agps.lua使用此参数。用户脚本中不需要传入此参数
  143. -- @bool[opt=nil] reqTime,是否需要服务器返回时间信息,true返回,false或者nil不返回,此参数可选,目前仅lib中agps.lua使用此参数。用户脚本中不需要传入此参数
  144. -- @table[opt=nil] reqWifi,搜索到的WIFI热点信息(MAC地址和信号强度),如果传入了此参数,后台会查询WIFI热点对应的经纬度,此参数格式如下:
  145. -- {
  146. -- ["1a:fe:34:9e:a1:77"] = -63,
  147. -- ["8c:be:be:2d:cd:e9"] = -81,
  148. -- ["20:4e:7f:82:c2:c4"] = -70,
  149. -- }
  150. -- @return nil
  151. -- @usage lbsLoc.request(cbFnc)
  152. -- @usage lbsLoc.request(cbFnc,true)
  153. -- @usage lbsLoc.request(cbFnc,nil,20000)
  154. function request(cbFnc,reqAddr,timeout,productKey,host,port,reqTime,reqWifi)
  155. assert(_G.PRODUCT_KEY or productKey,"undefine PRODUCT_KEY in main.lua")
  156. sys.taskInit(taskClient,cbFnc,reqAddr,timeout or 20000,productKey or _G.PRODUCT_KEY,host or "bs.openluat.com",port or "12411",reqTime,reqWifi)
  157. end