iBeacon技术初探

苹果在WWDC 2013上正式推出了iBeacon,并在iOS7设备上配备了该功能。苹果期望将其做为一种技术标准,这个标准允许移动App(包括iOS或Android设备)监听来自于iBeacon设备上的信号并做出响应。这种iBeacon设备配备有低功耗蓝牙(Bluetooth Low Energy, BLE)通信功能,并使用BLE向周围发送自己特有的ID,移动设备上的App在接收到该ID后可以做出相应的反应。比如,我们在店铺里设置iBeacon发射器,便可让应用接收到信息并将这一信息通知给服务器,服务器向我们的App返回与该店铺相关的产品或折扣信息。本质上讲,iBeacon技术允许移动应用了解它们在某个局部范围内的位置,并向用户分发基于位置的超文本上下文内容。本文将对iBeacon技术做个简要的介绍。

低功耗蓝牙技术(Bluetooth Low Energy)

iBeacon的底层通信技术是采用低功耗蓝牙技术,这种技术是在短距离范围内数据传输的无线区域网络技术。顾名思义,它即要求低功耗,又需要保证传统蓝牙技术的通信范围。

BLE与传统蓝牙有几点不同:

  1. 耗电量:BLE是低耗电量的,iBeacon设备使用一个纽扣电池即可持续运作长达3年时间。
  2. 低成本:BLE的成本只相当于传统蓝牙设备的60%-80%
  3. 应用:BLE适用于只要求少量定期传输数据的简单应用。传统的蓝牙适用于需要持续通信和大量数据传输的复杂应用。

BLE通信数据包主要由称为”Advertisements”的数据或小的数据包组成,并通过无线电波由Beacons或其它BLE设备以有规律的时间间隔来广播。BLE广告是一种单向通信(one-way communication)方法。希望被发现的Beacon设备可以以设定的时间间隔广播或”广告”自包含的数据包。这些数据包由智能手机等设备收集,并在设备上触发一些事件,如推送消息、提示等。

苹果iBeacon标准要求广播时间的间隔是100ms。频率超高越耗电,但可以让智能手机或其它监听设备越快地发现iBeacon。标准的BLE广播距离是100m,这使Beacon在室内位置跟踪场景下的效果更理想。

监听Beacon区域

Beacon区域监听使用iOS设备的内置无线电来检测用户何时在广告iBeacon信息的BLE设备附近。由于是地理位置的监听,当用户进入或在一个Beacon区域时,我们可以使用这些功能来生成提示或提供其它相关的信息。一个Beacon区域通过以下值的组合来进行标识:

  1. proximity UUID(全局唯一标识):一个128位值,唯一标识一类或一个组织中的一个或多个Beacon。
  2. major值,一个16位无符号整数,用于分组有相同proximity UUID值的相关的Beacon。
  3. minor值,一个16位无符号整数,用于区分具有相同proximity UUID值和major的值。

因为一个Beacon区域可以包含多个iBeacon设备,Beacon区域监听支持同时监听多个感兴趣的设备。例如,一个App为了在特定商场提高用户体验,可用使用相同的proximity UUID来监听商场的所有商铺。当用户进入一个商店时,App检测商铺的iBeacon设备并使用major和minor值来获取额外的信息,如用户进入哪家商店或用户在商店的哪个区域(注意:虽然每个iBeacon都必须有一个proximity UUID,但major和minor的值是可选的)。

定义一个Beacon区域

我们使用CLBeaconRegion类的初始化方法来定义一个beacon区域,并在系统中注册,以开启一个监听。当创建一个CLBeaconRegion对象时,我们指定需要监听的Beacon区域的proximityUUID, major和minor属性。我们必须提供一个唯一标识区域的字符串以便我们在代码中能引用它。注意一个区域的标识与Beacon标识信息无关。

为了注册一个beacon区域,调用CLLocationManager对象的startMonitoringForRegion方法。代码清单1是创建并注册的beacon区域的简单方法。

代码清单1:创建和注册一个beacon区域

1
2
3
4
5
6
- (void)registerBeaconRegionWithUUID:(NSUUID *)proximityUUID andIdentifier:(NSString *)identifier
{
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:proximityUUID identifier:identifier];
[manager startMonitoringForRegion:beaconRegion];
}

App在注册并监听某个Beacon区域后,会立即开始监听此区域。当App监听到注册的Beacon区域时,系统会为App生成一个合适的区域事件。

处理边界穿越事件

当用户进入一个注册的Beacon区域时,CLLocationManager对象将调用其代理对象的locationManager:didEnterRegion:方法。类似的,当用户离开这个区域时,将调用代理对象的locationManager:didExitRegion:方法。注意,用户必须穿过区域边界来触发这些调用,如果用户已经在区域中,CLLocationManager对象将不会调用locationManager:didEnterRegion:。我们可以实现这些代理方法来提示用户或展示一个指定位置的UI。

我们可以设置Beacon区域的notifyOnEntry和notifyOnExit属性来指定哪个边界穿越事件应该通知给我们的App。例如,如果在用户离开区域时不需要通知App,则可以设置区域的notifyOnEntry属性为NO。

我们也可以在用户打开设备的屏幕时再通知用户已进入一个Beacon区域。我们只需要在注册Beacon区域时,简单的设置Beacon区域的notifyEntryStateOnDisplay属性为YES,以及设置notifyOnEntry属性为NO。为了防止多余的通知被发送给用户,只在进入一个区域时才发送一个本地通知。

当用户已经在注册的Beacon区域内时,App可以调用CLLocationManager类的startRangingBeaconsInRegion:方法来确定我们的设备与区域中的一个或多个iBeacon设备的相对距离,并在距离改变时被通知。(注意:我们总是在尝试查找区域内的iBeacon设备时调用CLLocationManager的类方法isRangingAvailable)。对于大多数程序来说,知道这个相对距离是很有用的。例如,想像一个在每个展品上安装了iBeacon设备的博物馆。如果我们使用这个博物馆相应的App,当我们走近某个展品时,就可以通过iBeacon来向我们的App发送关于展品的信息。

当指定Beacon区域的iBeacon设备进入范围、离开范围或相对距离改变时,CLLocationManager对象调用代理对象的locationManager:didRangeBeacons:inRegion:方法。这个代理方法提供一个CLBeacon对象的数组来表示当前设备范围内的iBeacon。iBeacon的数组根据离设备的相对距离来排序,最近的在最前面。我们可以使用这些对象中的信息来确定用户离每个iBeacon设备的距离。CLBeacon对象的proximity属性给出了到一个beacon的相对距离。

注:iBeacon的排列依赖于检测到的BLE无线信号的强度,以及这些信号受墙壁、门或其它物理实体的影响。当我们使用iBeacon时需要考虑这些影响因素。

代码清单2显示了如何使用一个Beacon的proximity属性来确定到用户设备的相对距离。

代码清单2:确定用户设备与beacon的相对距离

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
- (void)locationManager:(CLLocationManager *)manager didRangeBeacons:(NSArray *)beacons inRegion:(CLBeaconRegion *)region
{
if ([beacons count] > 0)
{
CLBeacon *nearestExhibit = [beacons firstObject];
if (CLProximityNear == nearestExhibit.proximity)
{
NSLog(@"%d", nearestExhibit.major.integerValue);
}
else
{
NSLog(@"test");
}
}
}

注意:当多个iBeacon设备广告了相同的proximityUUID, major和minor属性组合时,在locationManager:didRangeBeacons:inRegion:方法中它们可能会有不同的距离与精度。建议每一个beacon设备都是唯一标识的。

在iOS设备中开启iBeacon功能

支持使用BLE分享数据的iOS设备可以当作iBeacon设备来使用。由于应用必须运行于前台,因此iOS设备上的iBeacon支持主要用于测试目的和任何情况下都运行于前台的App。对于其它类型的iBeacon实现,我们必须从第三方的制造商那获取专用的iBeacon设备。

因为将iOS设备作为一个iBeacon设备需要使用Core Bluetooth framework,所以我们需要在XCode工程中链接CoreBluetooth.framework。同时在相关的资源文件中导入头文件。

要在一个iOS设备上创建和广告一个Beacon区域,首先我们需要生成一个128位的UUID作为我们的proximity UUID。我们可以在终端使用uuidgen命令来生成一个UUID。然后,我们使用这个UUID来创建一个Beacon区域,同时定义所需的major和minor值。代码清单3显示了如何创建一个新Beacon区域

代码清单3

1
2
3
NSUUID *proximityUUID = [[NSUUID alloc] initWithUUIDString:@"D80415EC-AC22-4046-8497-4BDAC297323C"];
CLBeaconRegion *beaconRegion = [[CLBeaconRegion alloc] initWithProximityUUID:proximityUUID identifier:@"com.mycompany.myregion"];

现在我们已经创建了一个Beacon区域,然后我们需要使用Core Bluetooth framework的CBPeripheralManager来广告我们的Beacon的proximity UUID(及major或minor值)。在Core Bluetooth中,一个peripheral是使用BLE来广告和分享数据的设备。广告Beacon的数据是其它设备能检测并排列我们的Beacon设备的唯一方法。

为了在Core Bluetooth中广告peripheral数据,我们调用CBPeripheralManager实例的startAdvertising:方法。这个方法需要广告数据的字典。然后我们创建一个CBPeripheralManager类的实例,并让其广告我们的Beacon来让其它设备监听。代码清单4所示了这一过程。

代码清单4

1
2
3
4
NSDictionary *beaconPeripheralData = [beaconRegion peripheralDataWithMeasuredPower:nil];
manager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil options:nil];
[manager startAdvertising:beaconPeripheralData];

重要:当我们创建一个peripheral管理对象时,peripheral管理对象会调用它的代理的peripheralManagerDidUpdateState:方法。我们必须实现这个代理方法以确保BLE在本地peripheral设备上可用。

在广告我们的iBeacon后,我们必须在前台继续运行程序来广播所需要的蓝牙信号。

小结

iBeacon是苹果提出的近场定位技术,其目标直指NFC。在App中使用iBeacon并不复杂,苹果已经为我们解决了大部分的底层技术问题。我们只需要简单的创建一个Beacon区域并监听它,在代理对象中处理相应的事件即可。它的实质就是一种定位技术,其在室内导航方面前景光明,相信这一技术会在今后大有作为。

参考

  1. Location and Maps Programming Guide
  2. 如何使用iOS 7的iBeacons来提高你的应用
  3. 开发使用 iBeacon 的 iOS 7 应用
  4. 代码示例:AirLocate: Using CoreLocation to monitor, range, and configure your device as an iBeacon