微信小程序iBeacon测距及稳定程序的实现解析

前言

iBeacon是苹果公司推出的一项低耗能蓝牙技术,由蓝牙设备发射包含指定信息的信号,再由移动设备接收信号,从而实现近场通信。微信小程序2017年开始支持iBeacon,摇一摇附近就是基于iBeacon实现的,此外iBeacon还可以实现距离测量,本文将介绍如何基于微信小程序实现iBeacon测距。

iBeacon测距原理

蓝牙信标发射的信号强度(rssi)与收发设备之间的距离,某种程度上呈正相关,因此通过合理的运算转化,可以通过rssi的值反推出与接收设备间的距离。

蓝牙信标的rssi值是一个参考值,没有固定标准。想要计算出蓝牙信标的距离,还必须知道这个信标设备的txPower值。txPower是指当距离蓝牙信标1m时的rssi值,不同的蓝牙设备或相同设备不同的工况甚至不同的场地环境,都会影响txPower值,因此这个值虽然可以测量,但一定程度上是个经验值,无法测准。

rssi测距公式

知道rssi和txPower后就可以计算距离了,有两种计算公式:

一、

这个公式里的三个变量A、B、C都是经验值,需要根据手机系统或硬件型号精确调校,通常会将所有设备的校准结果保存成一个设备信息表,移动终端先检测本机型号,然后匹配设备信息调取相应的计算配置,再进行计算。很明显这个公式是比较依赖硬件调校的,没有数据储备的前提下这个公式会很难用。

转换成js代码:

const calculateAccuracy = function (txPower, rssi) {
 return (0.89976) * Math.pow(rssi / txPower, 7.7095) + 0.111
}

未精校情况下的测距表现:

先说这个图怎么看。

  • 纵轴代表测量距离,横轴代表时间,每隔一秒取样一次,图中是近10次取样的数值曲线。
  • 绿线是设备接收到的rssi值,反应硬件真实接收到的数据情况;
  • 红线是套用公式计算得出的瞬时距离;
  • 黄线是微信小程序自带的瞬时测距结果。

蓝牙信标与手机的实际距离1m,测试设备为红米Note7。

从上图可见,rssi值相对稳定,说明硬件没有太大问题。红线和黄线的波动都很大,说明准确度不咋地。二者的波动趋势几乎一致,所以有理由怀疑微信小程序内部也是用的这个测距公式。从结果来看,这个公式的准确度比较差,可能是因为没有精校的原因。

二、

这个公式里的A就是rssi,tx是txPower,n是经验值,n的取值跟物理环境有关。

const calculateAccuracy = function (txPower, rssi) {
 return Math.pow(10, Math.abs(rssi - txPower) / (10 * 4))
}

公式二的测距表现:

人比人得死,货比货得扔啊。

图中黄线还是波动的那么疯狂,但红线却异常稳定,而且呈现出跟绿线一致的波动幅度,说明测距精度靠谱。这个公式只有一个参数,生产环境中的调校相对简单,这里我们选择公式二作为测距公式。

iBeacon测距稳定程序

蓝牙信号本身就有波动性,加上现实环境中的很多因素也会影响到信号强度,比如物体遮挡、设备方向变化、硬件自身的稳定性等,所以接收设备检测到的rssi值通常是“跳动”的,直接使用测距公式算出的结果,往往不可用。必须实现一个稳定程序,让计算结果呈现出连续性和稳定性。

数据滤波

稳定程序主要做的事就是对波段数据“削峰填谷”,也可以称作数据滤波。最简单的滤波处理,就是收集一段时间的值求平均,只要硬件不出问题,固定距离的蓝牙信标rssi值总是会在一个相对稳定的区间内变化,采样时间越长,采样的平均值就会越接近真实值,因此在静态测距场景中,求平均是最佳方式。

//求数组平均值
const arrayAverage = arr => arr.reduce((acc, val) => acc + val, 0) / arr.length;
return arrayAverage([...])

具体实现是,当程序源源不断的接收到信标的rssi时,先用公式计算出瞬时测距结果,然后将结果存进一个数组,然后计算这个数组的平均值。静态测距时,测量结果还是非常准的,2m以内的距离误差可以低至0.1m。

实际应用中往往都是动态测距,所以采样数据的长度要加以限制,比如按后进先出的顺序,取最近10组数据。具体采样队列设为多长,要根据项目实际需求而定。采样队列的长度越长,测距结果越平滑,但对移动端的动态捕捉越迟钝;反之采样队列越短,结果越锐利,对移动端的动态捕捉越灵敏。

有时因为一些偶然因素,采样队列中会出现个别大幅偏离真实值的“燥音”数据,即使求平均也难以有效抹除影响,为消除这种影响,可以在求平均前先用高斯模糊算法对“偏大值”和“偏小值”做平滑处理,最大限度的降低数据噪音的干扰。

高斯模糊算法的关键是根据平均差求权重,一维高斯模糊的权重计算公式:

转换成js代码:

//求一维队列某点的高斯模糊权重 @param(队列长度,目标位置, 平均差)
const getOneGuassionArray = function (size, kerR, sigma) {
 if (size % 2 > 0) {
  size -= 1
 }
 if (!size) {
  return []
 }
 if (kerR > size-1){
  return []
 }
 let sum = 0;
 let arr = new Array(size);

 for (let i = 0; i < size; i++) {
  arr[i] = Math.exp(-((i - kerR) * (i - kerR)) / (2 * sigma * sigma));
  sum += arr[i];
 }

 return arr.map(e => e / sum);
}

关于“偏大值”和“偏小值”的概念将在下文介绍,这里只要知道我们的模糊目标是那些“极端数据”就行了。

时间加权

基于采样队列求平均的处理方式,不可避免的会让结果产生滞后性,这时可以引入时间加权的补偿算法。

所谓时间加权,是指在求平均值的时候,给距离当前时间较近的值更高的计算权重,反之给距离当前时间较远的值较低的计算权重,实现起来也非常简单。

以最简单的权重分配为例,将采样队列一分为二,按时间远近定位为“当前组”和“过去组”,比如说我想让当前组的权重是过去组的2倍,那么只要将当前组数据全部复制一份加入队列,然后再计算新队列的平均值。

//时间加权处理
queue = queue.slice(0, parseInt(queue.length / 2)).concat(queue)
//求平均
return arrayAverage(queue)

动态跟进

经过时间加权处理后,数据的滞后性会得到一定的抑制,但如果遇到比较“陡峭”的距离变化,这种处理仍然会给出一个相对“平滑”的反馈,为了让稳定程序能更好的感知动态变化,并且做出跟进反应,还需要人为的设置一些特殊条件。

首先,如何判断移动设备正在远离或靠近?

这里有一个简单的思路,可以先找出采样队列中的最大值和最小值,然后以一定的阈值找出偏大值和偏小值。比如队列中的最大值是3,最小值是1,阈值设置为0.1m,那么大于2.9m的数据都算偏大值,小于1.1m的数据都算偏小值。偏大值和偏小值的队列长度最长不超过总队列的二分之一。

然后,如果偏大值集中在队列的前三分之一部分,那么我们可以认为移动设备正在果断远离;反之偏小值集中在队列的前三分之一部分,则可以认为移动设备正在靠近。

//maxCount为偏大值的序号数组
//minCount为偏小值的序号数组
//queueLength为队列长度

if (arrayAverage(maxCount) < parseInt(queueLength / 3)) {
  console.log(`正在远离`)
} else if (arrayAverage(minCount) < parseInt(queueLength / 3)) {
  console.log(`正在靠近`)
}

基于这种远离和靠近的趋势判断,我们可以人为的让数据向运动方向做更激进的倾斜。怎么做呢?跳过时间加权逻辑,如果判断为正在远离,那么就将队列中的偏小值过滤掉,反之则将偏大值过滤掉,只计算剩下的数据;这种处理会得到一个明显过激的结果,但考虑到现实世界中的运动往往具有惯性,这种激进处理,可能会更贴合真实的运动情况,而且让数据的响应更“灵敏”。

效果检验

做到目前为止效果怎么样呢,直接看图吧。

下图中,绿线依然是rssi值,红线是根据rssi直接算出来的瞬时测距结果,黄线是加入稳定程序后的测距结果。

第一张图是相对静止的条件,可以看到黄线相对红线明显更加平稳,说明稳定程序还是起作用的。

第二张图是模拟快速远离的场景,可以看到黄线在保证平稳的前提下紧跟红线,没有被甩掉,主要体现的是稳定程序的动态跟进效果。

第三张图是抡胳膊甩手机+遮挡信号模拟出的场景,貌似稳定程序也架不住了,有点飘忽。

以上是关于稳定程序的简要实现思路,生产环境中肯定会面临更加复杂的情况,免不了还要做大量调试,这里只是抛砖引玉。

总结

蓝牙测距简单来说就是一个公式的应用,本身比较简单,基于测距可以实现很多近场应用,比如近场签到、近场推送等等,更进一步甚至可以实现对移动设备的定位,有了定位信息,很多室内定位、室内导航相关的应用就都可以实现了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 微信小程序使用websocket通讯的demo,含前后端代码,亲测可用

    0.概述websocket (1) 个人总结:后台设置了websocket地址,服务器开启后等待有人去连接它. 一个客户端一打开就去连接websocket地址,同时传递某些识别参数.这样一来后台和客户端连接成功了,然后后台就可以发消息给客户端了,(客户端也可以再回话给后台). (2) socket叫套接字,应用程序用socket向网络发出请求或者应答网络请求. (3) 官方解释的socket 建立连接四步骤: 服务器端开启socket,然后accep方法处于监听状态,等待客户端的连接. 客户端开

  • 微信小程序把百度地图坐标转换成腾讯地图坐标过程详解

    百度地图的经纬度放到腾讯地图里面解析地址,导致位置信息显示不正确,所以利用腾讯地图提供的API进行转换. 如果没有开发密钥(key),就到腾讯地图官方文档进行申请和下载qqmap-wx-jssdk.js 腾讯地图官方文档 申请步骤 填写信息 wxml代码 <map id='map' longitude="{{longitude}}" latitude="{{latitude}}" markers="{{markers}}" show-loc

  • 微信小程序实现人脸检测功能

    本文为大家分享了微信小程序实现人脸检测的具体代码,供大家参考,具体内容如下 因为本文章的人脸检测技术运用的是百度云人工智能,首先要有百度云的账号. 近期,人脸识别已经升级到了V3,开启了测试,所以也依照v3文档进行了更新: 1.人脸识别的每个接口,都需要用到百度云的access_token,首先获取 access-token ,一个月之后access_token过期:可以将获取的存入文件,再次引用时可以判断其是否过期,然后引用或者重新获取: //获取access_token function r

  • 微信小程序ibeacon三点定位详解

    空余时间简单写了一个微信小程序ibeacon三点定位. 事先淘宝买了七八个ibeacon小设备,放置在办公司角落.分别设置三个ibeacon的位置坐标点,根据每一个ibeacon到已经开启蓝牙的目标物距离,计算出目标物在当前区域内坐标位置.适用于区域内购物指示.当然,进入该区域事先要打开手机蓝牙. 下面代码: var app = getApp() Page({ data: { motto: 'Hello World', openBLE:'打开蓝牙设备', startBLEDiscovery:'初

  • 微信小程序显示倒计时功能示例【测试可用】

    本文实例讲述了微信小程序显示倒计时功能.分享给大家供大家参考,具体如下: 微信小程序中显示倒计时: index.wxml: <view class='countdown'>剩:<text style='color:#6B4EFD'> {{countDownDay}} </text> 天 <text style='color:#6B4EFD'>{{countDownHour}} </text> <text style='color:#6B4E

  • 微信小程序 地图map详解及简单实例

    微信小程序 地图map 微信小程序map 地图 属性名 类型 默认值 说明 longitude Number   中心经度 latitude Number   中心纬度 scale Number 1 缩放级别 markers Array   标记点 covers Array   覆盖物 标记点 标记点用于在地图上显示标记的位置,不能自定义图标和样式 属性 说明 类型 必填 备注 latitude 纬度 Number 是 浮点数,范围 -90 ~ 90 longitude 经度 Number 是

  • 微信小程序iBeacon测距及稳定程序的实现解析

    前言 iBeacon是苹果公司推出的一项低耗能蓝牙技术,由蓝牙设备发射包含指定信息的信号,再由移动设备接收信号,从而实现近场通信.微信小程序2017年开始支持iBeacon,摇一摇附近就是基于iBeacon实现的,此外iBeacon还可以实现距离测量,本文将介绍如何基于微信小程序实现iBeacon测距. iBeacon测距原理 蓝牙信标发射的信号强度(rssi)与收发设备之间的距离,某种程度上呈正相关,因此通过合理的运算转化,可以通过rssi的值反推出与接收设备间的距离. 蓝牙信标的rssi值是

  • 微信小程序开发中的疑问解答汇总

    前言 最近总结一篇微信小程序解答,作为小程序填坑人深有体会这里的变化,小程序刚发布消息的时候我就说了一个观点,只要小程序提供的组件或API丰富,稳定,兼容性好,才能实现小程序快速开发的理念,先如今还有很多组件的兼容不理想,有一些还在的优化中,因基于小程序这个平台开发限制很大,只能坐等中...如果想用第三方库来实现,小程序明文规定不支持第三方库的做法,这样做最终小程序审核环节百分百的不通过. 1.scroll-view 在 iOS 上存在 bug 在使用这个组件开发页面的时候,因自带滚动效果,Y

  • 微信小程序开发之数据存储 参数传递 数据缓存

    微信小程序开发内测一个月.数据传递的方式很少.经常遇到页面销毁后回传参数的问题,小程序中并没有类似Android的startActivityForResult的方法,也没有类似广播这样的通讯方式,更没有类似eventbus的轮子可用. 现在已知传递参数的方法只找到三种,先总结下.由于正处于内测阶段,文档也不是很稳定,经常修改,目前尚没有人造轮子. 先上GIF: 1.APP.js 我把常用且不会更改的参数放在APP.js的data里面了.在各个page中都可以拿到var app = getApp(

  • 微信小程序 UI布局常用技巧整理总结

    微信小程序ui设计规范汇总: 微信小程序是一种全新的应用形态,微信小程序平台不需要下载安装即可使用应用的平台,微信小程序实现了应用"触手可及"的梦想,用户扫一扫或者搜一下即可打开应用. 也体现了"用完即走"的理念,用户不用关心是否安装太多应用的问题.应用将无处不在,随时可用,但又无需安装卸载. 概要 基于微信小程序轻快的特点,我们拟定了小程序界面设计指南和建议. 设计指南建立在充分尊重用户知情权与操作权的基础之上.旨在微信生态体系内,建立友好.高效.一致的用户体验,

  • 微信小程序基于腾讯云对象存储的图片上传功能

    在使用腾讯云对象存储之前,公司一直使用的是传统的FTP的上传模式,而随着用户量的不断增加,FTP所暴露出来的问题也越来越多,1.传输效率低,上传速度慢.2.时常有上传其他文件来攻击服务器,安全上得不到保障.所以我们在经过慎重考虑觉得使用第三方的云存储服务. 在最开始的时候我们在腾讯云与阿里云中选择,最终我们选择腾讯云,腾讯云在文件上传用时方面的性能比较突出,文件越大表现越好:在下载用时方面表现略优于阿里云:文件删除用时方面总体速度略逊于,但在不同大小文件删除用时上都比较稳定.当然这与我们主要用于

  • 微信小程序使用swiper组件实现类3D轮播图

    Swiper是纯javascript打造的滑动特效插件,面向手机.平板电脑等移动终端. Swiper能实现触屏焦点图.触屏Tab切换.触屏多图切换等常用效果. Swiper开源.免费.稳定.使用简单.功能强大,是架构移动终端网站的重要选择! 在写微信小程序时,有写到实现3D轮播图的效果,可以直接使用微信小程序中自带的组件swiper来实现 效果图如下: 1.swiper的相关属性 indicator-dots 是否显示小圆点,也可以自己重新设置小圆点 circular 是否衔接滑动,就是实现无限

  • 微信小程序 swiper 组件遇到的问题及解决方法

    Swiper是纯javascript打造的滑动特效插件,面向手机.平板电脑等移动终端. Swiper能实现触屏焦点图.触屏Tab切换.触屏多图切换等常用效果. Swiper开源.免费.稳定.使用简单.功能强大,是架构移动终端网站的重要选择! swiper 组件高度被限制为150px了,所以内容无法撑开. 解决办法 给这组件重新设置个高度,然后在把里面的图片设置为自动适应容器大小.图片模式设置为 宽度不变 自动适应高度 <swiper class="test" .....>

  • 详解微信小程序开发(项目从零开始)

    一.序 微信小程序,估计大家都不陌生,现在应用场景特别多.今天就系统的介绍一下小程序开发.注意,这里只从项目代码上做解析,不涉及小程序如何申请.打包.发布的东西.(这些跟着微信官方文档的流程走就好).好了废话不多说,看目录. 注: 小程序是一套特殊的东西,融合了原生和web端.他是一个不完整的浏览器对象,所以很多DOM . BOM 的东西无法使用,但是他又通过微信APP实现了多线程. 二.如何创建小程序 很简单,首先下载微信开发者工具,下载稳定版本的就好. 下载 然后,创建小程序,可以参考下述图

  • 微信小程序与公众号卡券/会员打通的问题

    微信小程序与公众号卡券/会员打通 卡券开发:带你走出小程序的坑 tips:由于笔者也是一位前端菜鸟,所以尽量用简单直白的语言为大家讲解,如有说的不到位的地方,还望多多指教 - 作为小程序的研发人员已经默默在小程序深耕了有8个月了,可以说是陪小程序一起成长起来,经历了小程序内测-小程序API开发趋于稳定 好了,进入正题吧, 批量添加卡券 wx.addCard(OBJECT) 基础库 1.1.0 开始支持,低版本需做兼容处理 查看微信卡包中的卡券 wx.openCard(OBJECT) 基础库 1.

随机推荐