Files
BR_YKC/4G/tools/resource/soc_script/v2025.12.31.22/lib/lbsLoc2.lua
2026-03-31 15:46:04 +08:00

230 lines
7.3 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 lbsLoc2
@summary 基站定位v2
@version 1.0
@date 2023.5.23
@author wendal
@demo lbsLoc2
@usage
-- lbsloc 是异步回调接口,
-- lbsloc2 是是同步接口。
-- lbsloc比lbsloc2多了一个请求地址文本的功能。
-- lbsloc 和 lbsloc2 都是免费LBS定位的实现方式
-- airlbs 扩展库是收费 LBS 的实现方式。
-- 注意:
-- 1. 因使用了sys.wait()所有api需要在协程中使用
-- 2. 仅支持单基站定位, 即当前联网的基站
-- 3. 本服务当前处于测试状态
sys.taskInit(function()
sys.waitUntil("IP_READY", 30000)
-- mobile.reqCellInfo(60)
-- sys.wait(1000)
while mobile do -- 没有mobile库就没有基站定位
mobile.reqCellInfo(15)
sys.waitUntil("CELL_INFO_UPDATE", 3000)
local lat, lng, t = lbsLoc2.request(5000)
-- local lat, lng, t = lbsLoc2.request(5000, "bs.openluat.com")
log.info("lbsLoc2", lat, lng, (json.encode(t or {})))
sys.wait(60000)
end
end)
]]
local sys = require "sys"
local lbsLoc2 = {}
local function numToBcdNum(inStr,destLen)
local l,t,num = string.len(inStr or ""),{}
destLen = destLen or (inStr:len()+1)/2
for i=1,l,2 do
num = tonumber(inStr:sub(i,i+1),16)
if i==l then
num = 0xf0+num
else
num = (num%0x10)*0x10 + (num-(num%0x10))/0x10
end
table.insert(t,num)
end
local s = string.char(unpack(t))
l = string.len(s)
if l < destLen then
s = s .. string.rep("\255",destLen-l)
elseif l > destLen then
s = string.sub(s,1,destLen)
end
return s
end
--- BCD编码格式字符串 转化为 号码ASCII字符串(仅支持数字)
-- @string num 待转换字符串
-- @return string data,转换后的字符串
-- @usage
local function bcdNumToNum(num)
local byte,v1,v2
local t = {}
for i=1,num:len() do
byte = num:byte(i)
v1,v2 = bit.band(byte,0x0f),bit.band(bit.rshift(byte,4),0x0f)
if v1 == 0x0f then break end
table.insert(t,v1)
if v2 == 0x0f then break end
table.insert(t,v2)
end
return table.concat(t)
end
lbsLoc2.imei = numToBcdNum(mobile.imei())
local function enCellInfo(s)
-- 改造成单基站, 反正服务器也只认单基站
local v = s[1]
log.info("cell", json.encode(v))
local ret = pack.pack(">HHbbi",v.tac,v.mcc,v.mnc,31,v.cid)
return string.char(1)..ret
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
--[[
执行定位请求
@api lbsLoc2.request(timeout, host, port, reqTime)
@number 请求超时时间,单位毫秒,默认15000
@number 服务器地址,有默认值,可以是域名,一般不需要填
@number 服务器端口,默认12411,一般不需要填
@bool 是否要求返回服务器时间
@return string 若成功,返回定位坐标的纬度,否则会返还nil
@return string 若成功,返回定位坐标的经度,否则会返还nil
@return table 服务器时间,东八区时间. 当reqTime为true且定位成功才会返回
@usage
-- 关于坐标系
-- 部分情况下会返回GCJ02坐标系, 部分情况返回的是WGS84坐标
-- 历史数据已经无法分辨具体坐标系
-- 鉴于两种坐标系之间的误差并不大,小于基站定位本身的误差, 纠偏的意义不大
sys.taskInit(function()
sys.waitUntil("IP_READY", 30000)
-- mobile.reqCellInfo(60)
-- sys.wait(1000)
while mobile do -- 没有mobile库就没有基站定位
mobile.reqCellInfo(15)
sys.waitUntil("CELL_INFO_UPDATE", 3000)
local lat, lng, t = lbsLoc2.request(5000)
-- local lat, lng, t = lbsLoc2.request(5000, "bs.openluat.com")
log.info("lbsLoc2", lat, lng, (json.encode(t or {})))
sys.wait(60000)
end
end)
]]
function lbsLoc2.request(timeout, host, port, reqTime)
if mobile.status() == 0 then
return
end
local hosts = host and {host} or {"free.bs.air32.cn", "bs.openluat.com"}
port = port and tonumber(port) or 12411
local sc = socket.create(nil, function(sc, event)
-- log.info("lbsLoc", "event", event, socket.ON_LINE, socket.TX_OK, socket.EVENT)
if event == socket.ON_LINE then
--log.info("lbsLoc", "已连接")
sys.publish("LBS_CONACK")
elseif event == socket.TX_OK then
--log.info("lbsLoc", "发送完成")
sys.publish("LBS_TX")
elseif event == socket.EVENT then
--log.info("lbsLoc", "有数据来")
sys.publish("LBS_RX")
end
end)
if sc == nil then
return
end
-- socket.debug(sc, true)
socket.config(sc, nil, true)
local rxbuff = zbuff.create(64)
for k, rhost in pairs(hosts) do
local reqStr = string.char(0, (reqTime and 4 or 0) +8) .. lbsLoc2.imei
local tmp = nil
if mobile.scell then
local scell = mobile.scell()
if scell and scell.mcc then
-- log.debug("lbsLoc2", "使用当前驻网基站的信息")
tmp = pack.pack(">bHHbbi", 1, scell.tac, scell.mcc, scell.mnc, 31, scell.eci)
end
end
if tmp == nil then
local cells = mobile.getCellInfo()
if cells == nil or #cells == 0 then
socket.release(sc)
return
end
reqStr = reqStr .. enCellInfo(cells)
else
reqStr = reqStr .. tmp
end
-- log.debug("lbsLoc2", "待发送数据", (reqStr:toHex()))
log.debug("lbsLoc2", rhost, port)
if socket.connect(sc, rhost, port) and sys.waitUntil("LBS_CONACK", 1000) then
if socket.tx(sc, reqStr) and sys.waitUntil("LBS_TX", 1000) then
socket.wait(sc)
if sys.waitUntil("LBS_RX", timeout or 15000) then
local succ, data_len = socket.rx(sc, rxbuff)
-- log.debug("lbsLoc", "rx", succ, data_len)
if succ and data_len > 0 then
socket.close(sc)
break
else
log.debug("lbsLoc", "rx数据失败", rhost)
end
else
log.debug("lbsLoc", "等待数据超时", rhost)
end
else
log.debug("lbsLoc", "tx调用失败或TX_ACK超时", rhost)
end
else
log.debug("lbsLoc", "connect调用失败或CONACK超时", rhost)
end
socket.close(sc)
--sys.wait(100)
end
sys.wait(100)
socket.release(sc)
if rxbuff:used() > 0 then
local resp = rxbuff:toStr(0, rxbuff:used())
log.debug("lbsLoc2", "rx", (resp:toHex()))
if resp:len() >= 11 and(resp:byte(1) == 0 or resp:byte(1) == 0xFF) then
local lat = trans(bcdNumToNum(resp:sub(2, 6)))
local lng = trans(bcdNumToNum(resp:sub(7, 11)))
local t = nil
if resp:len() >= 17 then
t = {
year=resp:byte(12) + 2000,
month=resp:byte(13),
day=resp:byte(14),
hour=resp:byte(15),
min=resp:byte(16),
sec=resp:byte(17),
}
end
return lat, lng, t
end
end
rxbuff:del()
end
return lbsLoc2