182 lines
8.4 KiB
Lua
182 lines
8.4 KiB
Lua
|
|
--- 模块功能:根据基站信息查询经纬度
|
|||
|
|
-- @module lbsLoc
|
|||
|
|
-- @author openLuat
|
|||
|
|
-- @license MIT
|
|||
|
|
-- @copyright openLuat
|
|||
|
|
-- @release 2018.03.25
|
|||
|
|
|
|||
|
|
require"socket"
|
|||
|
|
require"utils"
|
|||
|
|
require"common"
|
|||
|
|
require"misc"
|
|||
|
|
module(..., package.seeall)
|
|||
|
|
|
|||
|
|
local function enCellInfo(s)
|
|||
|
|
local ret,t,mcc,mnc,lac,ci,rssi,k,v,m,n,cntrssi = "",{}
|
|||
|
|
log.info("lbsLoc.enCellInfo",s)
|
|||
|
|
for mcc,mnc,lac,ci,rssi in string.gmatch(s,"(%d+)%.(%d+)%.(%d+)%.(%d+)%.(%d+);") do
|
|||
|
|
mcc,mnc,lac,ci,rssi = tonumber(mcc),tonumber(mnc),tonumber(lac),tonumber(ci),(tonumber(rssi) > 31) and 31 or tonumber(rssi)
|
|||
|
|
local handle = nil
|
|||
|
|
for k,v in pairs(t) do
|
|||
|
|
if v.lac == lac and v.mcc == mcc and v.mnc == mnc then
|
|||
|
|
if #v.rssici < 8 then
|
|||
|
|
table.insert(v.rssici,{rssi=rssi,ci=ci})
|
|||
|
|
end
|
|||
|
|
handle = true
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
if not handle then
|
|||
|
|
table.insert(t,{mcc=mcc,mnc=mnc,lac=lac,rssici={{rssi=rssi,ci=ci}}})
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
for k,v in pairs(t) do
|
|||
|
|
ret = ret .. pack.pack(">HHb",v.lac,v.mcc,v.mnc)
|
|||
|
|
for m,n in pairs(v.rssici) do
|
|||
|
|
cntrssi = bit.bor(bit.lshift(((m == 1) and (#v.rssici-1) or 0),5),n.rssi)
|
|||
|
|
ret = ret .. pack.pack(">bi",cntrssi,n.ci)
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return string.char(#t)..ret
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function enWifiInfo(tWifi)
|
|||
|
|
local ret,cnt,k,v = "",0
|
|||
|
|
if tWifi then
|
|||
|
|
for k,v in pairs(tWifi) do
|
|||
|
|
log.info("lbsLoc.enWifiInfo",k,v)
|
|||
|
|
ret = ret..pack.pack("Ab",(k:gsub(":","")):fromHex(),(v<0) and (v+255) or v)
|
|||
|
|
cnt = cnt+1
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
return string.char(cnt)..ret
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function enMuid()
|
|||
|
|
local muid = misc.getMuid()
|
|||
|
|
return string.char(muid:len())..muid
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function trans(str)
|
|||
|
|
local s = str
|
|||
|
|
if str:len()<10 then
|
|||
|
|
s = str..string.rep("0",10-str:len())
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
return s:sub(1,3).."."..s:sub(4,10)
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local function taskClient(cbFnc,reqAddr,timeout,productKey,host,port,reqTime,reqWifi)
|
|||
|
|
while not socket.isReady() do
|
|||
|
|
if not sys.waitUntil("IP_READY_IND",timeout) then return cbFnc(1) end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
local retryCnt,sck = 0
|
|||
|
|
local reqStr = pack.pack("bAbAAAAA",
|
|||
|
|
productKey:len(),
|
|||
|
|
productKey,
|
|||
|
|
(reqAddr and 2 or 0)+(reqTime and 4 or 0)+8+(reqWifi and 16 or 0)+32,
|
|||
|
|
"",
|
|||
|
|
common.numToBcdNum(misc.getImei()),
|
|||
|
|
enMuid(),
|
|||
|
|
enCellInfo(net.getCellInfoExt()),
|
|||
|
|
enWifiInfo(reqWifi))
|
|||
|
|
log.info("reqStr",reqStr:toHex())
|
|||
|
|
while true do
|
|||
|
|
sck = socket.udp()
|
|||
|
|
if not sck then cbFnc(6) return end
|
|||
|
|
if sck:connect(host,port) then
|
|||
|
|
while true do
|
|||
|
|
if sck:send(reqStr) then
|
|||
|
|
local result,data = sck:recv(timeout)
|
|||
|
|
if result then
|
|||
|
|
sck:close()
|
|||
|
|
log.info("lbsLoc receive",data:toHex())
|
|||
|
|
if data:len()>=11 and (data:byte(1)==0 or data:byte(1)==0xFF) then
|
|||
|
|
local locType = data:byte(1)
|
|||
|
|
cbFnc(0,
|
|||
|
|
trans(common.bcdNumToNum(data:sub(2,6))),
|
|||
|
|
trans(common.bcdNumToNum(data:sub(7,11))),
|
|||
|
|
reqAddr and data:sub(13,12+data:byte(12)) or nil,
|
|||
|
|
data:sub(reqAddr and (13+data:byte(12)) or 12,-1),
|
|||
|
|
locType)
|
|||
|
|
else
|
|||
|
|
log.warn("lbsLoc.query","根据基站查询经纬度失败")
|
|||
|
|
if data:byte(1)==2 then
|
|||
|
|
log.warn("lbsLoc.query","main.lua中的PRODUCT_KEY和此设备在iot.openluat.com中所属项目的ProductKey必须一致,请去检查")
|
|||
|
|
else
|
|||
|
|
log.warn("lbsLoc.query","基站数据库查询不到所有小区的位置信息")
|
|||
|
|
log.warn("lbsLoc.query","在trace中向上搜索encellinfo,然后在电脑浏览器中打开http://bs.openluat.com/,手动查找encellinfo后的所有小区位置")
|
|||
|
|
log.warn("lbsLoc.query","如果手动可以查到位置,则服务器存在BUG,直接向技术人员反映问题")
|
|||
|
|
log.warn("lbsLoc.query","如果手动无法查到位置,则基站数据库还没有收录当前设备的小区位置信息,向技术人员反馈,我们会尽快收录")
|
|||
|
|
end
|
|||
|
|
cbFnc(5)
|
|||
|
|
end
|
|||
|
|
return
|
|||
|
|
else
|
|||
|
|
sck:close()
|
|||
|
|
retryCnt = retryCnt+1
|
|||
|
|
if retryCnt>=3 then return cbFnc(4) end
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
sck:close()
|
|||
|
|
retryCnt = retryCnt+1
|
|||
|
|
if retryCnt>=3 then return cbFnc(3) end
|
|||
|
|
break
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
else
|
|||
|
|
sck:close()
|
|||
|
|
retryCnt = retryCnt+1
|
|||
|
|
if retryCnt>=3 then return cbFnc(2) end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
end
|
|||
|
|
|
|||
|
|
--- 发送基站/WIFI定位请求(仅支持中国区域的位置查询)
|
|||
|
|
-- @function cbFnc 用户回调函数,回调函数的调用形式为:
|
|||
|
|
-- cbFnc(result,lat,lng,addr,time,locType)
|
|||
|
|
-- result:number类型
|
|||
|
|
-- 0表示成功
|
|||
|
|
-- 1表示网络环境尚未就绪
|
|||
|
|
-- 2表示连接服务器失败
|
|||
|
|
-- 3表示发送数据失败
|
|||
|
|
-- 4表示接收服务器应答超时
|
|||
|
|
-- 5表示服务器返回查询失败
|
|||
|
|
-- 6表示socket已满,创建socket失败
|
|||
|
|
-- 为0时,后面的5个参数才有意义
|
|||
|
|
-- lat:string类型或者nil,纬度,整数部分3位,小数部分7位,例如"031.2425864"
|
|||
|
|
-- lng:string类型或者nil,经度,整数部分3位,小数部分7位,例如"121.4736522"
|
|||
|
|
-- addr:目前无意义
|
|||
|
|
-- time:string类型或者nil,服务器返回的时间,6个字节,年月日时分秒,需要转为十六进制读取
|
|||
|
|
-- 第一个字节:年减去2000,例如2017年,则为0x11
|
|||
|
|
-- 第二个字节:月,例如7月则为0x07,12月则为0x0C
|
|||
|
|
-- 第三个字节:日,例如11日则为0x0B
|
|||
|
|
-- 第四个字节:时,例如18时则为0x12
|
|||
|
|
-- 第五个字节:分,例如59分则为0x3B
|
|||
|
|
-- 第六个字节:秒,例如48秒则为0x30
|
|||
|
|
-- locType:numble类型或者nil,定位类型,0表示基站定位成功,255表示WIFI定位成功
|
|||
|
|
-- @bool[opt=nil] reqAddr 是否请求服务器返回具体的位置字符串信息,目前此功能不完善
|
|||
|
|
-- @number[opt=20000] timeout 请求超时时间,单位毫秒,默认20000毫秒
|
|||
|
|
-- @string[opt=nil] productKey IOT网站上的产品证书,如果在main.lua中定义了PRODUCT_KEY变量,则此参数可以传nil
|
|||
|
|
-- @string[opt=nil] host 服务器域名,此参数可选,目前仅lib中agps.lua使用此参数。应用脚本可以直接传nil
|
|||
|
|
-- @string[opt=nil] port 服务器端口,此参数可选,目前仅lib中agps.lua使用此参数。应用脚本可以直接传nil
|
|||
|
|
-- @bool[opt=nil] reqTime 是否需要服务器返回时间信息,true返回,false或者nil不返回,此参数可选,目前仅lib中agps.lua使用此参数。应用脚本可以直接传nil
|
|||
|
|
-- @table[opt=nil] reqWifi 搜索到的WIFI热点信息(MAC地址和信号强度),如果传入了此参数,后台会查询WIFI热点对应的经纬度,此参数格式如下:
|
|||
|
|
-- {
|
|||
|
|
-- ["1a:fe:34:9e:a1:77"] = -63,
|
|||
|
|
-- ["8c:be:be:2d:cd:e9"] = -81,
|
|||
|
|
-- ["20:4e:7f:82:c2:c4"] = -70,
|
|||
|
|
-- }
|
|||
|
|
-- @return nil
|
|||
|
|
-- @usage lbsLoc.request(cbFnc)
|
|||
|
|
-- @usage lbsLoc.request(cbFnc,true)
|
|||
|
|
-- @usage lbsLoc.request(cbFnc,nil,20000)
|
|||
|
|
function request(cbFnc,reqAddr,timeout,productKey,host,port,reqTime,reqWifi)
|
|||
|
|
assert(_G.PRODUCT_KEY or productKey,"undefine PRODUCT_KEY in main.lua")
|
|||
|
|
sys.taskInit(taskClient,cbFnc,reqAddr,timeout or 20000,productKey or _G.PRODUCT_KEY,host or "bs.openluat.com",port or "12411",reqTime,reqWifi)
|
|||
|
|
end
|
|||
|
|
|