В этом примере показано моделирование устройств Bluetooth ® с низким энергопотреблением с профилем частоты сердечных сокращений с использованием библиотеки Communications Toolbox™ Library для протокола Bluetooth ®.
Спецификация ядра Bluetooth [1] включает версию Low Energy для низкоскоростных беспроводных персональных сетей, которая называется Bluetooth Low Energy (BLE) или Bluetooth Smart. Стек BLE состоит из: Generic Attribute Profile (GATT), Attribute Protocol (ATT), Security Manager Protocol (SMP), Logical Link Control and Adaptation Protocol (L2CAP), канального уровня (LL) и физического уровня (PH). BLE был добавлен в стандарт для устройств с низким энергопотреблением, генерирующих небольшие объемы данных, таких как уведомления, используемые в таких приложениях, как домашняя автоматизация, здравоохранение, фитнес и Интернет вещей (IoT).

ATT построен поверх L2CAP слоя BLE. ATT определяет набор протокольных блоков данных (PDU), которые используются для обмена данными в профилях на основе GATT.

GATT - это инфраструктура услуг, построенная с использованием ATT. GATT обрабатывает генерацию запросов или ответов на основе данных приложений от более высоких уровней или ATT PDU, принятых от более низкого уровня. Она хранит информацию в виде сервисов, признаков и дескрипторов признаков. Он использует архитектуру клиент-сервер.
Терминология ГАТТ:
Сервис: Сервис - это совокупность данных и связанных с ними вариантов поведения для выполнения определенной функции или функции. Пример: Служба сердечного ритма, которая позволяет измерять сердечный ритм.
Признак: Признак - это значение, используемое в службе вместе с ее разрешениями. Пример: Характеристика измерения сердечного ритма содержит информацию об измеренном значении сердечного ритма.
Дескриптор характеристики: Дескрипторы поведения характеристики. Пример: Дескриптор конфигурации характеристик клиента (CCCD) описывает, должен ли сервер уведомлять клиента в ответе, содержащем значение характеристики.
GATT-Client: Инициирует команды и запросы на сервер и получает ответы, указания и уведомления, отправленные сервером.
GATT-Server: принимает входящие команды и запросы от клиента и отправляет ответы, указания и уведомления клиенту.

Профиль частоты сердечных сокращений
Профиль частоты сердечных сокращений (HRP) [2] - низкоэнергетический профиль на основе GATT, определяемый Bluetooth Special Interest Group (SIG). HRP определяет связь между GATT-сервером устройства датчика частоты сердечных сокращений, такого как браслет, и GATT-клиентом, таким как смартфон или планшет. HRP широко используется в фитнес-приложениях для сбора измерений сердечного ритма.
% Check if the 'Communications Toolbox Library for the Bluetooth Protocol' % support package is installed or not. commSupportPackageCheck('BLUETOOTH');
В этом сценарии GATT-сервер представляет собой браслет с датчиком сердечного ритма, а GATT-клиент - смартфон.
% Create objects for GATT-server and GATT-client devices.
gattServer = helperBLEGATTServer;
gattClient = helperBLEGATTClient;
Первоначально клиент HRP обнаруживает службы, характеристики, дескрипторы характеристик, определенные на сервере. После обнаружения клиент подписывается на уведомления об измерении частоты сердечных сокращений.
Клиенты выполняют операцию обнаружения службы, чтобы получить информацию о доступных службах. При обнаружении службы клиент вызывает 'Discover all primary services' путем отправки запроса типа Read by group ATT PDU. Сервер отвечает доступными службами и связанными с ними дескрипторами, посылая ответ ATT PDU «Read by group type». Дескриптор - это уникальный идентификатор атрибута, который динамически назначается сервером.
Запрос клиента на услуги на сервере
Функция generateATTPDU генерирует блок ATT PDU, соответствующий данной процедуре, как указано в спецификации ядра Bluetooth.
% Preallocate a variable to store the generated link layer packets. pcapPackets = cell(1, 9); count = 1; % Configure a GATT client to discover services available at the server. gattClient.SubProcedure = 'Discover all primary services'; serviceDiscReqPDU = generateATTPDU(gattClient); % Transmit the application data (|serviceDiscReqPDU|) to the server through % PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(serviceDiscReqPDU); count = count+1;
Получить запрос клиента на сервере
Сервер получает запрос типа Read by group от клиента и посылает список доступных услуг в ответ ATT PDU типа Read by group.
Функция receiveData декодирует входящий PDU как GATT-сервер и возвращает соответствующий объект конфигурации ATT PDU и соответствующий ответный PDU.
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode the received ATT PDU and generate response PDU, if applicable. [attServerRespPDU, serviceDiscReqCfg, gattServer] = receiveData(gattServer, receivedPDU); fprintf("Received service discovery request at the server:\n") serviceDiscReqCfg % Transmit the application response data (|attServerRespPDU|) to the client % through PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(attServerRespPDU); count = count+1;
Received service discovery request at the server:
serviceDiscReqCfg =
bleATTPDUConfig with properties:
Opcode: 'Read by group type request'
StartHandle: '0001'
EndHandle: 'FFFF'
AttributeType: '2800'
Получить ответ сервера на клиенте
Функция receiveData декодирует входящий PDU как GATT-клиент и возвращает соответствующий объект конфигурации ATT PDU и соответствующий ответный PDU, если применимо.
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [~, serviceDiscRespCfg] = receiveData(gattClient, receivedPDU); gattClient.StartHandle = serviceDiscRespCfg.StartHandle; gattClient.EndHandle = serviceDiscRespCfg.EndHandle; % Expected response from the server: |'Read by group type response'| or % |'Error response'|. if strcmp(serviceDiscRespCfg.Opcode, 'Error response') fprintf("Received error response at the client:\n") serviceDiscRespCfg serviceDiscRespMsg = ['Error response(''' serviceDiscRespCfg.ErrorMessage ''')']; else fprintf("Received service discovery response at the client:\n") serviceDiscRespCfg service = helperBluetoothID.getBluetoothName(serviceDiscRespCfg.AttributeValue); serviceDiscRespMsg = ['Service discovery response(''' service ''')']; end
Received service discovery response at the client:
serviceDiscRespCfg =
bleATTPDUConfig with properties:
Opcode: 'Read by group type response'
StartHandle: '0001'
EndHandle: '0006'
AttributeValue: [2x2 char]
Услуга состоит из нескольких признаков. Для каждой службы существуют информационные элементы, которыми обмениваются клиент и сервер. Каждый информационный элемент может содержать дескрипторы его поведения. Характеристика содержит значение и связанные с ним дескрипторы. После обнаружения службы клиенты выполняют обнаружение характеристик, чтобы узнать о характеристиках, определенных в службе. При обнаружении признаков клиент вызывает 'Discover all characteristics of service' путем отправки блока ATT PDU «Read by type request». Сервер отвечает доступными характеристиками и связанными с ними дескрипторами, посылая ответ ATT PDU «Read by type».
Клиентский запрос характеристик на сервере
% Configure a GATT client to discover all the available characteristics at % the server. gattClient.SubProcedure = 'Discover all characteristics of service'; chrsticDiscReqPDU = generateATTPDU(gattClient); % Transmit the application data (|chrsticDiscReqPDU|) to the server through % PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(chrsticDiscReqPDU); count = count+1;
Получить запрос клиента на сервере
Декодирует принятый запрос и возвращает список доступных характеристик в ATT PDU ответа Read by type.
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [chrsticDiscRespPDU, chrsticDiscReqCfg, gattServer] = receiveData(gattServer, receivedPDU); fprintf("Received characteristic discovery request at the server:\n") chrsticDiscReqCfg % Transmit the application response data (|chrsticDiscRespPDU|) to the % client through PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(chrsticDiscRespPDU); count = count+1;
Received characteristic discovery request at the server:
chrsticDiscReqCfg =
bleATTPDUConfig with properties:
Opcode: 'Read by type request'
StartHandle: '0001'
EndHandle: '0006'
AttributeType: '2803'
Получить ответ сервера на клиенте
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [~, chrsticDiscRespCfg] = receiveData(gattClient, receivedPDU); % Expected response from the server: |'Read by type response'| or |'Error % response'|. if strcmp(chrsticDiscRespCfg.Opcode, 'Error response') fprintf("Received error response at the client:\n") chrsticDiscRespCfg chrsticDescRespMsg = ['Error response(''' chrsticDiscRespCfg.ErrorMessage ''')']; else fprintf("Received characteristic discovery response at the client:\n") attributeValueCfg = helperBLEDecodeAttributeValue(... chrsticDiscRespCfg.AttributeValue, 'Characteristic'); attributeValueCfg chrsticDescRespMsg = ['Characteristic discovery response(''' attributeValueCfg.CharacteristicType ''')']; end
Received characteristic discovery response at the client:
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: 'Heart rate measurement'
Характеристика может состоять из множества дескрипторов характеристик. После обнаружения характеристики клиенты выполняют обнаружение дескрипторов характеристик, чтобы узнать о списке дескрипторов и их дескрипторах. При обнаружении дескриптора характеристики клиент вызывает 'Discover all descriptors' отправкой «информационного запроса» ATT PDU. Сервер отвечает доступными дескрипторами характеристик и связанными с ними дескрипторами, посылая ATT PDU «информационного ответа».
Запрос клиента на дескрипторы характеристик на сервере
% Configure a GATT client to discover all the available characteristic % descriptors at the server. gattClient.SubProcedure = 'Discover all descriptors'; gattClient.StartHandle = dec2hex(hex2dec(chrsticDiscRespCfg.AttributeHandle)+1, 4); chrsticDescDiscReqPDU = generateATTPDU(gattClient); % Transmit the application data (|chrsticDescDiscReqPDU|) to the client % through PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(chrsticDescDiscReqPDU); count = count+1;
Получить запрос клиента на сервере
Декодирует принятый запрос и возвращает список доступных дескрипторов характеристик в ATT PDU информационного ответа.
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [chrsticDescDiscRespPDU, chrsticDescDiscReqCfg, gattServer] = receiveData(gattServer, receivedPDU); fprintf("Received characteristic descriptor discovery request at the server:\n") chrsticDescDiscReqCfg % Transmit the application response data (|chrsticDescDiscRespPDU|) to the % client through PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(chrsticDescDiscRespPDU); count = count+1;
Received characteristic descriptor discovery request at the server:
chrsticDescDiscReqCfg =
bleATTPDUConfig with properties:
Opcode: 'Information request'
StartHandle: '0003'
EndHandle: '0006'
Получить ответ сервера на клиенте
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [~, chrsticDescDiscRespCfg] = receiveData(gattClient, receivedPDU); % Expected response from the server: |'Information response'| or |'Error % response'|. if strcmp(chrsticDescDiscRespCfg.Opcode, 'Error response') fprintf("Received error response at the client:\n") chrsticDescDiscRespCfg chrsticDescDiscRespMsg = ['Error response(''' chrsticDescDiscRespCfg.ErrorMessage ''')']; else fprintf("Received characteristic descriptor discovery response at the client:\n") chrsticDescDiscRespCfg descriptor = helperBluetoothID.getBluetoothName(chrsticDescDiscRespCfg.AttributeType); chrsticDescDiscRespMsg = ['Characteristic descriptor discovery response(''' descriptor ''')']; end
Received characteristic descriptor discovery response at the client:
chrsticDescDiscRespCfg =
bleATTPDUConfig with properties:
Opcode: 'Information response'
Format: '16 bit'
AttributeHandle: '0004'
AttributeType: '2902'
После обнаружения дескрипторов характеристик клиент может включать или отключать уведомления для его значения характеристики. Чтобы включить уведомления, клиент должен установить бит уведомления (первый бит) значения дескриптора конфигурации характеристик клиента (CCCD) путем вызова 'Write characteristic value' подпроцесса.
Подписка клиента на уведомления на сервере
% Configure a GATT client to enable the notifications of Heart rate % measurement characteristic. gattClient.SubProcedure = 'Write characteristic value'; gattClient.AttributeHandle = chrsticDescDiscRespCfg.AttributeHandle; gattClient.AttributeValue = '0100'; enableNotificationReqPDU = generateATTPDU(gattClient); % Transmit the application data (|enableNotificationReqPDU|) to the client % through PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(enableNotificationReqPDU); count = count+1;
Получить запрос клиента на сервере
Декодирует принятый запрос и посылает ответ в ответ записи ATT PDU.
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [enableNotificationRespPDU, enableNotificationReqCfg, gattServer] = receiveData(gattServer, receivedPDU); fprintf("Received enable notification request at the server:\n") enableNotificationReqCfg % Transmit the application response data (|enableNotificationRespPDU|) to % the client through PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(enableNotificationRespPDU); count = count+1;
Received enable notification request at the server:
enableNotificationReqCfg =
bleATTPDUConfig with properties:
Opcode: 'Write request'
AttributeHandle: '0004'
AttributeValue: [2x2 char]
Получить ответ сервера на клиенте
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [~, enableNotificationRespCfg] = receiveData(gattClient, receivedPDU); % Expected response from the server: |'Write response'| or |'Error % response'|. if strcmp(enableNotificationRespCfg.Opcode, 'Error response') fprintf("Received error response at the client:\n") enableNotificationRespCfg enableNotificRespMsg = ['Error response(''' enableNotificationRespCfg.ErrorMessage ''')']; else fprintf("Received enable notification response at the client:\n") enableNotificationRespCfg enableNotificRespMsg = 'Notifications enabled(''Heart rate measurement '')'; end
Received enable notification response at the client:
enableNotificationRespCfg =
bleATTPDUConfig with properties:
Opcode: 'Write response'
Когда клиент включает уведомления для характеристики, сервер периодически уведомляет клиента о значении характеристики (измерение частоты сердечных сокращений).
Сервер HRP уведомляет об измерении частоты сердечных сокращений клиента после его подписки.
Сервер отправляет уведомления клиенту
Функция notifyHeartRateMeasurement генерирует PDU уведомления, как указано в спецификации ядра Bluetooth.
% Reset the random number generator seed. rng default % Measure heart rate value using sensor (generate a random number for heart % rate measurement value). heartRateMeasurementValue = randi([65 95]); % Notify the heart rate measurement. [gattServer, notificationPDU] = notifyHeartRateMeasurement(gattServer, ... heartRateMeasurementValue); % Transmit the application data (|notificationPDU|) to the client through % PHY. [bleWaveform, pcapPackets{count}] = helperBLETransmitData(notificationPDU); count = count+1;
Получать уведомления сервера на клиенте
% Decode the received BLE waveform and retrieve the application data. receivedPDU = helperBLEDecodeData(bleWaveform); % Decode received ATT PDU and generate response PDU, if applicable. [~, notificationCfg] = receiveData(gattClient, receivedPDU); fprintf("Received notification at the client:\n") % Decode the received heart rate measurement characteristic value. heartRateCharacteristicValue = helperBLEDecodeAttributeValue(... notificationCfg.AttributeValue, 'Heart rate measurement'); heartRateCharacteristicValue heartRateMeasurementValue = heartRateCharacteristicValue.HeartRateValue; % Visualize the BLE GATT Client-Server model. helperBLEVisualizeHRPFrame(serviceDiscRespMsg, chrsticDescRespMsg, ... chrsticDescDiscRespMsg, enableNotificRespMsg, heartRateMeasurementValue);
Received notification at the client:
heartRateCharacteristicValue =
helperBLEAttributeValueConfig with properties:
AttributeType: 'Heart rate measurement'
HeartRateValueFormat: 'UINT8'
SensorContactStatus: 'Contact detected'
EnergyExpendedFieldFlag: 'Present, Units: Kilo Joules'
RRIntervalFieldFlag: 'Present'
HeartRateValue: 90
EnergyExpended: 100
RRInterval: 10

В этом примере используется blePCAPWriter объект для экспорта созданных PDU в файл с расширением .pcap или .pcapng. Для анализа и визуализации этого файла используйте анализатор пакетов третьей части, такой как Wireshark.
Создание объекта типа blePCAPWriter и укажите имя файла захвата пакетов.
% Create the BLE PCAP Writer file object pcapObj = blePCAPWriter("FileName", "bleHRP");
Используйте write для записи всех PDU BLE LL в файл PCAP. Константа timestamp определяет время захвата PDU. В этом примере время захвата одинаково для всех PDU.
timestamp = 124800; % timestamp (in microseconds) % Write all the LL PDUs to the PCAP file for idx = 1:numel(pcapPackets) write(pcapObj, pcapPackets{idx}, timestamp, "PacketFormat", "bits"); end % Clear the object clear pcapObj; fprintf("Open generated pcap file 'bleHRP.pcap' in a protocol analyzer to view the generated frames.\n")
Open generated pcap file 'bleHRP.pcap' in a protocol analyzer to view the generated frames.
Поскольку сгенерированные пакеты профиля частоты сердечных сокращений соответствуют стандарту Bluetooth, можно открыть, проанализировать и визуализировать файл PCAP с помощью стороннего анализатора пакетов, такого как Wireshark [3]. Данные, показанные на этих рисунках, используют пакеты профиля частоты сердечных сокращений, сгенерированные в этом примере.
Запрос на обнаружение службы

Ответ на обнаружение службы

Уведомление значения измерения частоты сердечных сокращений

В этом примере показано моделирование устройств BLE с профилем частоты сердечных сокращений с использованием сценария GATT клиент-сервер, как указано в спецификации ядра Bluetooth [1]. Для просмотра сгенерированных кадров можно использовать анализатор пакетов.
В примере используются следующие функции:
bleATTPDUConfigСоздание объекта конфигурации для BLE ATT PDU
bleATTPDU: Формирование блока распределения питания BLE ATT
bleATTPDUDecodeДекодирование BLE ATT PDU
blePCAPWriter: Создание объекта записи файлов BLE PCAP или PCAPNG
В примере используются следующие помощники:
helperBLEGATTClient: Предоставляет методы для профиля Generic Attribute
helperBLEGATTServer: Создание объекта сервера GATT
helperBLATEttribureStartConfig: Создание объекта конфигурации для значения атрибута BLE
helperBLEGenerateAttribureValue: создание значения атрибута BLE
helperBLEDecateAttribityValue: декодер значений атрибутов BLE
helperBLEDecaseData: Декодирует полученную форму сигнала и извлекает данные приложения
helperBLEPrependStartAddress: добавляет PDU канального уровня с адресом доступа
helperBLETransmitData: Передача данных приложения путем генерации формы сигнала BLE
helperBluetootID: идентификаторы Bluetooth и их имена присваиваются Группой специальных интересов Bluetooth (SIG)
helperBLEVisualityHRPFrame: визуализация кадров профиля сердечного ритма (HRP), обмен которыми осуществляется в HRP Example
helperBLEPlotHRPFrames: Постройте график обмена кадрами данных между сервером профиля частоты сердечных сокращений и клиентом
Веб-сайт технологии Bluetooth ®. «Веб-сайт Bluetooth Technology | Официальный веб-сайт Bluetooth Technology». Доступ состоялся 8 июля 2020 года. https://www.bluetooth.com/.
«Development/LibpcapFileFormat - Wiki Wiki Wieshark». Доступ состоялся 8 июля 2020 года. https://wiki.wireshark.org/Development/LibpcapFileFormat.
Группа, Tcpdump. «Общий репозиторий Tcpdump/Libpcap». Доступ состоялся 8 июля 2020 года. https://www.tcpdump.org.