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

182 lines
8.4 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.
--- 模块功能:根据基站信息查询经纬度
-- @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)
-- resultnumber类型
-- 0表示成功
-- 1表示网络环境尚未就绪
-- 2表示连接服务器失败
-- 3表示发送数据失败
-- 4表示接收服务器应答超时
-- 5表示服务器返回查询失败
-- 6表示socket已满创建socket失败
-- 为0时后面的5个参数才有意义
-- latstring类型或者nil纬度整数部分3位小数部分7位例如"031.2425864"
-- lngstring类型或者nil经度整数部分3位小数部分7位例如"121.4736522"
-- addr目前无意义
-- timestring类型或者nil服务器返回的时间6个字节年月日时分秒需要转为十六进制读取
-- 第一个字节年减去2000例如2017年则为0x11
-- 第二个字节例如7月则为0x0712月则为0x0C
-- 第三个字节例如11日则为0x0B
-- 第四个字节例如18时则为0x12
-- 第五个字节例如59分则为0x3B
-- 第六个字节例如48秒则为0x30
-- locTypenumble类型或者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