主要内容

基于心率谱的蓝牙LE设备建模

本示例向您展示如何使用蓝牙®工具箱使用心率配置文件(HRP)对蓝牙®低能(LE)设备建模。

使用这个例子,你可以:

  • 创建并配置蓝牙LE HRP客户端-服务器场景,其中智能手机作为客户端,带心率传感器的腕带作为服务器。

  • 配置客户端进行业务发现和特征发现。

  • 配置客户端以允许接收来自服务器的特性通知。

  • 将生成的pdu (protocol data units)导出到文件.pcap扩展。

  • 使用第三方数据包分析器(如Wireshark)将生成的pdu可视化[4].

背景

蓝牙核心规范[2]包括用于低速率无线个人区域网络的低能耗版本,称为低能耗蓝牙(蓝牙LE)或智能蓝牙。蓝牙LE协议栈包括:GATT (Generic Attribute Profile)、ATT (Attribute Protocol)、SMP (Security Manager Protocol)、L2CAP (Logical Link Control and Adaptation Protocol)、LL (Link Layer)和PHY (Physical Layer)。蓝牙LE被添加到生成少量数据的低能耗设备标准中,例如用于家庭自动化、医疗保健、健身和物联网(IoT)等应用程序的通知警报。

属性的协议

ATT构建在蓝牙LE的L2CAP层之上。ATT定义了一组协议数据单元(pdu),用于基于ATT的配置文件中的数据交换。

通用属性概要

GATT是基于ATT协议构建的业务框架,根据上层的应用数据或下层接收到的ATT PDU处理请求或响应的生成。它以服务、特征和特征描述符的形式存储信息。它使用客户机-服务器体系结构。

关贸总协定的术语:

  • 服务:服务是完成特定功能或特性的数据和相关行为的集合。示例:允许测量心率的心率服务。

  • 特点:特征是服务中使用的值及其权限。例如:心率测量特征包含有关所测量的心率值的信息。

  • 特征描述符:特征行为的描述符。例如:客户端特征配置描述符(CCCD),描述服务器是否必须在包含特征值的响应中通知客户端。

  • GATT-Client:向服务器发起命令和请求,并接收服务器发送的响应、指示和通知。

  • GATT-Server:接受来自客户端的传入命令和请求,并向客户端发送响应、指示和通知。

心率剖面

心率谱[3.]是蓝牙特殊兴趣小组(SIG)定义的基于gatt的低能量配置文件。HRP定义了心率传感器设备(如腕带)的gatt服务器和智能手机、平板电脑等gatt客户端之间的通信。HRP在健身应用中广泛用于收集心率测量。

Bluetooth LE HRP Client-Server场景

在此场景中,gatt服务器是带心率传感器的腕带,gatt客户端是智能手机。

为gatt服务器和gatt客户端设备创建对象gattServer = helperBLEGATTServer;gatclient = helperBLEGATTClient;

最初,HRP客户端发现服务器上定义的服务、特征和特征描述符。发现后,客户端订阅心率测量通知。

服务发现

客户端执行服务发现操作以获取有关可用服务的信息。在服务发现中,客户端调用“发现所有主要服务”通过发送按组类型请求读取攻击力PDU。服务器通过发送一个“按组类型读取响应”ATT PDU来响应可用的服务及其相关句柄。一个处理是由服务器动态分配的属性的唯一标识符。

客户端请求服务器上的服务

generateATTPDU对象函数生成一个ATT PDU,对应于蓝牙核心规范中指定的给定子过程。

预分配一个变量存储生成的链路层报文pcapPackets = cell(1,9);Count = 1;配置GATT客户端发现服务器上可用的服务gattClient。子过程=“发现所有主要服务”;service离散qpdu = generateATTPDU(gatclient);%将应用数据(| service离散qpdu |)通过% PHY[ble波形,pcapPackets{count}] = helperBLETransmitData(service离散qpdu);Count = Count +1;

在服务器接收客户端请求

服务器接收一个按组类型请求读取类中发送可用服务的列表按组类型响应读取攻击力PDU。

receiveData对象函数将传入的PDU解码为GATT-server,并返回相应的ATT PDU配置对象和相应的响应PDU。

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[attServerRespPDU, serviceDiscReqCfg, gattServer] = receiveData(gattServer, receivedPDU);流("服务器收到的服务发现请求:\n"
服务器端收到的服务发现请求:
serviceDiscReqCfg
serviceDiscReqCfg = bleATTPDUConfig with properties: Opcode: '按组类型请求读取' StartHandle: '0001' EndHandle: 'FFFF' AttributeType: '2800'
%向客户端发送应用响应数据(|attServerRespPDU|)通过PHY的百分比[ble波形,pcapPackets{count}] = helperBLETransmitData(attServerRespPDU);Count = Count +1;

在客户端接收服务器响应

receiveData对象函数将传入的PDU解码为gatt客户端,并返回相应的ATT PDU配置对象和适当的响应PDU(如果适用的话)。

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[~, service离散spcfg] = receiveData(gatclient, receivedPDU);gattClient。StartHandle = servicedisspcfg .StartHandle;gattClient。EndHandle = service离散spcfg .EndHandle;%期望服务器响应:|'按组类型读取响应'|或% |'错误响应'| . %如果比较字符串(serviceDiscRespCfg。操作码,“错误响应”)流("在客户端收到错误响应:\n") service离散spcfg service离散spmsg = [“错误响应(“”serviceDiscRespCfg。ErrorMessage“‘)’];其他的流("客户端收到的服务发现响应:\n") service离散spcfg service = helperBluetoothID.getBluetoothName(service离散spcfg . attributevalue);service离散spmsg = [服务发现响应(")服务“‘)’];结束
客户端收到的服务发现响应:
serviceDiscRespCfg = bleATTPDUConfig with properties: Opcode: '按组类型响应读取' StartHandle: '0001' EndHandle: '0006' AttributeValue: [2x2 char]

特征发现

服务由多个特征组成。对于每个服务,客户机和服务器之间都有信息元素交换。每个信息元素都可以包含其行为的描述符。一个特征包含一个值及其相关的描述符。发现服务后,客户端执行特征发现了解服务中定义的特征。在特征发现中,客户端调用“发现服务的所有特征”通过发送“按类型读取请求”ATT PDU。服务器通过发送一个“按类型读取响应”ATT PDU来响应可用的特征及其相关句柄。

客户端请求服务器的特性

配置GATT客户端以发现所有可用的特性%服务器gattClient。子过程=“发现服务的所有特征”;chrstic离散qpdu = generateATTPDU(gatclient);%发送应用数据(| chrstic离散qpdu |)到服务器% PHY[ble波形,pcapPackets{count}] = helperBLETransmitData(chrsticdiscrete qpdu);Count = Count +1;

在服务器接收客户端请求

解析接收到的请求并返回可用特征的列表按类型响应读取攻击力PDU。

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[chrsticdissppdu, chrsticdisqcfg, gattServer] = receiveData(gattServer, receivedPDU);流("已收到服务器上的特征发现请求:\n"
服务器端收到的特征发现请求:
chrsticDiscReqCfg
chrsticdisqcfg = bleATTPDUConfig with properties: Opcode: '按类型请求读取' StartHandle: '0001' EndHandle: '0006' AttributeType: '2803'
将应用程序响应数据(| chrsticdissppdu |)发送到%客户端通过PHY[ble波形,pcapPackets{count}] = helperBLETransmitData(chrsticdissppdu);Count = Count +1;

在客户端接收服务器响应

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[~, chrsticdisspcfg] = receiveData(gatclient, receivedPDU);%期望服务器响应:|'读取类型响应'|或|'错误%的回答让|如果比较字符串(chrsticDiscRespCfg。操作码,“错误响应”)流("在客户端收到错误响应:\n") chrsticDescRespMsg = [“错误响应(“”chrsticDiscRespCfg。ErrorMessage“‘)’];其他的流("客户端收到的特征发现响应:\n") attributeValueCfg = helperBLEDecodeAttributeValue(...chrsticDiscRespCfg。AttributeValue,“特征”);attributeValueCfg chrsticDescRespMsg = [“特征发现响应(")”attributeValueCfg。CharacteristicType“‘)’];结束
在客户端收到的特征发现响应:
attributeValueCfg = helperBLEAttributeValueConfig with properties: AttributeType: 'Characteristic' BroadcastFlag: 'False' ReadFlag: 'False' WriteWithoutResponseFlag: 'False' WriteFlag: 'False' NotifyFlag: 'True' IndicateFlag: 'False' AuthenticatedSignedWritesFlag: 'False' ExtendedPropertiesFlag: 'False' CharacteristicValueHandle: '0003' CharacteristicType: '心率测量'

特征描述符发现

一个特征可以由多个特征描述符组成。发现特征后,客户端执行特征描述符发现要了解描述符及其句柄的列表。在特征描述符发现中,客户端调用“发现所有描述符”通过发送“信息请求”ATT PDU。服务器通过发送一个“信息响应”ATT PDU来响应可用的特征描述符及其相关句柄。

客户端请求服务器上的特征描述符

配置GATT客户端发现所有可用特性%描述符gattClient。子过程=“发现所有描述符”;gattClient。StartHandle = dec2hex(hex2dec(chrsticdisspcfg . attributehandle)+ 1,4);chrsticdesc离散qpdu = generateATTPDU(gatclient);%向客户端发送应用数据(| chrsticdesc离散qpdu |)通过PHY的百分比[ble波形,pcapPackets{count}] = helperBLETransmitData(chrsticDescDiscReqPDU);Count = Count +1;

在服务器接收客户端请求

类中的可用特征描述符列表信息的反应攻击力PDU。

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[chrsticdesc离散sppdu, chrsticdesc离散qcfg, gattServer] = receiveData(gattServer, receivedPDU);流("在服务器上收到的特征描述符发现请求:\n"
在服务器上收到的特征描述符发现请求:
chrsticDescDiscReqCfg
chrsticDescDiscReqCfg = bleATTPDUConfig with properties: Opcode: 'Information request' StartHandle: '0003' EndHandle: '0006'
将应用程序响应数据(| chrsticdesc离散sppdu |)发送到%客户端通过PHY[ble波形,pcapPackets{count}] = helperBLETransmitData(chrsticDescDiscRespPDU);Count = Count +1;

在客户端接收服务器响应

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[~, chrsticdesc离散spcfg] = receiveData(gatclient, receivedPDU);来自服务器的期望响应:|'信息响应'|或|'错误%的回答让|如果比较字符串(chrsticDescDiscRespCfg。操作码,“错误响应”)流("在客户端收到错误响应:\n") chrsticdesc离散spcfg chrsticdesc离散spmsg = [“错误响应(“”chrsticDescDiscRespCfg。ErrorMessage“‘)’];其他的流("在客户端收到的特征描述符发现响应:\n") chrsticdesc离散spcfg描述符= helperBluetoothID.getBluetoothName(chrsticdesc离散spcfg . attributetype);chrsticDescDiscRespMsg = [特征描述符发现响应("描述符“‘)’];结束
在客户端收到的特征描述符发现响应:
chrsticDescDiscRespCfg = bleATTPDUConfig with properties: Opcode: 'Information response' Format: '16 bit' AttributeHandle: '0004' AttributeType: '2902'

订阅通知

发现特征描述符后,客户端可以启用或禁用通知求它的特征值。要启用通知,客户端必须设置的通知位(第一个位)客户端特征配置描述符(CCCD)值,通过调用“写特征值”子过程。

客户端在服务器上订阅通知

配置GATT客户端启用心率通知%测量特性gattClient。子过程=“写特征值”;gattClient。一个ttributeHandle = chrsticDescDiscRespCfg.AttributeHandle; gattClient.AttributeValue =“0100”;enableNotificationReqPDU = generateATTPDU(gatclient);%向客户端发送应用数据(|enableNotificationReqPDU|)通过PHY的百分比[ble波形,pcapPackets{count}] = helperBLETransmitData(enableNotificationReqPDU);Count = Count +1;

在服务器接收客户端请求

对接收到的请求进行解码,并以写回应攻击力PDU。

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[enableNotificationRespPDU, enableNotificationReqCfg, gattServer] = receiveData(gattServer, receivedPDU);流("已收到服务器上的启用通知请求:\n"
在服务器上收到启用通知请求:
enableNotificationReqCfg
enableNotificationReqCfg = bleATTPDUConfig with properties: Opcode: '写请求' AttributeHandle: '0004' AttributeValue: [2x2 char]
发送应用响应数据(|enableNotificationRespPDU|)到%客户端通过PHY[ble波形,pcapPackets{count}] = helperBLETransmitData(enableNotificationRespPDU);Count = Count +1;

在客户端接收服务器响应

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[~, enableNotificationRespCfg] = receiveData(gatclient, receivedPDU);服务器期望的响应:|'写响应'|或|'错误%的回答让|如果比较字符串(enableNotificationRespCfg。操作码,“错误响应”)流("在客户端收到错误响应:\n") enablenotificrespcfg = [“错误响应(“”enableNotificationRespCfg。ErrorMessage“‘)’];其他的流("在客户端收到启用通知响应:\n") enableNotificationRespCfg =“启用通知(“心率测量”)”结束
在客户端收到启用通知响应:
enableNotificationRespCfg = bleATTPDUConfig with properties: Opcode: '写入响应'

通知客户心率测量值

当客户端为某个特性启用通知时,服务器会定期通知characteristic的值(心率测量)发给客户。

客户端订阅后,HRP服务器会通知客户端心跳测量结果。

服务器向客户端发送通知

notifyHeartRateMeasurement对象函数生成蓝牙核心规范中指定的通知PDU。

重置随机数生成器种子rng默认的使用传感器测量心率值(为心脏生成一个随机数%率测量值)heartratemmeasurementvalue = randi([65 95]);通知心率测量[gattServer, notificationPDU] = notifyheartratemmeasurement (gattServer, notificationPDU)...heartRateMeasurementValue);%通过发送应用数据(|notificationPDU|)到客户端% PHY[ble波形,pcapPackets{count}] = helperBLETransmitData(notificationPDU);Count = Count +1;

在客户端接收服务器通知

解码接收到的蓝牙LE波形并检索应用程序%的数据receivedPDU = helperBLEDecodeData(ble波形);解码接收到的ATT PDU并生成响应PDU(如果适用)[~, notificationCfg] = receiveData(gatclient, receivedPDU);流("已收到客户端通知:\n"
客户端收到通知:
解码接收到的心率测量特征值heartRateCharacteristicValue = helperBLEDecodeAttributeValue(...notificationCfg。AttributeValue,“心率测量”);heartRateCharacteristicValue
heartratecharteristicvalue = helperBLEAttributeValueConfig with properties: AttributeType: '心率测量' HeartRateValueFormat: 'UINT8' SensorContactStatus: '接触检测' EnergyExpendedFieldFlag: 'Present,单位:Kilo Joules' RRIntervalFieldFlag: 'Present' HeartRateValue: 90 energyexpenditure: 100 RRInterval: 10
heartRateMeasurementValue = heartRateCharacteristicValue.HeartRateValue;可视化蓝牙LE GATT客户-服务器模型helperBLEVisualizeHRPFrame (serviceDiscRespMsg chrsticDescRespMsg,...chrsticDescDiscRespMsg, enableNotificRespMsg, heartRateMeasurementValue);

图蓝牙LE心率配置文件包含11个轴对象。坐标轴对象1包含3个图像、文本类型的对象。坐标轴对象2包含2个图像、文本类型的对象。坐标轴对象3包含2个图像、文本类型的对象。坐标轴对象4包含2个图像、文本类型的对象。坐标轴对象5包含2个图像、文本类型的对象。坐标轴对象6包含2个图像、文本类型的对象。坐标轴对象7包含2个图像、文本类型的对象。坐标轴对象8包含2个图像、文本类型的对象。坐标轴对象9包含2个图像、文本类型的对象。 Axes object 10 contains 4 objects of type image, text. Axes object 11 contains 2 objects of type image, text.

导出到PCAP文件

这个例子使用了blePCAPWriter对象将生成的pdu导出到文件中.pcap扩展或.pcapng扩展。要分析和可视化此文件,请使用第三方数据包分析程序(如Wireshark)。

创建类型的对象blePCAPWriter并指定抓包文件名。

创建Bluetooth LE PCAP Writer文件对象pcapObj = blePCAPWriter(“文件名”“bluetoothLEHRP”);

使用对象函数将所有蓝牙LE LL pdu写入PCAP文件。常数时间戳PDU的捕获时间。本例中,所有pdu的捕获时间相同。

时间戳= 124800;%时间戳(微秒)%将所有的LL pdu写入PCAP文件idx = 1:numel(pcapPackets) write(pcapObj, pcapPackets{idx}, timestamp,“PacketFormat”“位”);结束%清除对象清晰的pcapObj;流("打开生成的pcap文件'bluetoothLEHRP。在协议分析器中查看生成的帧。\n"
打开生成的pcap文件‘bluetoothLEHRP。在协议分析器中查看生成的帧。

生成ATT pdu的可视化

由于生成的心率配置文件数据包符合蓝牙标准,您可以使用第三方数据包分析器(如Wireshark)打开、分析和可视化PCAP文件[4].这些图中显示的数据使用本例中生成的心率配置文件包。

  • 服务发现请求

  • 服务发现响应

  • 通知心率测量值

结论

此示例演示了使用蓝牙核心规范中指定的GATT客户端-服务器场景对具有心率配置文件的蓝牙LE设备建模[2].您可以使用包分析器来查看生成的帧。

附录

下面的例子使用了这些helper:

选定的参考书目

  1. Bluetooth®技术网站。“蓝牙技术网站|蓝牙技术官网。”2021年11月29日访问。https://www.bluetooth.com/。

  2. 蓝牙特别兴趣小组(SIG)。“蓝牙核心规范”5.3版。https://www.bluetooth.com/。

  3. 蓝牙特别兴趣小组(SIG)。“心率档案”1.0版。https://www.bluetooth.com/。

  4. 开发/LibpcapFileFormat - Wireshark Wiki2021年11月29日访问。https://www.wireshark.org

  5. 组,Tcpdump。“Tcpdump/Libpcap公共存储库。”2021年11月29日访问。https://www.tcpdump.org。

  6. Tuexen, M.“PCAP下一代(Pcapng)捕获文件格式。2021。https://www.ietf.org/。

另请参阅

功能

对象

相关的话题