目录
一、前言
对于低功耗蓝牙而言,一般分为两种类型的设备:一种为是Central devices(中心设备),一种是Peripheral devices(外围设备)。中心设备一般为手机或者Pad等设备,外围设备一般为手环,iBeacon等低功耗蓝牙设备。外围设备一般低功耗蓝牙设备,时刻通过广播向外发送数据包。只要在范围内的中心设备都能够收到相关广播。对于不了解低功耗蓝牙的可以阅读我的文章:认识Bluetooth Low Energy
二、认识iBeacon
我们上面提到了iBeacon,其实iBeacon是基于低功耗蓝牙这项技术的。最早是苹果公司在移动设备上配备了iBeacon的,通过iBeacon发送广播数据,附近的设备可以接收数据然后进行相关操作。举个例子比如某些店铺安装了iBeacon设备,然后手机用户经过店铺就会收到店铺促销活动的相关消息。这类应用有很多。
1.iBeacon的特点
- 时刻发送广播数据包;
- 一般不可连接;
- 短距离传输,一般能达到50~80m;
- 信号强度和广播距离会受到周围环境的干扰;
- 可以通过信号强度(RSSI)粗略计算位置信息;
2.低功耗蓝牙的数据格式
完整数据包为:广播包(Advertising Data)和响应包(Scan Response Data),对于每个低功耗设备而言,广播包都是必须有的,而响应包是可选的。在前面的文章中我们介绍过关于低功耗蓝牙的相关东西,不熟悉的童鞋可以阅读认识Bluetooth Low Energy。每个数据包格式如下图:
- 每个数据包都包含31个字节,一般都包含有效数据(Significant part)部分和无效数据部分(Non-sinificant part);
- 有效数据部分:包含若干个广播数据单元,如图所示,称为AD Structure。其中每个数据单元都是Length+Data的格式,Length是一个字节的长度,Data包含AD Type+AD Data,数据长度为Length。AD Type是该数据单元所代表的数据类型,为一个字节;AD Data是该数据单元真正应该解析的数据部分,数据长度为Length-1。数据解析部分会在后面详细介绍;
- 无效数据部分:若有效数据不足31个字节,无效数据会用0进行补位;
注意:
bit:一个二进制数据0或者1;
1 byte = 8 bit
1 octets: 8 bit数组串;
3.iBeacon数据格式
iBeacon设备就是低功耗蓝牙的一种,它特有的参数,请阅读:iBeacon参数。
三、解析广播数据
在上一篇文章中,我们进行了低功耗蓝牙设备的扫描工作。不清楚蓝牙扫描的可以阅读低功耗蓝牙开发之设备扫描。当我们开启蓝牙扫描之后,会在ScanCallback的onScanResult方法中回调扫描到的低功耗蓝牙设备。在这个回调方法里第一个参数是callbackType,是在开始扫描的时候设置的回调类型;第二个参数是ScanResult,里面包含了扫描到设备的信息。
我们在这里使用云里物里这个设备厂商的iBeacon设备作为分析示例,打印一下ScanResult这个参数会发现:
ScanResult{
device=C2:00:F4:00:00:4E,
scanRecord=ScanRecord [mAdvertiseFlags=6,
mServiceUuids=null,
mManufacturerSpecificData={76=[2, 21, -30, -59, 109, -75, -33, -5, 72, -46, -80, 96, -48, -11, -89, 16, -106, -32, 39, 17, 76, -70, -59]},
mServiceData={0000fff0-0000-1000-8000-00805f9b34fb=[100, 39, 17, 76, -70]},
mTxPowerLevel=4,
mDeviceName=MiniBeacon_00001],
rssi=-70,
timestampNanos=214956467801851,
eventType=27,
primaryPhy=1,
secondaryPhy=0,
advertisingSid=255,
txPower=127,
periodicAdvertisingInterval=0
}
我们分析一下能从这个回调里拿到什么参数:
- BluetoothDevice:远程蓝牙设备的一些信息,包含设备名,设备MAC地址,蓝牙设备类型等信息;
- ScanRecord:低功耗蓝牙的扫描结果的原始信息,包含蓝牙的Flags,ManufacturerSpecificData,ServiceData,Tx Power Level(广播功率)等;
- Rssi:实时信号强度;
- TimestampNanos:自设备Boot为标准获得的该蓝牙设备扫描到的时间戳;
等;
下面我们针对低功耗蓝牙的主要参数进行解析:
1.解析iBeacon数据:
数据来源:ScanRecord;
通过ScanRecord获取Byte数组即可获取16进制Byte数组:
- 16进制Byte数组:
//广播包数据
[2, 1, 6, 26, -1, 76, 0, 2, 21,#iBeacon advertising prefix(9)
-30, -59, 109, -75, -33, -5, 72, -46, -80, 96, -48, -11, -89, 16, -106, -32,# iBeacon profile serviceUuid(16)
39, 17,#major(2)
76, -70,#minor(2)
-59,#txPower 表示距离1米是应该接收到的信号强度,可用于计算距离(1)
//响应包数据
2, 10, 4, #Tx Power Level
8, 22, -16, -1, 100, 39, 17, 76, -70,#Service Data
17, 9, 77, 105, 110, 105, 66, 101, 97, 99, 111, 110, 95, 48, 48, 48, 50, 55,#Complete Local Name
0, 0]
有些心细的童鞋可能会发想上面的广播包和响应包不是31个字节啊!??具体为什么我也没有深究过,通过ScanRecord获取字节数组就得到上面的结果,有可能是Android系统做了特殊的处理。大家可以发表一下自己的见解!不胜感激~
- 16进制HexString:
将上述数据转化成Hexadecimal Value(十六进制),为什么需要转化为十进制呢?一方面是行业习惯,另一方面是方便查找AD type做数据解析。
//广播报数据
02 01 06 1A FF 4C 00 02 15 #iBeacon advertising prefix(9)
E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 # iBeacon profile serviceUuid(16)
27 11 #major(2)
4C BA #minor(2)
C5 #txPower 表示距离1米是应该接收到的信号强度,可用于计算距离(1)
//响应包数据
02 0A 04 #Tx Power Level
08 16 F0 FF 64 27 11 4C BA #Service Data
11 09 4D 69 6E 69 42 65 61 63 6F 6E 5F 30 30 30 32 37 #Complete Local Name
00 00
- 按照GAP(蓝牙接入规范)解析
(1)《Flags》(02 01 06)-3
0 2
len:02 type:01 value:06(3)
##以value为06(HexString)为例
获取value的各bit位数据:0000 0110
解析结果:LE普通发现模式;不支持BR/EDR
##解析规则:各位值为1
bit 0: LE有限发现模式 (LELimitDiscoverable)
bit 1: LE普通发现模式 (LEGeneralDiscoverable)
bit 2: 不支持BR/EDR (BrEdrNotSupported)
bit 3: 对Same Device Capable(Controller)同时支持BLE和BR/EDR(LEAndBrEdrCapable(Controller))
bit 4: 对Same Device Capable(Host)同时支持BLE和BR/EDR(LEAndBrEdrCapable(Host))
bit 5..7: 预留
(2)《Manufacturer Specific Data》(1A FF 4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 27 11 4C BA C5)-27
3 4 5 29
len:1A(26) type:FF value:4C 00 02 15 E2 C5 6D B5 DF FB 48 D2 B0 60 D0 F5 A7 10 96 E0 27 11 4C BA C5 (5-29)
##Company identifier code (0x004C == Apple)
02 Byte 0 of iBeacon advertisement indicator
15 Byte 1 of iBeacon advertisement indicator
27 11 #major(2)
4C BA #minor(2)
C5 #txPower 表示距离1米是应该接收到的信号强度
(3)《Tx Power Level》(02 0A 00)-3
30 31 32
len:02 type:0A value:04(3)
(4)《Service Data》(08 16 F0 FF 64 27 11 4C BA)-09
33 34 35 41
len:08 type:16 value:F0 FF 64 27 11 4C BA
(5)《Complete Local Name》(11 09 4D 69 6E 69 42 65 61 63 6F 6E 5F 30 30 30 32 37)-18
len:11(17) type:09 value:4D 69 6E 69 42 65 61 63 6F 6E 5F 30 30 30 32 37
上面这些参数都是基于Generic Access Profile和Bluetooth Core Specification v4.0进行解析的。
2.设备基本参数:
- Name(设备名):来源BluetoothDevice-device.getName();
- Address(Mac地址):来源BluetoothDevice-device.getAddress();
- Device Type(蓝牙类型):来源BluetoothDevice-device.getType();
- BondState(绑定状态):来源BluetoothDevice-device.getBondState();
- Rssi(实时信号强度):来源ScanResult-result.getRssi();
- Tx Power Level(发射功率等级):来源ScanRecord-record.getTxPowerLevel()或通过响应包数据解析得到,类型为:0x0A;
- Flags(蓝牙的特性):通过解析ManufacturerSpecificData获取,类型为:0x01;
- Manufacturer Specific Data(制造商特定数据):通过ManufacturerSpecificData获取,类型为:0xFF。可以获取低功耗蓝牙设备的公司识别码,(iBeacon)设备的UUID,Major,Minor,Rssi at 1m(广播校验值)在此处解析;
- ServiceData(响应包数据):通过ScanRecord获取,类型:0x16,可以获取ServiceData的UUID和附加数据等;
到这里就基本结束了,总的而言如果是自产设备,可以在响应包里根据业务需求添加需要的信息。