Beacon(毕垦)的初步分析

由于公司项目需要,对Beacon的通信机制和相关技术进行调研。



一、Beacon 简介

Beacon 是一种基于 BLE (Bluetooth Low Energy) 的技术,以固定间隔广播发送固定格式的数据。信号强弱以 RSSI 相对强度来表示,遇到障碍物信号会很弱。
iBeacon 是 Beacon 在 iOS 的实现,因此只能在 iOS 平台使用;Eddystone 是基于 Beacon 的数据标准以及扩展。简单的理解成 iBeacon 是内置到苹果手机里的, Beacon 是外置的设备。

iBeacon 是苹果公司 2013 年 9 月发布的移动设备用 OS(iOS7)上配备的新功能。其工作方式是,配备有低功耗蓝牙(BLE)通信功能的设备使用 BLE 技术向周围发送自己特有的 ID,接收到该ID 的应用软件会根据该 ID 采取一些行动。比如,在店铺里设置 iBeacon 通信模块的话,便可让 iPhone 和 iPad 上运行一资讯告知服务器,或者由服务器向顾客发送折扣券及进店积分。此外,还可以在家电发生故障或停止工作时使用 iBeacon 向应用软件发送资讯。

2014 年,许多组织开始着力开发蓝牙 Beacon 试点项目,到 2015 年,已经有许多公司开始尝试利用部署好的蓝牙 beacon 探索新的服务模式。据市场研究机构(ABI Research)预测,预计到2019 年,Beacon 将有 6 千万的市场占有量。

二、Beacon 特点

Beacon 特点有:

Beacon 是使用蓝牙4.0(BLE)技术发射信号的小设备
有效范围从几十厘米到几米,电池可用3年
信号为单向发射,只能发送小数据量,例如一个 128 bit的ID
智能手机通常作为接收方

通俗的说,Beacon 是一个室内蓝牙导航的“GPS卫星”,可以向覆盖区域的用户,自动发送信息,并判断用户所处位置,再基于位置传达相应信息。Beacon 传播速度快,安全性高,传输距离远,应用领域和市场前景广阔,引起诸多高新企业在此技术上发力。

三、Beacon 的标准

蓝牙无线通讯技术作为一种无线数据与语音通信的开放性全球标准,最开始的应用是在语音通信领域取代耳机线。直至 4.0 版本推出的低功耗蓝牙技术在智能可穿戴设备与智能家居设备中应用及其广泛,这些都是从最初蓝牙耳机时代逐渐革新升级过来的,现在蓝牙技术应用的智能设备几乎成为白领们追赶潮流的标志。

Beacon 的标准包括信号数据的格式等,苹果和谷歌各有一套标准,苹果标准更早,谷歌的标准更加强大。

  • Apple iBeacon 2013 6 月发布
  • Google Eddystone 2015,7 月发布

要知道蓝牙(Bluetooth®)是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用 2.4—2.485G Hz的ISM波段的 UHF 无线电波)。而且蓝牙是一种支持设备短距离通信(最大传输距离100米)的无线电技术,能够有效地简化移动通信终端设备之间的通信,从而使数据传输变得更加迅速高效;它采用分散式网络结构以及快跳频和短包技术,支持点对点及点对多点通信。

四、Beacon 的广播

Beacon 会每隔一定的时间广播一个数据包到周围,作为独立的蓝牙主机(比如手机等)在执行扫描动作时,会间隔地接收到 Beacon 广播出来的数据包。该数据包内容最多可以包含 31 个字节的内容。同时,在主机接收到广播包时,其中会指示该广播包来自于哪一个蓝牙从机 MAC 地址(每个 Beacon 拥有唯一的 MAC 地址)的从机设备和当前的接收发送信号强度指示值 RSSI 为多少。这时候,如果手机上安装有 Beacon 对应的 APP,接收到该 I D的 APP 会根据该 ID 的设置条件采取相应的动作!作为 Beacon 设备放在室内的某个固定位置,被设置成广播模式,上电后即进行广播,不能和任何低功耗蓝牙主机进行连接。

BLE 协议栈采用了分层结构,其中有一层称为 GAP(Generic Access Profile),该层负责设备间的广播,搜寻以及连接。搜寻过程涉及广播设备和扫描设备。广播设备以固定的间隔向外广播数据包,这些数据包中的信息可以帮助扫描设备确定该设备是否是其感兴趣的设备。

Beacon 设备也进行广播,但是其它设备不需要与其进行连接。我们可以称其为广播者(BLE 规范中广播者只广播不接受连接请求)。手机应用只需要利用广播包中的相关信息就可以实现定位的目的,因此不需要与 Beacon 设备进行连接。

Beacon 帧格式

广播数据包最多仅可以包含 31 字节数据,所以设计者必须慎重选择需要包含的数据。蓝牙 SIG 组织在 Core Specification Supplement (CSS)文件中将这 31 个字节数据分成多个 AD Type 结构,每个 AD Type 都有相同的结构,分别为长度字节,类型字节以及数据域。

Beacon 设备可以在一个或多个标准广播数据包中编码数据,传递信息。但是编码原理可能有所差异,即帧格式不同。目前主流的三种帧格式分别为苹果公司的 iBeacon,Radius Networks 公司的AltBeacon 以及谷歌公司的 Eddystone。因此为了与不同的beacon设备进行交互,应用开发者在开发beacon应用时需要了解对应设备的帧格式。

五、蓝牙beacon常见的应用场景

Beacon 是一种通过低功率蓝牙技术(BluetoothLowEnergy)实现精确定位的设备。当室内某个位置安装了一个 Beacon 信号发射基站时,这个基站会创建一个信号区域。用户携带着移动设备进入信号区域的时候,相应的程序便会主动提示用户是否需要接入这个信号网络,同时手机中的应用程序会把用户离信号发射基站的距离划分为近(near),适中(medium)和远(far),并由此精确的对用户进行定位,依据用户处于的特定情境向他传达相应的信息。

时下,蓝牙 Beacon 在国外超市、机场的部署已经相当普遍,尤其用在蓝牙室内定位方面,Beacon 的使用是蓝牙应用的方向和趋势之一。蓝牙 Beacon 比较常见的应用是一下几个方面:

  • 信息推送(商场、景区、博物馆)
  • 蓝牙beacon室内导航(会展、图书馆、博物馆、酒店、机场、校园、医院、监狱、商业CBD)
  • beacon和微信摇一摇结合,可以开展新的营销和互动方式,比如摇关注、摇签到、摇投票、摇导航、摇互动

在大多数应用场景中,蓝牙beacon主要用于室内定位。不论在商场,机场,办公室,还是博物馆,都可以利用这些位置信息来提供服务。在这些案例中,通过将蓝牙 Beacon 安装在特定位置,然后利用智能手机上的 APP 与之交互,就可以达到定位的效果。

六、Beacon 和蓝牙的区别

iBeacon 它是一种低耗能蓝牙技术。是苹果公司2013年9月发布的移动设备用 OS(iOS7)上配备的新功能。其工作方式是,配备有低功耗蓝牙(BLE)通信功能的设备使用 BLE 技术向周围发送自己特有的 ID,接收到该 ID 的应用软件会根据该 ID 采取一些行动。

蓝牙技术是一种无线技术标准,可实现固定设备、移动设备和楼宇个人域网之间的短距离数据交换(使用2.4—2.485GHz的ISM波段的UHF无线电波)。

在很多硬件人员的眼中认为,iBeacon 和 BLE 没有区别啊,都是在同一个模块上面开发的,只是发送的数据格式不一样,iBeacon 应该和 BLE 没有区别,这个其实是一个错误,在 iOS 的开发过程中 iBeacon 和 BLE 是两个不同的东西,所有的数据都被苹果拦截了,只给开发者特定的 API 可以调用。

七、APP集成

Beacon 的使用需要手机 APP 支持,每家都需要自己的 APP 集成该功能。

Beacon 设备本身只向外发射信号,无法向手机推送消息,也无法接收消息。既然 Beacon 设备无法推送消息,那前面说的推送消息是如何实现的呢?这就得靠安装在手机上的 APP 了。比如有个顾客安装了商场的 APP,商家在数码专柜的角落部署了一个 Beacon,当顾客靠近数码专柜时, APP 在后台检测到你距离数码专柜不到 5 米,这时 APP 发起一个通知,你点开后弹出了最新的数码产品介绍和优惠信息。检测与 Beacon 之间的距离,并发起通知,全都由 APP 本身控制。

7.1 Android 集成

Beacon 设备在 Android 平台上就是一个 BLE 设备,所以操作也基本跟 BLE 扫描和解析一致。

扫描

扫描方法和BLE扫描方法一样的:

//这里使用的android 4.3的API,android 5.0开始扫描API做了一点变化,为了获得更大的兼容性,我们依然使用的4.3的API。
//不需要兼容4.3的推荐使用android 5.0 的API,官方已经帮助我们封装了很多,使用起来更简单
bluetoothAdapter.startLeScan( leScanCallback);  
private LeScanCallback leScanCallback=new LeScanCallback() { 
    @Override 
    public void onLeScan(BluetoothDevice bluetoothdeivce, int rssi, byte[] scandata) {
        //把byte数组转成16进制字符串,方便查看 
        Log.e("TAG","scandata:"+ Bytes2HexString(scandata) +" rssi:"+rssi);
    } 
};

这样扫描到的是所有的 BLE 设备,接下来要识别 BLE 设备是不是 Beacon 设备。

识别

识别就是通过扫描回调里的 byte[] scandata 来进行判断,判断依据的广播格式:

这个广播格式规定了 Beacon 的广播数据是 30 个字节,第 0,1,2 字节是 BLE4.0 的协议固定格式,第3字节 Length ,0x1A (16 进制的 1A 等于 10 进制 26)表示后面的数据是 26 个字节长度( 3 + 1 + 26 = 30)。再看第 4 字节名称是 Type,数据 0xFF,也是 BLE4.0协议里的,顾名思义,0xFF表示的是一个类型,是厂商数据类型,表示后面的25个字节就是厂商数据(Manufacturer Data,BLE 设备厂商可以自定义这部分数据,Manufacturer Data 由两部分构成:厂商 id 和数据部分)。Manufacturer Data 里的前2个字节也就是第 5 - 6 字节,是厂商的 id,固定占 2 个字节,苹果的公司 id 是 0x004 C(苹果公司向世界蓝牙组织申请的,不同的公司有不同的 id),表示这个设备使用的是苹果的协议,后面的第 7-8 字节是苹果规定的固定的 0x0215,表示这个设备是苹果的 iBeacon 设备,再就是 iBeacon设备的 uuid,major,minor 等信息了。

if(scandata[5]==0x4C&&scandata[6]==0x00&&scandata[7]==0x02&&scandata[8]==0x15) {
  //这是一个iBeacon设备。
  //注意这里004C的判断,在广播里厂商id这2个字节的数据是颠倒的
}

//这里用了android 5.0 API扫描结果来演示
//上面提到的okble框架在4.3基础上封装的跟5.0 API一样,喜欢的可以直接用
SparseArray<byte[]> manufacturerData= scanResult.getManufacturerSpecificData();
int size_1=manufacturerData.size();
for (int i=0;i<size_1;i++){
    int key=manufacturerData.keyAt(i);
    byte[] value=manufacturerData.get(key);
    if(key==0x004C) {//0x004c is apple company id
        if(value!=null && value.length==23&& value[0]==0x02&&value[1]==0x15){
            //this is an iBeacon

        }
    }
}

如果项目只用到 iBeacon,使用第一种简便判断法的,效率会高点。

解析

识别到是 iBeacon 后,然后解析出对应的 uuid,major,minor 等信息。

byte[] uuidValue=new byte[16];
System.arraycopy(scandata, 9, uuidValue, 0, 16);
String uuid="";
String hexStr=BytesToHexString(uuidValue);
uuid=hexStr.substring(0, 8);
uuid+="-";
uuid+=hexStr.substring(8, 12);
uuid+="-";
uuid+=hexStr.substring(12, 16);
uuid+="-";
uuid+=hexStr.substring(16, 20);
uuid+="-";
uuid+=hexStr.substring(20, 32);
int major=buildUint16(scandata[25], scandata[26]);
int minor=buildUint16(scandata[27], scandata[28]);
int measuredPower= scandata[29];

-------↓↓↓↓↓↓工具类↓↓↓↓↓↓↓----------
private final static byte[] hex = "0123456789ABCDEF".getBytes();

/**
     *  字节数组转十六进制字符串
     *
     * @param b: byte[] bytes_1=new byte[]{(byte) 0xA0,(byte) 0xB1,2}
     * @return "A0B102"
     */
public static String BytesToHexString(byte[] b) {
    if(b==null){
        return null;
    }
    byte[] buff = new byte[2 * b.length];
    for (int i = 0; i < b.length; i++) {
        buff[2 * i] = hex[(b[i] >> 4) & 0x0f];
        buff[2 * i + 1] = hex[b[i] & 0x0f];
    }
    return new String(buff);
}

/**
     * 高低位 组成int,
     * @param hi
     * @param lo
     * @return
     */
public static int buildUint16(byte hi, byte lo) {
    return (int) ((hi << 8) + (lo & 0xff));
}

7.2 iOS集成

iBeacon 其工作方式是: 配备有低功耗蓝牙(BLE)通信功能的设备(iBeacon)使用 BLE 技术向周围发送自己特有的 UUID,使用 iBeacon 的 App 接收到该 UUID 的应用软件会根据该 UUID 采取一些行动。
iOS 在 BLE、iBeacon 开发过程中与 Android 的区别:

  • 在 iOS 中所有的数据都是通过 API 获取的,也就是说在 iOS 中不会看到蓝牙模块的裸数据(在这里的裸数据就代表蓝牙模块发送的 16 进制的数据),只能拿到苹果公司提供的极个别的 API 中的数据
  • BLE、iBeacon 各使用各自的 API,他们之间没有任何对应关系。如果想使用 BLE 就不可能获取到 iBeacon 的 Major、Minor、UUID 等信息,如果使用 iBeacon,没有办法发起链接请求获取服务
  • 苹果公司为了省电和隐私限制只能监听指定 UUID 的 iBeacon,无法像 Android 一样搜索附近所有的 iBeacon 信息,虽然 iBeacon 扫描底层可以获取到附近的所有的 iBeacon 信息

Beacon 使用苹果提供 CoreLocation 库 然而在 BLE 在开发过程中使用 CoreBluetooth 库。从官方提供的库来看就很清楚了,特别是在 IOS8 之上的时候如果想使用 ibeacon,必须让用户点击是否允许“ XX APP 使用地理位置”。如果 在第一次使用 iOS APP 扫描 iBeacon 的时候没有提示这句话是不可能接收到 iBeacon 的信号(除非 iOS 8.0 之下)。如果是BLE则的开发过程中之需要提示用户打开蓝牙,并不要求其他的地理位置任何信息。

iBeacon 在 CoreLocation 框架中抽象为 CLBeacon 类, 该类有6个属性,分别是:

  • proximityUUID,是一个 NSUUID,用来标识公司。每个公司、组织使用的 iBeacon 应该拥有同样的 proximityUUID。
  • major,主要值,用来识别一组相关联的 beacon,例如在连锁超市的场景中,每个分店的 beacon 应该拥有同样的 major。
  • minor,次要值,则用来区分某个特定的 beacon。
  • proximity,远近范围的,一个枚举值。
typedef NS_ENUM(NSInteger, CLProximity) {
CLProximityUnknown,// 无效
CLProximityImmediate,//在几厘米内
CLProximityNear,//在几米内
CLProximityFar//超过 10 米以外,不过在测试中超不过10米就是far
}
  • accuracy,与iBeacon的距离。
  • rssi,信号轻度为负值,越接近0信号越强,等于0时无法获取信号强度。

参考