基站/WIFI定位 ============= wifi与基站定位 -------------- 作者:闫国梁 最后更新时间:2020年6月30日 基站定位: ---------- 原理: ~~~~~~ 手机在插入sim卡开机以后,需要搜索周围的基站信息(就是找信号),通常在有信号的地方,手机能搜索到的基站不止一个,就像你的笔记本在小区里能搜到不止一个开着的路由器一样。然后手机会自动从这些基站中选择信号最好的(假如是基站A)连接注册。其余的基站就不用了吗?不不,手机仍然搜索着它们,一旦你离开基站A一段距离,基站A的信号不如基站B了,手机会自动切换成基站B。这也就是为什么同样是待机一天,你在火车上比在家里耗电要多的原因,手机需要不停的搜索、连接基站。 当手机的网络覆盖到一定程度的时候,基站定位也就应运而生了。 其原理如下: 众所周知,距离基站越远,信号越差,所以用信号的强度可以大致估计距离基站的远近。好了,由于基站都是中国移动中国联通等运营商建立的,所以他们可以确定每个基站准确的位置,当手机同时搜索到至少三个基站的信号时(现在的网络覆盖这是很轻松的一件事情),手机除了连接信号最好的一个外,同时根据基站信号的强弱,大致估计出距离基站的远近。由于基站位置是确定的,所以确定位置是很容易的,只需要以基站为圆心,距离为半径多次画圆即可,需要三个基站的信号可以准确的定位。 相对于三个基站的信号来说,如果只搜索到一个基站或者两个基站,也可以定位,只不过,相对来说不准确 WIFI定位的原理和基站定位原理类似 ## AT模式 ### 查询基站定位指令说明 语法规则: +-----+------------------+---------------------------------------------+ | 命 | 语法 | 返回 | | 令 | | | | 类 | | | | 型 | | | +=====+==================+=============================================+ | 设 | AT+CIPGSMLOC=, | **If =1:** +CIPGSMLOC:[,,,, ] OK **If =2:** | | 置 | | +CIPGSMLOC: [,,] OK **If error is related | | 命 | | to ME functionality:** +CME ERROR: | | 令 | | | +-----+------------------+---------------------------------------------+ | 测 | AT+CIPGSMLOC=? | +CIPGSMLOC:(list of supported s),(range of | | 试 | | ) OK | | 命 | | | | 令 | | | +-----+------------------+---------------------------------------------+ 参数定义: +------+-------------------------+-------+-------------------------+ | 参数 | 定义 | 取值 | 对取值的说明 | +======+=========================+=======+=========================+ | | operation type | 1 | View the longitude, | | | | | latitude and time | +------+-------------------------+-------+-------------------------+ | | | 2 | View the time only | +------+-------------------------+-------+-------------------------+ | | as defined in +SAPBR | 1-3 |   | +------+-------------------------+-------+-------------------------+ | | Current |   |  经度 | | | longitude in degrees | | | +------+-------------------------+-------+-------------------------+ | | Current latiitude in |   | 纬度 | | | degrees | | | +------+-------------------------+-------+-------------------------+ | | the format is yy/mm/dd |   | for example 18/11/08 | +------+-------------------------+-------+-------------------------+ | | the format is hh/mm/ss |   | for example 15:47:26 | +------+-------------------------+-------+-------------------------+ | |   | 0 | Success | +------+-------------------------+-------+-------------------------+ | | | 1 | 未找到数据 | +------+-------------------------+-------+-------------------------+ | | | 6 | 参数错误 | +------+-------------------------+-------+-------------------------+ | | | 7 | 未知错误 | +------+-------------------------+-------+-------------------------+ | | | 404 | Not Found | +------+-------------------------+-------+-------------------------+ | | | 408 | Request Time-out | +------+-------------------------+-------+-------------------------+ | | | 601 | Network Error | +------+-------------------------+-------+-------------------------+ | | | 602 | No memory | +------+-------------------------+-------+-------------------------+ | | | 603 | DNS Error | +------+-------------------------+-------+-------------------------+ | | | 604 | Stack busy | +------+-------------------------+-------+-------------------------+ | | | 65535 | Other Error | +------+-------------------------+-------+-------------------------+ 基站定位测试流程实例 ~~~~~~~~~~~~~~~~~~~~ 以下部分加粗内容是模块发给mcu,非加粗是mcu发给模块 AT 训练波特率 **AT** **OK** AT+SAPBR=1,1 激活PDP **AT+SAPBR=1,1** **OK** AT+SAPBR=2,1 查询是否激活成功,成功能查询到IP **AT+SAPBR=2,1** **+SAPBR: 1,1,“10.150.186.203”** **OK** AT+CIPGSMLOC=1,1 查询基站定位 **AT+CIPGSMLOC=1,1** **+CIPGSMLOC: 0,31.174749,121.600788,2020/06/30,13:07:46** **OK** ### 查询WIFI定位指令说明 语法规则: +-----+-----------------+----------------------------------------------+ | 命 | 语法 | 返回 | | 令 | | | | 类 | | | | 型 | | | +=====+=================+==============================================+ | 设 | AT+WIFILOC=, | **If =1:** +WIFILOC:[,,,,] OK **If =2:** | | 置 | | +WIFILOC: [,,] OK **If error is related to | | 命 | | ME functionality:** +CME ERROR: | | 令 | | | +-----+-----------------+----------------------------------------------+ | 测 | AT+WIFILOC=? | +WIFILOC:(list of supported s),(range of ) | | 试 | | OK | | 命 | | | | 令 | | | +-----+-----------------+----------------------------------------------+ 参数定义: ==== ============================ ===== ============================ 参数 定义 取值 对取值的说明 ==== ============================ ===== ============================ \ operation type 1 longitude, latitude and time \ 2 View the time only \ as defined in +SAPBR 1-3   \ Current longitude in degrees   经度 \ Current latitude in degrees   纬度 \ the format is yy/mm/dd   for example 18/11/08 \ the format is hh:mm:ss   for example 15:47:26 \   0 Success \ 1 未找到数据 \ 6 参数错误 \ 7 未知错误 \ 404 Not Found \ 408 Request Time-out \ 601 Network Error \ 602 No memory \ 603 DNS Error \ 604 Stack busy \ 65535 Other Error ==== ============================ ===== ============================ WIFI定位测试流程实例 ~~~~~~~~~~~~~~~~~~~~ 以下部分加粗内容是模块发给mcu,非加粗是mcu发给模块 AT 训练波特率 **AT** **OK** AT+SAPBR=1,1 激活PDP **AT+SAPBR=1,1** **OK** AT+SAPBR=2,1 查询是否激活成功,成功能查询到IP **AT+SAPBR=2,1** **+SAPBR: 1,1,“10.150.186.203”** **OK** AT+WIFILOC=1,1 查询wifi定位 **AT+WIFILOC=1,1** **+WIFILOC: 0,31.174864,121.600850,2020/06/30,13:01:28** **OK** ## LUAT模式 ### 基站定位接口 **lbsLoc.request(cbFnc, reqAddr, timeout, productKey, host, port, reqTime, reqWifi)** 发送根据基站查询经纬度请求(仅支持中国区域的位置查询) - 参数 +---------+------------------------------------------------------------+ | 传入 | 释义 | | 值类型 | | +=========+============================================================+ | f | cbFnc,用户回调函数,回调函数的调用形式为: | | unction | cbFnc(result,lat,lng,addr) result:number类型 0表示成功 | | | 1表示网络环境尚未就绪 2表示连接服务器失败 | | | 3表示发送数据失败 4表示接收服务器应答超时 | | | 5表示服务器返回查询失败 6表示socket已满,创建socket失败 | | | 为0时,后面的3个参数才有意义 | | | lat:string类型 | | | 或者nil,纬度,整数部分3位,小数部分7位,例如“031.2425864” | | | lng:string类型 | | | 或者nil,经度,整数部分3位,小数部分7位,例如“121.4736522” | +---------+------------------------------------------------------------+ | bool | ** | | | 可选参数,默认为\ ``nil``**\ ,reqAddr,此参数无意义,保留 | +---------+------------------------------------------------------------+ | number | **可选参数,默认为\ ``2 | | | 0000``**\ ,timeout,请求超时时间,单位毫秒,默认20000毫秒 | +---------+------------------------------------------------------------+ | string | **可选参数,默认为\ ``ni | | | l``**\ ,productKey,IOT网站上的产品证书,此参数可选,用户 | | | 如果在main.lua中定义了PRODUCT_KEY变量,就不需要传入此参数 | +---------+------------------------------------------------------------+ | string | **可选 | | | 参数,默认为\ ``nil``**\ ,host,服务器域名,此参数可选, | | | 目前仅lib中agps.lua使用此参数。用户脚本中不需要传入此参数 | +---------+------------------------------------------------------------+ | string | **可选 | | | 参数,默认为\ ``nil``**\ ,port,服务器端口,此参数可选, | | | 目前仅lib中agps.lua使用此参数。用户脚本中不需要传入此参数 | +---------+------------------------------------------------------------+ | bool | **可选参数,默认为\ ``nil``**\ ,reqTime,是否需要服务 | | | 器返回时间信息,true返回,false或者nil不返回,此参数可选, | | | 目前仅lib中agps.lua使用此参数。用户脚本中不需要传入此参数 | +---------+------------------------------------------------------------+ | table | **可选参数,默认为\ ``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,} | +---------+------------------------------------------------------------+ - 返回值 nil ### 基站定位测试脚本说明 以resource\8910_script:raw-latex:`\script`\_LuaTask_V2.3.2:raw-latex:`\demo`:raw-latex:`\lbsLoc`:raw-latex:`\testLbsLoc`.lua为例 首先:通过lbsLoc.request(getLocCb)发起请求getLocCb是回调函数,回调函数里处理请求结果。 .. code:: lua --[[ 功能 :获取基站对应的经纬度后的回调函数 参数 : result:number类型,0表示成功,1表示网络环境尚未就绪,2表示连接服务器失败,3表示发送数据失败,4表示接收服务器应答超时,5表示服务器返回查询失败;为0时,后面的3个参数才有意义 lat:string类型,纬度,整数部分3位,小数部分7位,例如031.2425864 lng:string类型,经度,整数部分3位,小数部分7位,例如121.4736522 返回值:无 ]] function getLocCb(result, lat, lng) log.info("testLbsLoc.getLocCb", result, lat, lng) --获取经纬度成功 if result == 0 then --失败 else end sys.timerStart(reqLbsLoc, 20000) end WIFI定位接口 ~~~~~~~~~~~~ .. _原理-1: 原理: ~~~~~~ wifi定位,顾名思义,周围必须有wifi才可以!这个技术貌似最初是谷歌提出来的,目的是解决室内精确定位,原理类似基站定位。 谷歌的工程师们是这样想的:一个wifi热点的覆盖范围仅有几十米,全世界绝大多数的wifi热点都是固定位置的,他们又拥有独一无二的MAC地址(一种编码,作用类似热点的身份证号码),如果应用基站定位的原理,那么就可以获得相当精确的位置信息了。可是,世界上那么多wifi热点,你总不能跑到各个国家,敲开市民的门去测量吧?谷歌想到了他的神器——谷歌地图。 假如你的家里有个自己设立的无线路由器,经常开机,你的邻居正在阳台上用手机玩谷歌地图,恰好他手机的wifi是开着的,不过没有连接你家的热点。当你的邻居用GPS准确在地图上定位后,谷歌服务器会记录周边的wifi热点信息。正好,你的路由器开着,然后被记录到数据库了:某国家某省某市某小区某楼东侧(其实是用经纬度)有一个MAC地址为12-2e-3f-4a-09-3d的wifi热点。几天后你打算晚上吃川菜,于是连上你的路由器打开谷歌地图打算搜索,这时你惊奇的发现没开GPS,但是你的位置却精确的定位在某国家某省某市某小区某楼东侧。这是为什么呢?这就是wifi依赖定位:你打开谷歌地图后,会上传周围的wifi热点信息,然后2-2e-3f-4a-09-3d上传到服务器上,服务器根据这个地址反馈你邻居用GPS定位出来的经纬度给你,从而实现精确匹配位置。当世界上N多N多人重复上述定位的时候,谷歌就可以建立起来一个丰富而且强大的wifi热点位置数据库。 说明:wifi定位是基站定位的拓展,最终的实现还是基站定位。通过wifi的接口获取附近wifi信息,然后调用基站定位接口进行查询。 **request(cbFnc,timeout)** - 参数 - 返回值 nil ### WIFI定位测试脚本说明 以resource\8910_script:raw-latex:`\script`\_LuaTask_V2.3.2:raw-latex:`\demo`:raw-latex:`\wifi`:raw-latex:`\testWifi`.lua为例,首先通过wifiScan.request获取wifi信息,在回调函数里使用内部消息WIFI_SCAN_IND传递回调数据结果,等收到回调结果以后,通过lbsLoc.request把附近wifi信息的表传入然后请求。在回调里处理请求结果。 .. code:: lua sys.taskInit(function() while true do sys.wait(5000) wifiScan.request(function(result,cnt,tInfo) log.info("testWifi.scanCb",result,cnt) sys.publish("WIFI_SCAN_IND",result,cnt,tInfo) end) local _,result,cnt,tInfo = sys.waitUntil("WIFI_SCAN_IND") if result then for k,v in pairs(tInfo) do log.info("testWifi.scanCb",k,v) end lbsLoc.request(function(result,lat,lng) log.info("testLbsLoc.getLocCb",result,lat,lng) sys.publish("LBS_WIFI_LOC_IND",result,lat,lng) end,false,false,false,false,false,false,tInfo) local _,result,lat,lng = sys.waitUntil("LBS_WIFI_LOC_IND") end end end) 其他补充:用户也可以通过其他平台接口进行定位,可以通过\ **wifiScan.request**\ 、\ **net.getCellInfo、net.getCellInfoExt**\ 等接口获取附近基站和wifi信息以后通过其他平台进行定位。