微信蓝牙外设开发记录 - 1 (微信蓝牙设备广播包解析)

1. 前言

     最近领导安排一个项目,直接丢了一个机器给我,和两份通讯协议给我,让我完成Android 端和微信小程序平台的蓝牙BLE项目开发。我一看,我问领导这个项目还有没有其他相关资料,领导回复两个字:“没有”,我顿时蒙了,又是这样子,每次由他安排的项目总是坑,还问我什么大概什么时候可以做好,什么时候可以提交一份Demo. 此时,想哭的心都有。领导没有相关项目资料,只能自己想办法了,后来看协议,发现这种蓝牙设备是微信蓝牙设备。就是蓝牙模块是符合微信蓝牙规范的设备,单片机通过是一个支持蓝牙Airsync协议 的模块,使用其中的通道指令进行通讯。

2. 基本知识

2.1 微信蓝牙外设是符合微信官方规定的蓝牙设备规范的蓝牙设备,其包括经典蓝牙和 4.0 BLE 蓝牙,目前支持 ios 和 andriod 两个系统。

2.2 微信硬件平台使用蓝牙作为近场控制的连接件,并拟定了《微信蓝牙外设协议》,这份协议像一个标准,用于规范微信和蓝牙外设之间的数据交互场景和接口。。

2.3 微信蓝牙物联是一种近场控制场景

微信硬件平台支持蓝牙和Wifi/3G/GPRS接入。蓝牙接入则是一种近场控制手段,用户只能利用微信通过手机的蓝牙来控制20米左右的蓝牙设备。也即是,当蓝牙设备离开手机蓝牙的连接范围,那么用户是控制不了该设备的。

对于蓝牙外设来说,手机就像一个蓝牙网关一样,手机通过蓝牙来跟蓝牙外设进行通信,将得到的数据通过手机的wifi或者3G/4G信号与云后端(微信公众平台、第三方云服务端)交互。前者是基于微信Airsync协议,后者则是微信制定的基于TCP/IP协议的《设备接入接口协议》。

3. 微信蓝牙硬件设备

3.1  服务UUID 和 读写特征和指示特征的UUID

名称                 值

ServiceUUID 0xFEE7(该 uuid 经蓝牙官方授权)

Write Characteristics UUID 0xFEC7

Indicate Characteristics UUID 0xFEC8

Read Characteristics UUID 0xFEC9Andriod RFCOMM UUID e5b152ed-6b46-09e9-4678-665e9a972cbc

3.2 蓝牙广播

3.2.1 广播模式

BLE 中有两种角色 Central 和 Peripheral,也就是中心设备和外围设备。中心设备可以主动连接外围设备,外围设备发送广播或者被中心设备连接。外围通过广播被中心设备发现,广播中带有外围设备自身的相关信息。

对于蓝牙设备来说,主要的状态是,包括未连接和已连接两种。

在未连接时,它需要进行广播。其广播的目的是为了让手机能够扫描蓝牙知到这个蓝牙设备是支持Airsync协议的设备。

那么,广播数据需要包含什么格式的数据才能被手机微信所识别到呢?这就是蓝牙Airsync协议规定的内容。

根据微信规范定义,

蓝牙普通广播包格式::manufature specific data 需以 MAC 地址(6 字节)结尾。

并且 manufature specific data 长度需大于等于 8 字节(最前两个字节为 company id,没有的话随便填)。

确认广播包:manufature specific data 需以下面格式结尾,

0xfe 0x01 0x01 + MAC 地址(6 字节)。并且 manufature specific data 长度需大于等于

8 字节(最前两个字节为 company id,没有的话随便填)。

3.2.2 BLE 蓝牙广播包

3.2.2.1 BLE广播概述

 BLE 连接过程中有三个重要的数据包:SCAN_REQ, SCAN_RSP 和 CONNECT_REQ。
 SCAN_REQ:  扫描请求,由主设备(MASTER DEVICE)向从设备(SLAVE DEVICE)发出,目的是为了获得从设备的响应以得到更多的从设备广播数据信息(包括设备名字,或者服务UUID,及其它如厂家特定格式的信息(如硬件版本,软件版本号,设备系列号等等)


SCAN_RSP:  从设备对就主设备发起的SCAN_REQ的响应,作为广播包的补充,从设备可以给主设备更多的广播数据,比如说,有些设备在广播包里面没有设备名字,这个时候就可以把设备名字放在这个包里面发给主设备


CONNECT_REQ:主设备向从设备发出连接请求。至此连接建立完成(从设备不会响应这个请求),如果从设备没有连接上面的问题的话,以后主从双方会开始相互交换有效数据(基于GAP,GATT及SMP协议)或者交换空包。
   
 

3.2.2.2 BLE 广播包报文结构 (摘:《ble 广播数据格式细致分析》)

BLE报文结构如下,他由下图所示的各个域组成。因为有的域的长度超过了一个字节,所以在传输的过程中就涉及到多字节域中哪个字节先传输的问题,BLE报文传输时的字节序和比特序如下:

  •  字节序:大多数多字节域是从低字节开始传输的。注意,并不是所有的多字节域都是从低字节开始传输的。
  • 比特序:各个字节传输时,每个字节都是从低位开始。

具体每个部分的详细解析可以查看《ble 广播数据格式细致分析》 这篇文章。

其中,本文关注PDU 中的数据段(AdvData)

  • 广播报文:长度域包含6个比特,有效值的范围是6~37。
  •  数据报文:长度域包含5个比特,有效值的范围是0~31。

  广播报文和和数据报文的长度域有所不同,主要原因是:广播报文除了最多31个字节的数据之外,还必须要包含6个字节的广播设备地址。6+31=37,所以需要6比特的长度域。

  再次强调:广播时必须要包含6个字节的广播设备地址。

3..2.2.3 数据(AdvData)

  广播和扫面响应的数据格式如下图所示,由有效数据部分和无效数据部分组成。

                                                         图8:广播和扫描响应的数据格式

  1)  有效数据部分:包含N个AD Structure,每个AD Structure由Length,AD Type和AD Data组成。其中:

  • Length:AD Type和AD Data的长度。
  • AD Type:指示AD Data数据的含义。

3.2.3.4  广播包可以在 Android 代码中可以使用 BluetoothAdapter 来发起扫描得到,基本用法如下:
BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback()
{
    @Override
    public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
        //其中,scanRecord 就是广播包的二进制数据
        //这个广播包,其位置是在, BLE 广播报文格式中的PDU(协议数据单元)中的AdvData 段,
        //而且,AdvData 段由有效数据部分和无效数据部分组成,
        //有效数据部分:包含N个AD Structure,每个AD Structure由Length,AD Type和AD Data组成。其中:

        //Length:AD Type和AD Data的长度。
        //AD Type:指示AD Data数据的含义。
    }
};

安卓蓝牙在扫描设备后,回调方法 onLeScan(...)中的参数 scanRecord 就是广播数据,这里同时包含广播数据扫描应答数据(均为31字节),所以长度一般就是 62 字节,BLE4.0规定,如果广播包和扫描应答包不足字节,则以0补齐.

3.2.2.5 广播数据格式

所有的 AD type 的定义在文档 ​Core Specification Supplement 中。 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,剩下的是厂商自己按照需求添加,里面的数据内容自己定义。

3.2.2.6  微信蓝牙设备广播包数据:

02 01 06 05 02 E7 FE E0 FF 09 FF FF FF  F3 3F 31 F3 FF 3F 0D 09 41 46 47 46 34 20 20 20 20 20 20 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 

上面蓝牙广播包中,包含广播包和应答包,各个AD Structure 解析如下:

1个AD Structure 02 01 06

Length

AD Type

AD Data

02

01

06

2字节

AD type为“Flag”

flag说明了物理连接功能,比如有限发现模式,不支持经典蓝牙等。

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: 预留。

2个AD Structure 05 02 E7 FE E0 FF 

Length

AD Type

AD Data

05

02

E7 FE E0 FF 

5字节

AD type为“SERVICE_UUID_MORE_AVAILABLE”

非完整的 16 bit UUID 列表

E7 FE 为 微信蓝牙硬件指定的服务UUID ,根据微信蓝牙外设协议介绍 (该 uuid 经蓝牙官方授权)

FF E0 为 另外一个服务 UUID

3个AD Structure 09 FF FF FF F3 3F 31 F3 FF 3F  

Length

AD Type

AD Data

09

FF

FF FF F3 3F 31 F3 FF 3F

9字节

AD type为“Manufacturer Specific Data”

 

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

根据微信蓝牙外设规定,

普通广播包:manufature specific data 需以 MAC 地址(6 字节)结尾。 并且 manufature

specific data 长度需大于等于 8 字节(最前两个字节为 company id,没有的话随便填)。

确认广播包:manufature specific data 需以下面格式结尾,

0xfe 0x01 0x01 + MAC 地址(6 字节)。 并且 manufature specific data 长度需大于等于

8 字节(最前两个字节为 company id,没有的话随便填)。

 

因此: FF FF F3 3F 31 F3 FF 3F  , FF FF 为厂商ID,   F3 3F 31 F3 FF 3F , 为蓝牙设备的MAC 地址

4个AD Structure 0D 09 41 46 47 46 34 20 20 20 20 20 20 20  

Length

AD Type

AD Data

0D

09

41 46 47 46 34 20 20 20 20 20 20 20

13字节

AD type为“完整的本地名称”

41 46 47 46 34 20 20 20 20 20 20 20  蓝牙名称的ASCII 码的16进制

以上就是微信蓝牙广播包解析。

参考文章

以蓝牙开发的视觉解读微信Airsync协议

ble 广播数据格式细致分析

BLE 广播数据解析

猜你喜欢

转载自blog.csdn.net/gd6321374/article/details/102558278