Board logo

标题: 从概念入门到开发指导,基于蓝牙的Beacon技术纯干货! [打印本页]

作者: 我是MT    时间: 2015-8-13 15:59     标题: 从概念入门到开发指导,基于蓝牙的Beacon技术纯干货!

什么是Beacon

基于 Bluetooth 技术的Beacon,最简单的理解就是一个小型的信息基站,可以应用在室内导航、移动支付、店内导购、人流分析、物品跟踪等等所有与人在室内流动相关的活动之中。随着时代的发展,现代人对移动设备越来越依赖,也有越来越多的活动在室内进行,而GPS这样的室外导航在室内中有些死角及易受建筑物的干扰,且从精准度和耗电量上不能满足室内定位的需求。因此,基于蓝牙技术的Beacon应运而生,成为理想的室内数据解决方案。Beacon技术做到的是通过Bluetooth Smart向通信覆盖范围内的移动设备捕捉和推送信息。2014年已经有许多机构开展了一些实验性项目,并有预测指出,2015年Beacon将在全球范围内将得到大力部署、并带来更多新型服务。ABI Research预测到2019年市场上的Beacon设备总数将达到六千万台,市场规模之大,可见一斑。

多数情况下,通过Beacon可以进行室内定位并提供相应的服务,如在百货商场及时推送品牌促销信息、在机场为旅客定位登机口和餐饮设施的位置、或在博物馆向游客推送身旁的文物信息等。在这些应用场景中,Beacon的位置是固定的,用户通过智能手机APP可以获取这些位置信息。但最近也有一些移动的Beacon应用出现。例如Lighthouse公司推出的一款可穿戴式的Beacon解决方案,对需要特殊帮助的学生进行位置追踪并保障他们的安全。在中国,每到春运或旅游旺季,总有老人或儿童在拥挤的人流中走散,而未来这种基于移动和可穿戴式Beacon的解决方案可以帮助人们更快速准确地在公共场所找到走失的亲人。

规划Beacon ID,准确判断相对位置

Beacon的首要任务就是允许APP确认两者之间的相对位置,并借助这一位置信息实现更多功能。APP必须拥有相应数据的访问权限,并将蓝牙广告数据包中所传输的Beacon ID与实际位置分布信息相对应。位置信息的表达越简单越好,以便于APP读取和分析。例如,而对于商场的Beacon应用,根据店铺ID规划Beacon ID会更合适,这样APP就能够判断出用户是走进了左边的这家李宁,还是右边的那家耐克。

根据位置信息规划Beacon广告数据包中的Beacon ID,是Beacon实现诸多应用的重要前提。Beacon ID 数据可以通过设备上安装的APP在本地进行设置,也可发送至云端或网络以便远程操作。本地数据存储的好处在于它便于访问,而且没有网络也照样能够运行。而远程数据存储的情况下,用户使用的数据是相同的,但网络访问难免更耗时,因此要加倍注意确保用户体验不受影响。有时最佳的解决方案是采用“混搭”的方式,即将本地数据及时进行远程同步、并存储在APP的本地数据库中。这样,在没有网络的情况下,APP也能够使用最新的数据了。

APP后台自动运行,无需用户干预

对于用户来说,最好无需特意开启APP就能够探测到附近的Beacon。也就是说APP最好能够自动在后台运行,而不需要用户干预。这就需要开发时注意系统资源(如电源电量)的合理使用。当然,前提是要确保您的智能手机开启了蓝牙功能。

相对距离视情况而定

到底多近才算近,这是所有Beacon应用开发者需要考虑的问题。实际上,这需要根据实际情况决定。对一些应用来说,只要有一两个Beacon (多个Beacon即可定义”区域“) 的信号,就可以触发动作了,例如针对走进商场或店铺的顾客、机场里走近值机柜台的旅客等。而对于其他一些应用,可能需要用户十分靠近特定的Beacon时,才会提示用户。比如占地较小、陈列物密集的博物馆或美术馆的导览系统,就需要在参观者十分靠近特定的展品时才会提示相应的展品信息。

通过Beacon可以推算用户的相对距离。因为广告数据包中包含了距离与信号强度的对照数据(比如距离为一米时,信号强度是多少多少),所以我们就可以通过接收器(比如手机)测量到的信号强度推算出相对应的距离。如果你使用了API(Application Programming Interface, 应用程序编程接口),就会发现API其实能够很方便地实现距离测算。但是,必须指出距离是推算的、而非精确计算的结果(虽然测算的准确度已经可以满足当前大部分应用的需求)。

Beacon广告数据形式多种选择

关于Beacon的文章已经有很多了,尤其是关于iBeacon的。iBeacon是苹果的广告数据形式,是苹果公司的专利。iOS设备对iBeacon提供原生支持,但有些情况下还需要满足特定的认证要求。关于iBeacon的更多信息可访问Apple.com。

但是,还有一些其他的Beacon广告形式规格,例如Radius Network的AltBeacon。AltBeacon是开源的,可应用于任何平台而不受限制。它最近还发布了面向安卓系统的开源API。

如何开启运用

零售商与市场营销领域是Beacon的大舞台,可以为通路营销与更佳的消费者体验提供无限的想象空间。可以预见,Beacon的运用将会有光明的前景:通过Beacon将产品和促销信息发送给顾客;博物馆和美术馆等也可以开发专门的应用,向走进展厅的参观者发送展厅主题介绍、或对在展品前驻足的参观者发送详细的展品信息等;机场还可以用Beacon追踪所有旅客的动向。对于有开发Beacon应用想法的读者,可以注册下载最新的开发工具Bluetooth Developer Studio,开启自己的Beacon开发之旅。

手把手教你如何开发AltBeacon安卓APP

前面已经介绍了Beacon的一些基础知识,以及AltBeacon和它的蓝牙广告形式。下面将用一个实际的开发案例,指导读者学习如何用AltBeacon安卓API开发Beacon原型APP。

运用Beacon进行博物馆导览

将Beacon应用于博物馆导览,这样当游客靠近展品时,APP可以提示该展品的相关信息,走过路过就再也不会错过!想象一下,如果故宫有了这款APP, 当游客走到一个不明觉厉的青铜方樽面前,只要拿起手机就能快速了解它的主人、出土信息和花纹的寓意,再也不用担心被人嘲笑没文化了。

这个设计的设想是:首先,博物馆内安装的所有的Beacon基站都在APP能够探测到的范围内,而且APP能够默默地在后台运行并探测附近的Beacon,但只有当游客与Beacon基站的距离靠近至2米范围内时才会跳出弹窗,提示与这一Beacon相关的展品信息;其次,针对同一展品,APP不会不识趣地反复跳出提示窗;最后,还能够查阅APP系统日志底层Beacon相关事件。下面请看实地操作!

如果你也是第一次创建Beacon应用APP,看这里!

绑定服务,设定“区域”

对于首次建立应用程序类别的开发者,以下几点需要注意:首先,用AltBeacon API BeaconManager将APP与后台运行的AltBeacon库中的服务绑定。另外,要着手设定一个或多个“区域”。这里所说的“区域”是指一个或一组Beacon,由AltBeacon Beacon ID 域值来规定。Beacon ID域将20个八位字节的标识域分成1个16字节的主ID、1个2字节的二级ID、1个2字节的三级ID。在我的这个APP中,主Beacon是我所关注的,因此只设定了主ID,因此我将二级和三级ID设为空值。


图1 – 基本初始化步骤

更多干货往下看!

APP程序类别

针对不同的显示界面(包括主要展品信息界面、Beacon事件日志界面)的活动类别、以及其他一些辅助性的Java类别,这个APP包括一个自定义应用程序类和一个Actiivity类别。AltBeacon API自身就是一个库,它负责APP后台运行弹出,并提供一系列接口来支持与Beacon探测相关的回调函数。这些都通过自定义应用程序类“GyboApplication.java”执行。


图2 – AltBeacon API 关键接口

测定距离,更新范围

AltBeacon API支持“监测”与“测距”功能。监测功能会在APP进入某一个或某一组Beacon区域时生成事件。这其实是一个二进制的概念,因为只有两种可能——APP在区域内、APP不在区域内。测距功能可以追踪游客距离某一组Beacon的距离,当两者近到一定程度时,就可以触发功能。

我们还必须对应用程序类别执行的RangeNotifier接口中的单实例对象方法“didRangeBeaconsInRegion(Collection[B] beacons, Region region)”进行编码。AltBeacon库的后台蓝牙扫描进程能够发现附近的Beacon,而“didRangeBeaconsInRegion”每秒钟调用一次,并提供当次扫描到的Beacon列表。APP绝大多数功能都在此基础上实现。
Beacon分类则代表物理意义上的Beacon, 它有着一系列属性,包括:Beacon类型标示、蓝牙MAC地址和名称、接收信号强度指示器RSSI(Received Signal Strength Indicator)、(制造过程中设定的)校准传输的Beacon发射功率、与Beacon相对距离的估算值(以米为单位计量、通过RSSI和Beacon发射功率计算得出)。

定义最近的Beacon,判断信息推送时间

有了Beacon列表以及每个Beacon与游客的距离估算值,要推算出哪个Beacon离游客最近应该是不成问题的。但是在测试过程中也有一些问题。有的Beacon明知道就在范围内,却没有出现在didRangeBeaconsInRegion方法获取的Beacon列表中,到底哪里出了问题?经分析,原因可能是Beacon广播频率与安卓APP扫描的频率和持续时间不匹配,导致有时扫描过程无法接收到实际范围内所有Beacon的广告数据包。这就引出了另一个问题:如何控制安卓APP里的这些参数?

当APP收到范围更新时,就要判断是否需要执行相应的功能。具体来说,就是看哪个Beacon离游客最近、有没有近到需要向游客提示Beacon所对应的展品信息。如果最近的Beacon发生了变化,游客会收到提示信息。例如,游客离开刚刚驻足的展品,下一次范围更新之后,离他最近的Beacon可能就不是之前那一个(组)了。当然,还要判断距离最近的Beacon是近到什么程度,才能向游客发送通知信息。实验中的APP把这一数值设定为2米。当然你也可以允许用户手动设置、自定义这一类配置。

扫描配置又是什么?

BeaconManager类允许开发者对APP进行广告数据包扫描时长、活动间歇时长等参数进行配置。可以在初始代码中添加如下的代码。


图4 – 扫描配置

想要做好适合APP的扫描配置,需要考虑很多方面。扫描过程的电量消耗是很大的,因此扫描频次过高或时长过长就会增加电池电量的消耗。但如果扫描频次跟不上,Beacon探测结果的更新就会延迟,进而影响用户体验。

因此,根据实际应用场景的需要,我们必须在耗电水平和用户体验之间进行权衡取舍。例如,一个用来探测路途中经过的店铺的APP,就需要比博物馆导览APP拥有更快的Beacon广告探测和反应速度。

还需要考虑Beacon的广播频率。如果扫描频率高于Beacon广告,有时就会由于最近一次扫描活动中的广播数据包丢失而导致实际范围内的Beacon没有出现在API回调的报告中。

现实世界中的Beacon探测

不得不承认,现实世界总是不完美的。为了让APP能够更好的为人民服务,程序猿编写代码时也不得不考虑现实中的问题种种。在测试过程中,尽管我们很认真地设置了扫描配置,Beacon扫描偶尔还是会有漏网之鱼。现实中,由于游客和Beacon之间的物理屏障(如人群、其他物品等)、或Beacon配置与之前设想的不同,也会出现一些纰漏。物理屏障的存在会导致游客在展厅内行走时,APP数据回报出现短暂的异常。因此,Beacon应用不应当仅根据最近一次的数据回报就立刻作出回应。认识到这一点让我们收获颇多:与其中规中矩地根据AltBeacon库回调的数据行事,不如对算法进行适度的“模糊”处理,也许能改善Beacon APP的表现。为了改善算法,我们决定采用更复杂一些的方法来追踪范围内的Beacon。

模糊的Beacon追踪

我们的方法简单而有效——保留了最近15秒的报告中提示位于范围内的Beacon的相关数据缓存,以及每个Beacon最近一次被探测到的精确时间。通过计时器任务,把最近15秒内没有被探测到的Beacon视为“过期”、移除缓存。

在可以称得上“重中之重”的didRangeBeaconsInRegion方法中,我们更新了Beacon数据缓存和回调的Beacon对象列表,然后评估全部的缓存数据,以判定目前距离最近的Beacon。于是测试的结果有了改善。这类似于数据平滑处理,相关代码片段如下图。


图5 – GyboApplication.java中的Beacon缓存设置和使用


图6 –BeaconEvent类别


图7 –负责终止BeaconEvent对象的计时器任务

最后的最后,提醒用户!

一旦实际执行了获取范围内Beacon报告的代码、采取了某种方式追踪Beacon、并根据获得的数据判断哪一个Beacon离游客最近,那么就只剩最后一步了:在合适的情况下提示游客Beacon所关联的展品信息。怎样判断是否“合适”呢?主要看最后一次生成的通知是否为同一Beacon相关的,因为没有必要反复提示用户同一个展品的信息。还需要将估算的Beacon距离与既设的(触发行为的)最小距离值进行对比,判断游客是否足够靠近Beacon(也就是展品),然后决定是否发送展品信息。

如果APP是在前台运行,提示游客的方法就很简单:更新主要展览信息页面、显示最近的展品介绍。我们使用内存中有关Beacon及其对应展品的数据结构,每个Beacon都有自己的ID,就可以分别对应各自的展品信息,并在APP本地映射了这些数据的对应关系,但正如第一篇中所讲到的,对于除了原型以外的任何APP,最好从远程服务器上获取相关数据,根据位置或其他信息配置Beacon。


图8 –Beacon Information类别


图9 –ThingOfInterest类别

通知列表下拉菜单中的通知,并将其链接到定义展品信息页面的Activity。


图10 – 安卓系统通知,提示附近发现Beacon

下图是安卓通知的代码。


图11 – 创建通知

量身定做自己的专属Beacon

前面已经介绍了Beacon应用开发的概念和AltBeacon广播形式,并详细讲解了如何利用AltBeacon安卓API开发博物馆导览APP原型。下面将向大家介绍如何测试这一博物馆导览APP。

选择蓝牙开发板,启动你的专属Beacon!

我们暂时还没有现成采用AltBeacon形式的Beacon,但手上有不少蓝牙开发板。蓝牙开发板是具有智能蓝牙功能的微控制器(MCU),其内部一般都内置了蓝牙协议栈。由于开发板一般都具有丰富的外设接口和引线,因此开发板通常用来搭建产品的原型可以将编译生成的固件直接烧入到开发板当中,甚至可以直接做成产品功能展示,或是单纯用于试验或学习。我决定用自己手上既有的几块开发板来创建Beacon应用,然后测试一下安卓博物馆导览APP。

我使用的是Bluegiga DKBluetooth Low Energy开发套件和英特尔Edison开发板。Bluegiga开发板的编程采用BGScript脚本语言。英特尔Edison运行的是则Linux,编程语言有多项选择。我习惯用由JavaScript框架驱动的Node.js,这样能找到适用的智能蓝牙的功能包或是库文件。

Bluegiga变身AltBeacon

Bluegiga的BGScript脚本语言简单易懂,且配有Bluegiga框架所提供的丰富的功能库。用BGScript创建Bluegiga应用涉及用文本编辑器创建脚本文件和其他项目配置文件。通过Bluegiga SDK中的软件更新工具,就可以直接通过USB将编译生成的固件烧入到开发板上。

脚本包括变量和数组声明、事件处理器回调函数。回调是编程模型的重要部分,调用标准Bluegiga功能函数会促发相关的回调函数。同样,框架也可以调用事件处理器,以回应脚本之外的情况。

在任何平台上实现Beacon都涉及与通用访问配置文件(Generic Access Profile, GAP)协作,要求设置广播数据包内容、配置广播参数。

Bluegiga AltBeacon实施的要素如下图:

先从变量声明开始。


图11 – 数组声明

广播的设置可以在Bluegiga标准事件处理器“system_boot”中完成,开发板接通电源或重置之后,系统会调用“system_boot”。我先设置了包含Flags字段数组,Flags字段包括许多位,从每一位都能看出Bluetooth Smart和/或Bluetooth BR/EDR的支持方式。

广播数据包中可能包含的字段称为广播数据类型(ADV data types),蓝牙核心规格附录的A部分(数据类型规格)对其有明确定义。广播数据类型的标准结构,包括一个单一字节长度字段 (它的值不包括长度字段本身占有的字节)、一个单一字节数据类型字段。GAP编号文档中定义了数据类型值。
下面是初始过程的首部分代码:


图12 –在system_boot事件处理器中定义flags广播类型

在本系列文章的第一篇中,我介绍了AltBeacon形式并解释了GAP 制造商特定数据广播字段中编码的数据。我在同一数组内的后20字节中填入了这些数据。


图13 – 定义制造商特定数据字段中的AltBeacon数据

然后为Beacon设备设置名称,这一名称今后可以显示在Central设备(主要是智能手机)返回的扫描结果中。它的值是另一个广播类型,因此我将它设立在它自己的数据里。可以看到,指定的本地名称就是AltBeacon。


图14 – 建立用于扫描响应的本地名称

配置广播参数包括调用Bluegiga的一些功能、数组。


图15 – 配置GAP 广播

这样,我的Bluegiga定制AltBeacon准备就绪。


图16 –蓝兆科技DKBLE上的AltBeacon

另一种选择:英特尔Edison上的AltBeacon

Node.js是模块化设计,有多种用途的模块供选用。对于Node.js来说,模块与库类似。“Bleno”模块能够为担任蓝牙GAP外设的应用提供诸多功能,如GATT配置文件的定义和实施。它是开源的,由Sandeep Mistry创建。SandeepMistry还创建了Noble模块,可以用来创建GAP中央模式设备的相关软件。Bleno和Noble都位于github上。

Bleno的标准分布不支持AltBeacon形式,但却支持iBeacon。因此,我复制了Noble github 仓库并改写了Bleno,这样就可以生成AltBeacon形式的GAP广播了。下面就跟大家介绍一下是怎么改写的。

我在标准的bleno.js源文件上添加了新功能,然后就可以根据node.js应用的一系列既设参数启动广播了。新功能代码就长以下这个样子:


图17 –bleno/lib/bleno.js中的新功能

这一代码基本上就是将必须的AltBeacon数据填充到缓冲区,然后调用添加至Linuxbindings.js源文件中其他功能。Bleno可以与Linux上的BlueZ蓝牙协议栈协作,当在基于Linux的平台上执行功能时,Bleno所引出的用于多种应用的功能最终被映射到针对BlueZ功能的调用。我只好对Bleno中Linux相关的部分作一些修改,这样才能支持AltBeacon。


图18 –bleno/lib/linux/bindings.js中的新功能


图19 –bleno/lib/linux/hci-ble.js中的新功能

这些功能所作的就是准备一个和Bluegiga开发板类似、包含所有必需广播数据的缓冲区,然后将其传递至、并通过Bleno API层,最终到达BlueZ的主机控制接口(Host Controller Interface,HCI)。
AltBeacon Node.js 应用

Bleno经修正之后就可以支持AltBeacon了, 剩下的就是使用新的bleno模块来创建node.js应用,然后使用AltBeacon形式开始广播。整个应用就是下图中的7行代码。


图20 –AltBeacon node.js 应用

为运行AltBeacon APP,我使用Putty通过SSH或是telnet建立了与英特尔Edison的终端会话,然后运行命令行里的node app.js。


图21 – Putty建立终端对话




欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/) Powered by Discuz! 7.0.0