跳转至

03 基站和WiFi定位

作者:王城钧

一、基站/wifi/概述

1.1 基站定位原理

基站定位也就是"LBS 定位",全称是 Location Based Service,它包括两层含义:首先是确定移动设备或用户所在的地理位置;其次是提供与位置相关的各类信息服务。意指与定位相关的各类服务系统,简称"定位服务"。

多基站定位中,模块正常联网后,搜索并上报周围的基站信息, 上报到服务器后, 服务器根据三角定位法, 估算出一个大概的坐标,最后返回计算出来的经纬度给模块。

单基站定位中,模块正常联网后,搜索并上报周围的基站信息,服务器会存储多数已知基站的经纬度,根据模块上报的基站信息,直接下发对应位置的经纬度数据。

多基站一般精度在 10-300 米内,单基站误差有可能会在 1.5KM 内

1.2 wifi 定位原理

WIFI 定位的原理和基站定位原理类似,搜索并上报附近的 wifi 信息, 上报到服务器后, 服务器根据三角定位法, 估算出一个大概的坐标,精度在 50~500 米不等。

1.3 免费和收费服务区别

在过去的时间里,合宙为您提供了免费的单基站(LBS)定位服务,为您创造了重要价值。

但是由于单基站定位技术本身的原因,无法提供相对精准的定位服务。

在产品不支持 GPS 功能的情况下,为了满足部分用户更精准的定位需求,合宙现在已推出了多 LBS/WIFI 定位收费服务,相对于免费的单 LBS 定位服务来说,定位精度更高。

1.3.1 免费服务

  1. 免费服务仅支持单基站定位,无 wifi 定位, 使用旧的后台接口,只使用合宙数据库,当前请求频率限制:2 分钟最多 1 次。

  2. 超过频次的定位请求均会返回定位失败。返回错误码,不包含位置信息。

1.3.2 收费服务

在产品不支持 GPS 功能的情况下,为了满足部分用户更精准的定位需求,合宙现在正式推出了多 LBS/WIFI 定位收费服务,相对于免费的单 LBS 定位服务来说,定位精度更高。

关于收费服务的详细介绍,请参考这里

关于如何开通收费服务定位的介绍,请参考LBS配置文档 - 合宙模组资料中心

注意:只有用 2014 年 11 月 25 号后的 lib 库才能支持。

二、演示功能概述

Air780EGH 支持两种定位,分别是 LBS 定位,WIFI 定位,

本文主要介绍 Air780EGH 使用 LuatOS 来实现定位服务,大致流程如下:

付费版本:

  1. 可以自主开通付费服务,然后去 iot 平台 LBS 服务中查看自己的 id 和 key
  2. 首先打开合宙 iot 云平台,选择 lbs

  • 然后选择我的项目里面选择新建项目,里面对应有项目 id 和项目 key

  1. 烧录 airlbs 示例 demo 点这里,通过 airlbs.request 接口发起请求,上报基站和 wifi,进行混合定位

免费版本:

  1. 烧录好内核固件和 lbsloc2 示例 demo 点这里,通过 lbsLoc2.request 接口发起请求,上报基站信息,进行单基站定位

三、准备硬件环境

参考:硬件环境清单第二章节内容,准备以及组装好硬件环境。

四、软件环境

在开始实践本示例之前,先筹备一下软件环境:

  1. Luatools 工具

  2. 内核固件文件(底层 core 固件文件):

本demo开发测试时使用的固件为LuatOS-SoC_V2018_Air780EGH_1.soc,本demo对固件版本没有什么特殊要求,所以你如果要测试本demo时,可以直接使用最新版本的内核固件;如果发现最新版本的内核固件测试有问题,可以使用我们开发本demo时使用的内核固件版本来对比测试;

  1. luatos 需要的脚本和资源文件

坐标拾取工具 https://docs.openluat.com/file/GPS-Offset.html

免费版本脚本所在位置:免费版本脚本 DEMO

付费版本脚本所在位置:付费版本脚本 DEMO

lib 脚本文件:使用 Luatools 烧录时,勾选 添加默认 lib 选项,使用默认 lib 脚本文件;

准备好软件环境之后,接下来查看如何烧录项目文件到 Air780EGH 核心板,将本篇文章中演示使用的项目文件烧录到 Air780EGH 核心板中。

五、API 接口说明

详细的 API 接口说明点击下面链接查看:

airlbs 定位服务

lbsLoc2 - 基站定位 v2

wlan - wifi 操作

六、代码示例介绍

示例分为免费版本和付费版本,免费版本只有单基站定位,付费版本有多基站定位和 wifi+ 基站混合定位

6.1 免费版本基站定位

6.1.1 代码介绍

(注:免费版本一定要使用第四章的 lib 文件)

lbsloc2_app.lua

-- 加载lbsloc2库
local lbsLoc2 = require("lbsLoc2")

-- lbsloc2循环定位函数
local function lbsloc2_task_func()
    while not socket.adapter(socket.dft()) do
            log.warn("lbsloc2_task_func", "wait IP_READY", socket.dft())
            -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
            -- 或者等待1秒超时退出阻塞等待状态;
            -- 注意:此处的1000毫秒超时不要修改的更长;
            -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
            -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
            -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
            sys.waitUntil("IP_READY", 1000)
    end

    -- 检测到了IP_READY消息
    log.info("lbsloc2_task_func", "recv IP_READY", socket.dft())

    while true do 
        mobile.reqCellInfo(15) --进行基站扫描,超时时间为15s
        sys.waitUntil("CELL_INFO_UPDATE", 3000) --等到扫描成功,超时时间3S
        log.info("扫描出的基站信息", json.encode(mobile.getCellInfo())) -- 打印基站信息
        local lat, lng, t = lbsLoc2.request(5000) --仅需要基站定位给出的经纬度
        -- local lat, lng, t = lbsLoc2.request(5000,nil,nil,true) --需要经纬度和当前时间
        --(时间格式{"year":2024,"min":56,"month":11,"day":12,"sec":44,"hour":14})
        log.info("lbsLoc2", lat, lng, (json.encode(t or {}))) --打印经纬度和时间
        sys.wait(60000) -- 1分钟定位一次
    end
end

sys.taskInit(lbsloc2_task_func)

6.1.2 运行结果展示

6.2 付费版本多基站定位

付费版本 可以使用多基站/基站 +wifi 定位多种方式,当然,受限于模块设计,在使用 wifi 扫描时候,4G 数据传输较慢丢包概率较大,所以尽量在 wifi 扫描完毕后,再进行数传工作 (注:付费版本一定要使用第四章的 lib 文件)

6.2.1 代码介绍

airlbs_app.lua

local airlbs = require "airlbs"

local timeout = 10 -- 扫描基站/wifi 做 基站/wifi定位 的超时时间,最小5S,最大60S

--  此服务为收费服务,需自行联系销售申请或者在 https://iot.openluat.com/finance/order 购买

--  以下为合宙LBS平台开通的项目id和秘钥
--  以下项目密钥和id请根据实际项目进行修改,https://iot.openluat.com/lbs/bs 在此网址中我的项目下
local airlbs_project_id = "此处换成自己的项目id"
local airlbs_project_key = "此处换成自己的项目key"

--多基站定位
local function airlbs_multi_cells_task_func()
    while not socket.adapter(socket.dft()) do
        log.warn("lbsloc2_task_func", "wait IP_READY", socket.dft())
        -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
        -- 或者等待1秒超时退出阻塞等待状态;
        -- 注意:此处的1000毫秒超时不要修改的更长;
        -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
        -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
        -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
        sys.waitUntil("IP_READY", 1000)
    end

    -- 检测到了IP_READY消息
    log.info("airlbs_multi_cells_func", "recv IP_READY", socket.dft())
    socket.sntp() -- 进行NTP授时
    sys.waitUntil("NTP_UPDATE", 1000) 
    while true do
        if airlbs_project_id and airlbs_project_key then
            local result, data = airlbs.request({
                project_id = airlbs_project_id,-- 项目ID
                project_key = airlbs_project_key,-- 项目密钥
                timeout = timeout * 1000, -- 实际的超时时间(单位:ms)
            })
            if result then
                log.info("airlbs多基站定位返回的经纬度数据为", json.encode(data))
            end
        else
            log.warn("请检查project_id和project_key")
        end
        sys.wait(60000) 
        -- 循环60S一次多基站定位,此处设置定位请求间隔为60S非必须,请求频率可根据自己所购买的套餐进行计算,超过频次的定位请求均会返回定位失败。返回错误码,不包含位置信息。
    end
end

--多基站定位
sys.taskInit(airlbs_multi_cells_task_func)

6.2.2 运行结果展示

6.3 付费版本 wifi+ 基站混合定位

付费版本 可以使用多基站/基站 +wifi 定位多种方式,当然,受限于模块设计,在使用 wifi 扫描时候,4G 数据传输较慢丢包概率较大,所以尽量在 wifi 扫描完毕后,再进行数传工作 (注:付费版本一定要使用第四章的 lib 文件)

6.3.1 代码介绍

local airlbs = require "airlbs"

local timeout = 10 -- 扫描基站/wifi 做 基站/wifi定位 的超时时间,最小5S,最大60S

--  此服务为收费服务,需自行联系销售申请或者在 https://iot.openluat.com/finance/order 购买

--  以下为合宙LBS平台开通的项目id和秘钥
--  以下项目密钥和id请根据实际项目进行修改,https://iot.openluat.com/lbs/bs 在此网址中我的项目下
local airlbs_project_id = "此处换成自己的项目id"
local airlbs_project_key = "此处换成自己的项目key"


--多基站+多wifi定位
local function airlbs_multi_cells_wifi_task_func()
    while not socket.adapter(socket.dft()) do
        log.warn("airlbs_multi_cells_wifi_func", "wait IP_READY", socket.dft())
        -- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"
        -- 或者等待1秒超时退出阻塞等待状态;
        -- 注意:此处的1000毫秒超时不要修改的更长;
        -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡
        -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配
        -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())
        sys.waitUntil("IP_READY", 1000)
    end

    -- 检测到了IP_READY消息
    log.info("airlbs_multi_cells_wifi_func", "recv IP_READY", socket.dft())

    socket.sntp() --进行NTP授时
    sys.waitUntil("NTP_UPDATE", 1000)

    -- 如需wifi定位,需要硬件以及固件支持wifi扫描功能
    local wifi_info = nil
    if wlan then
        wlan.init()--初始化wlan
        wlan.scan()--扫描wifi
        sys.waitUntil("WLAN_SCAN_DONE", timeout * 1000)--等待扫描完成
        wifi_info = wlan.scanResult()--获取扫描结果
        log.info("scan", "wifi_info", #wifi_info)--打印扫描结果
    end

    while true do
        local result, data = airlbs.request({
            project_id = airlbs_project_id,-- 项目ID
            project_key = airlbs_project_key,-- 项目密钥
            wifi_info = wifi_info,-- wifi信息
            timeout = timeout * 1000,-- 实际的超时时间(单位:ms)
        })
        if result then
            local data_str = json.encode(data)
            log.info("airlbs多基站+多wifi定位返回的经纬度数据为", data_str)-- 解析经纬度
            local lat = data_str:match("\"lat\":([0-9.-]+)")-- 匹配lat
            log.info("airlbs", "lat", lat)-- 打印lat
            local lng = data_str:match("\"lng\":([0-9.-]+)")-- 匹配lng
            log.info("airlbs", "lng", lng)-- 打印lng
        else        
            log.warn("请检查project_id和project_key")-- 打印提示信息
        end
        sys.wait(60000) 
        -- 循环60S一次基站+wifi定位,此处设置定位请求间隔为60S非必须,请求频率可根据自己所购买的套餐进行计算,超过频次的定位请求均会返回定位失败。返回错误码,不包含位置信息。
    end

end

--多基站+多wifi定位
sys.taskInit(airlbs_multi_cells_wifi_task_func)

6.3.2 运行结果展示

7 常见问题

7.1 基站/wifi 混合定位精度如何?

搜索到的小区/wifi 越多,定位的精度越高;一般来说,城市中心定位精度比郊区和农村定位精度高,城市中心的定位精度在几十米到几百米不等,郊区和农村的定位精度更低,可能会有几千米甚至更大的误差。收费版多基站定位和免费版单基站定位的精度没有具体数值,但是多基站定位和免费版单基站定位的精度高。多基站定位时,最多需要 18 个基站信息参与定位。

通过多基站/多 wifi 定位,将实时搜索到的信号强度排名前几的基站和 wifi 同时上报给后台参与定位,当然,基站定位的误差都比较大,如果需要准确定位,请使用支持 GPS 的模块。

7.2 为什么基站定位失败?

  1. 后台基站数据库查询不到所有小区的位置信息;在 Luatools 脚本日志中向上搜索 cells,然后在电脑浏览器中打开定位查询,手动查找 mcc,mnc,lac,ci 位置;

  1. 如果手动可以查到位置,则服务器存在 BUG,直接向技术支持人员反映问题;如果手动无法查到位置,则基站数据库还没有收录当前设备的小区位置信息,向技术支持人员反馈,我们会尽快收录。
  2. 达到了总的 qps 限制数量。
  3. 检查代码里的 project_id 和 project_key 是否正常,project_id 是个 7 位的字符串

7.3 合宙官方的基站定位能在国外使用吗?

不能,没有国外的基站数据库。

7.4 基站/WIFI 定位定位获取的经纬度是什么格式的?

基站/WIFI 定位获取的经纬度为 WGS-84 格式,各种坐标系说明以及转换方法请网上搜索坐标系在线转换工具即可查询。

7.5 原来用的 lbsLoc.request 免费的,现在还能继续免费用吗?

可以免费使用,但 lbsloc 不维护服务器了,不建议新用户使用。

7.6 获取到了经纬度,如何查看具体获取的位置?

可以参考这个坐标拾取工具 https://docs.openluat.com/file/GPS-Offset.html

7.7 IMEI不在自己名下怎么处理?

参考这篇文章进行归属 https://docs.openluat.com/air780epm/product/attributioniot/