Android的BLE广播数据包介绍和解析---BLE--Android系列, 蓝牙技术BLE

目录

一、引言

二、广播的类型

三、广播数据格式

四、广播数据解析

五、总结


一、引言

理解和分析这个数据包结构(这里面也涉及广播间隔时间的设置,设备广播数据间隔设置长了,会影响设备被发现的效率;设置短时,又响应功耗)。

我们所说的BLE设备,其实是有区分有两种角色 Central 和 Peripheral,也就是中心设备和外围设备。中心设备可以主动连接外围设备,外围设备发送广播或者被中心设备连接。外围通过广播被中心设备发现,广播中带有外围设备自身的相关信息。在日常APP开发中,手机端的BLE一般都是充当中心设备的。

广播包有两种:广播包(Advertising Data)和响应包(Scan Response),其中广播包是每个设备必须广播的,而响应包是可选的。

二、广播的类型

广播的类型一般分为四种,有:

2.1 可连接的非定向广播(Connectable Undirected Event Type)

这种是用途最广的广播类型,包括广播数据和扫描响应数据,它表示当前设备可以接受其他任何设备的连接请求。进行通用广播的设备能够被扫描设备扫描到,或者在接收到连接请求时作为从设备进入一个连接。通用广播可以在没有连接的情况下发出,换句话说,没有主从设备之分。

2.2 可连接的定向广播(Connectable Directed Event Type)

定向广播类型是为了尽可能快的建立连接。这种报文包含两个地址:广播者的地址和发起者的地址。发起者收到发给自己的定向广播报文之后,可以立即发送连接请求作为回应。定向广播类型有特殊的时序要求。完整的广播事件必须每3.75ms重复一次。这一要求使得扫描设备只需扫描3.75ms便可以收到定向广播设备的消息。当然,如此快的发送会让报文充斥着广播信道,进而导致该区域内的其他设备无法进行广播。因此,定向广播不可以持续1.28s以上的时间。如果主机没有主动要求停止,或者连接没有建立,控制器都会自动停止广播。一旦到了1.28s,主机便只能使用间隔长得多的可连接非定向广播让其他设备来连接。

当使用定向广播时,设备不能被主动扫描。此外,定向广播报文的净荷中也不能带有其他附加数据。该净荷只能包含两个必须的地址。

2.3 不可连接的非定向广播(Non-connectable Undirected Event Type)

仅仅发送广播数据,而不想被扫描或者连接。这也是唯一可用于只有发射机而没有接收机设备的广播类型。不可连接广播设备不会进入连接态,因此,它只能根据主机的要求在广播态和就绪态之间切换。

2.4 可扫描的非定向广播(Scannable Undirected Event Type)

又称可发现广播,这种广播不能用于发起连接,但允许其他设备扫描该广播设备。这意味着该设备可以被发现,既可以发送广播数据,也可以响应扫描发送扫描回应数据,但不能建立连接。这是一种适用于广播数据的广播形式,动态数据可以包含于广播数据之中,而静态数据可以包含于扫描响应数据之中。

注意:所谓的定向和非定向针对的是广播的对象,如果是针对特定的对象进行广播(在广播包PDU中会包含目标对象的MAC)就是定向广播,反之就是非定向。可连接和不可连接是指是否接受连接请求,如果是不可连接的广播类型,它将不回应连接请求。可扫描广播类型是指回应扫描请求。

三、广播数据格式

每个包都是 31 字节,数据包中分为有效数据(significant)和无效数据(non-significant)两部分。

  • 有效数据部分:包含若干个广播数据单元,称为 AD Structure。如图中所示,AD Structure 的组成是:第一个字节是长度值 Len,表示接下来的 Len 个字节是数据部分。数据部分的第一个字节表示数据的类型 AD Type,剩下的 Len - 1 个字节是真正的数据 AD data。其中 AD type 非常关键,决定了 AD Data 的数据代表的是什么和怎么解析
  • 无效数据部分:因为广播包的长度必须是 31 个 byte,如果有效数据部分不到 31 自己,剩下的就用 0 补全。这部分的数据是无效的,解释的时候,忽略即可

AD Type 包括如下类型:

Flags: TYPE = 0x01。这个数据用来标识设备 LE 物理连接的功能。DATA 是 0 到多个字节的 Flag 值,每个 bit 上用 0 或者 1 来表示是否为 True。如果有任何一个 bit 不为 0,并且广播包是可连接的,就必须包含此数据。各 bit 的定义如下:

  • bit 0: LE 有限发现模式
  • bit 1: LE 普通发现模式
  • bit 2: 不支持 BR/EDR
  • bit 3: 对 Same Device Capable(Controller) 同时支持 BLE 和 BR/EDR
  • bit 4: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
  • bit 5..7: 预留

Service UUID: 广播数据中一般都会把设备支持的 GATT Service 广播出来,用来告诉外面本设备所支持的 Service。有三种类型的 UUID:16 bit, 32bit, 128 bit。广播中,每种类型类型有有两个类别:完整和非完整的。这样就共有 6 种 AD Type。

  • 非完整的 16 bit UUID 列表: TYPE = 0x02;
  • 完整的 16 bit UUID 列表: TYPE = 0x03;
  • 非完整的 32 bit UUID 列表: TYPE = 0x04;
  • 完整的 32 bit UUID 列表: TYPE = 0x05;
  • 非完整的 128 bit UUID 列表: TYPE = 0x06;
  • 完整的 128 bit UUID 列表: TYPE = 0x07;

Local Name: 设备名字,DATA 是名字的字符串。Local Name 可以是设备的全名,也可以是设备名字的缩写,其中缩写必须是全名的前面的若干字符。

  • 设备全名: TYPE = 0x08
  • 设备简称: TYPE = 0x09

TX Power Level: TYPE = 0x0A,表示设备发送广播包的信号强度。DATA 部分是一个字节,表示 -127 到 + 127 dBm。

带外安全管理(Security Manager Out of Band):TYPE = 0x11。DATA 也是 Flag,每个 bit 表示一个功能:

  • bit 0: OOB Flag,0 表示没有 OOB 数据,1 表示有
  • bit 1: 支持 LE
  • bit 2: 对 Same Device Capable(Host) 同时支持 BLE 和 BR/EDR
  • bit 3: 地址类型,0 表示公开地址,1 表示随机地址

外设(Slave)连接间隔范围:TYPE = 0x12。数据中定义了 Slave 最大和最小连接间隔,数据包含 4 个字节:

  • 前 2 字节:定义最小连接间隔,取值范围:0x0006 ~ 0x0C80,而 0xFFFF 表示未定义;
  • 后 2 字节:定义最大连接间隔,同上,不过需要保证最大连接间隔大于或者等于最小连接间隔。

服务搜寻:外围设备可以要请中心设备提供相应的 Service。其数据定义和前面的 Service UUID 类似:

  • 16 bit UUID 列表: TYPE = 0x14
  • 32 bit UUID 列表: TYPE = 0x??
  • 128 bit UUID 列表: TYPE = 0x15

Service Data: Service 对应的数据。

  • 16 bit UUID Service: TYPE = 0x16, 前 2 字节是 UUID,后面是 Service 的数据;
  • 32 bit UUID Service: TYPE = 0x??, 前 4 字节是 UUID,后面是 Service 的数据;
  • 128 bit UUID Service: TYPE = 0x??, 前 16 字节是 UUID,后面是 Service 的数据;

公开目标地址:TYPE = 0x17,表示希望这个广播包被指定的目标设备处理,此设备绑定了公开地址,DATA 是目标地址列表,每个地址 6 字节。

随机目标地址:TYPE = 0x18,定义和前一个类似,表示希望这个广播包被指定的目标设备处理,此设备绑定了随机地址,DATA 是目标地址列表,每个地址 6 字节。

Appearance:TYPE = 0x19,DATA 是表示了设备的外观。

**厂商自定义数据: **TYPE = 0xFF,厂商自定义的数据中,前两个字节表示厂商 ID,剩下的是厂商自己按照需求添加,里面的数据内容自己定义。

主要的也就是这些了,更多的可参考SIG官网。

四、广播数据解析

4.1 旧接口(API 21 之前)

在API21之前,Android蓝牙扫描可以使用 BluetoothAdapter的startLeScan来发起扫描。基本用法如下:
BluetoothAdapter:

    //不带过滤搜索
    startLeScan(BluetoothAdapter.LeScanCallback callback)
    //带UUID过滤搜索
    startLeScan(UUID[] serviceUuids, BluetoothAdapter.LeScanCallback callback)
 
    BluetoothAdapter.LeScanCallback mLeScanCallback =  new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            // 解析广播数据
            parseScanRecodeData(scanRecord);
        }
    };

当扫描到设备以后,就会回调 onLeScan(...),这里的参数 scanRecord 就是广播数据,同时包含广播数据和扫描相应数据(如果有的话),所以长度一般就是 62 字节。

整个广播数据就在这个scanRecord中,所以需要对scanRecord进行字节解析

public static ParsedAd parseScanRecodeData(byte[] adv_data) {
    ParsedAd parsedAd = new ParsedAd();
    ByteBuffer buffer = ByteBuffer.wrap(adv_data).order(ByteOrder.LITTLE_ENDIAN);
    while (buffer.remaining() > 2) {
        byte length = buffer.get();
        if (length == 0)
            break;
 
        byte type = buffer.get();
        length -= 1;
        switch (type) {
            case 0x01: // Flags
                parsedAd.flags = buffer.get();
                length--;
                break;
            case 0x02: // Partial list of 16-bit UUIDs
            case 0x03: // Complete list of 16-bit UUIDs
            case 0x14: // List of 16-bit Service Solicitation UUIDs
                while (length >= 2) {
                    parsedAd.uuids.add(UUID.fromString(String.format(
                            "%08x-0000-1000-8000-00805f9b34fb", buffer.getShort())));
                    length -= 2;
                }
                break;
            case 0x04: // Partial list of 32 bit service UUIDs
            case 0x05: // Complete list of 32 bit service UUIDs
                while (length >= 4) {
                    parsedAd.uuids.add(UUID.fromString(String.format(
                            "%08x-0000-1000-8000-00805f9b34fb", buffer.getInt())));
                    length -= 4;
                }
                break;
            case 0x06: // Partial list of 128-bit UUIDs
            case 0x07: // Complete list of 128-bit UUIDs
            case 0x15: // List of 128-bit Service Solicitation UUIDs
                while (length >= 16) {
                    long lsb = buffer.getLong();
                    long msb = buffer.getLong();
                    parsedAd.uuids.add(new UUID(msb, lsb));
                    length -= 16;
                }
                break;
            case 0x08: // Short local device name
            case 0x09: // Complete local device name
                byte sb[] = new byte[length];
                buffer.get(sb, 0, length);
                length = 0;
                parsedAd.localName = new String(sb).trim();
                break;                
            case (byte) 0xFF: // Manufacturer Specific Data
                parsedAd.manufacturer = buffer.getShort();
                length -= 2;
                break;
            default: // skip
                break;
        }
        if (length > 0) {
            buffer.position(buffer.position() + length);
        }
    }
    return parsedAd;
}

4.2 新接口

在Android 5.0 (API 21)及之后使用新接口扫描BLE设备,也提供了一些广播数据包的解析接口。新和扫描方法使用的是BluetoothLeScanner,封装成了一个新的类,BluetoothLeScanner还有另一个扫描方法,这个方法就是多了一个扫描过滤 和 扫描设置参数:

    BluetoothLeScanner bluetoothLeScanner=bluetoothAdapter.getBluetoothLeScanner();
    bluetoothLeScanner.startScan(mLeScanCallback);
    //扫描过滤 和 扫描设置参数:
    bluetoothLeScanner.startScan(List<ScanFilter> filters, ScanSettings settings, mLeScanCallback)
 
    ScanCallback mLeScanCallback = new ScanCallback() {
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            Log.e(TAG, "ScanResult:" + scanResult.toString());
            ![](http://www.xmamiga.com/wp-content/uploads/2018/10/Android-BLE-Scaner.png)byte[] scanData=result.getScanRecord().getBytes();
            //把byte数组转成16进制字符串,方便查看
            //Log.e("TAG","onScanResult :"+utils.Bytes2HexString(scanData));//与旧接口一致
            Log.e(TAG, "newdevice:" + device.getAddress() + "  " + device.getName());
            Log.e(TAG, "scanRecord:" + scanResult.getScanRecord().toString());
            Log.e(TAG, "scanRecord getManufacturerSpecificData:" + scanResult.getScanRecord().getManufacturerSpecificData().toString());
        }
    };

搜索结果如下:

 

手机端运行Log:

涉及接口有:

涉及接口有:
ScanResult接口:

TypePublic methodsins
intgetAdvertisingSid()Returns the advertising set id.
BluetoothDevicegetDevice()Returns the remote Bluetooth device identified by the Bluetooth device address.
intgetPeriodicAdvertisingInterval()Returns the periodic advertising interval in units of 1.25ms.
intgetRssi()Returns the received signal strength in dBm.
ScanRecordgetScanRecord()Returns the scan record, which is a combination of advertisement and scan response.

ScanRecord接口:

TypePublic methodsins
intgetAdvertiseFlags()Returns the advertising flags indicating the discoverable mode and capability of the device.
byte[]getBytes()Returns raw bytes of scan record.
StringgetDeviceName()Returns the local name of the BLE device.
SparseArray<byte[]>getManufacturerSpecificData()Returns a sparse array of manufacturer identifier and its corresponding manufacturer specific data.
byte[]getManufacturerSpecificData(int manufacturerId)Returns the manufacturer specific data associated with the manufacturer id.
byte[]getServiceData(ParcelUuid serviceDataUuid)Returns the service data byte array associated with the serviceUuid.
List≶ParcelUuid&gt;getServiceUuids()Returns a list of service UUIDs within the advertisement that are used to identify the bluetooth GATT services.

五、总结

BLE广播数据包并不复杂,数来数去也有那几个字节,用心地去理解,就可以解析出自已想要的数据。

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Ble hogp是一种蓝牙低功耗技术,主要用于手机与外设之间的通信。下面分别介绍ble hogp的广播、扫描、连接和数据读写源的特点。 1. 广播广播是指外设将自身的信息以广播的方式发送出去,让手机能够主动发现并连接到该外设。Ble hogp的广播具有低功耗、简单快速的特点。外设只需要定期发送广播包,手机接收到广播包后可以通过解析其中的信息来决定是否连接到该外设。 2. 扫描:手机通过扫描的方式来主动寻找广播中的外设。扫描可以设置不同的模式,例如高功耗模式和低功耗模式。在低功耗模式下,手机会定期地对周围蓝牙设备进行扫描,以获取设备的信息,但不会建立连接。这样可以降低功耗并提高扫描效率。 3. 连接:当手机扫描到外设后,可以发起连接请求。连接是建立在广播和扫描的基础上的,通过连接可以进行双向通信。Ble hogp的连接具有低延迟、高稳定性的特点。一旦连接建立成功,手机与外设可以通过读写特定的属性来进行数据交互。 4. 数据读写:通过连接建立后,手机和外设之间可以进行数据交换。外设可以提供一些特定的属性,例如传感器数据、设置参数等等。手机可以通过读取这些属性来获取数据,也可以通过写入这些属性来发送指令给外设。数据读写是ble hogp的核心功能之一。 总之,ble hogp通过广播、扫描、连接和数据读写来实现手机与外设之间的低功耗通信。这种技术在物联网、智能家居等领域有着广泛的应用前景。 ### 回答2: BLE(Bluetooth Low Energy)是一种低功耗的蓝牙通信技术,具有广播、扫描、连接和数据读写等四个主要功能。下面将对这四个功能进行详细解释。 首先是BLE广播功能。BLE设备可以通过广播发出自己的存在和基本信息,使周围的其他设备可以发现并与之建立连接。广播可以包含设备的唯一标识符(如MAC地址)、设备名称以及其他自定义的数据。 其次是BLE的扫描功能。扫描是指BLE设备搜索周围的其他设备并获取它们的广播信息。通过扫描,设备可以发现附近的BLE设备,并获取设备的基本信息,以便进行连接。 连接是BLE的另一个重要功能。一旦设备发现了周围的BLE设备,并获取了设备的广播信息,就可以开始与目标设备之间建立连接。连接可以是单向的(一主多从)或双向的(多主多从),连接的建立可以通过设备之间的握手过程完成。 最后是BLE的数据读写功能。一旦连接建立成功,设备之间可以进行数据的传输。一个设备可以向另一个设备写入数据,另一个设备则可以读取这些数据。数据的读写可以通过BLE的特征(Characteristics)和服务(Services)来实现,特征和服务通常通过UUID(Universally Unique Identifier)来标识。 总之,BLE广播、扫描、连接和数据读写是其四个主要功能。通过这些功能,BLE设备可以实现低功耗的蓝牙通信,并与其他设备进行数据交换。 ### 回答3: BLE(Bluetooth Low Energy)是一种低功耗蓝牙技术,常用于物联网设备之间的通信。BLE设备的工作流程通常包括广播、扫描、连接和数据读写。 首先是广播(Advertising),BLE设备可以周期性地发送广播包,携带自己的标识和一些附加信息,以便其他设备能够检测到它们的存在。广播的目的是宣告自己的存在,以及提供连接的可能性。这些广播包可以被其他设备扫描到。 接下来是扫描(Scanning),BLE设备可以主动扫描周围的广播包,以检测到附近的其他设备,并获得它们的标识和附加信息。扫描有两种模式,一种是主动扫描模式,设备主动发送请求,另一种是被动扫描模式,设备只接收广播包而不发送请求。 当一个设备检测到其他设备的广播包并确定要与其建立连接时,就可以进行连接(Connection)。连接由两个设备之间的主设备和从设备建立,主设备负责管理连接和数据传输。连接状态下,设备之间可以进行数据传输、发送命令、获取传感器数据等操作。 最后是数据读写(Data Reading/Writing),在连接状态下,设备之间可以进行数据的读写操作。一个设备可以将数据写入其他设备的特征值,而另一个设备可以读取这些特征值的数据。通过这种方式,设备之间可以进行信息交换和数据传输。 总结来说,BLE设备的工作流程包括广播、扫描、连接和数据读写。广播用于宣告设备的存在,扫描用于检测其他设备,连接用于建立设备之间的通信连接,数据读写用于在连接状态下进行数据交换和传输。这些环节共同构成了BLE设备之间的通信过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_57781768

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值