Моделирование устройств BLE с профилем сердечного ритма

В этом примере показано моделирование устройств Bluetooth ® Low Energy с профилем сердечного ритма с помощью библиотеки Communications Toolbox™ для протокола Bluetooth ®.

Фон

Спецификация ядра Bluetooth [1] включает версию Low Energy для низкоскоростных беспроводных персональных сетей, которая упоминается как Bluetooth Low Energy (BLE) или Bluetooth Smart. Стек BLE состоит из: профиля типовых атрибутов (GATT), протокола атрибутов (ATT), протокола диспетчера безопасности (SMP), протокола логического управления Ссылки и адаптации (L2CAP), Ссылки Слоя (LL) и физического слоя (PHY). BLE был добавлен к стандарту для устройств с низким энергопотреблением, генерирующих небольшие объемы данных, таких как оповещения об уведомлениях, используемые в таких приложениях, как автоматизация дома, здравоохранение, фитнес и Интернет вещей (IoT).

Протокол атрибутов

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

Профиль типового атрибута

GATT является сервисной средой, созданной с использованием ATT. GATT обрабатывает генерацию запросов или ответов на основе данных приложения от более высоких слоев или PDU ATT, полученного от нижнего уровня. Он хранит информацию в виде сервисов, признаков и дескрипторов признаков. Он использует архитектуру клиент-сервер.

Терминология ГАТТ:

  • Сервис: Сервис является набором данных и связанного поведения для выполнения конкретной функции или функции. Пример: Служба сердечного ритма, которая позволяет измерять сердечный ритм.

  • Характеристика: Характеристика является значением, используемым в службе вместе с ее разрешениями. Пример: Характеристика измерения сердечного ритма содержит информацию об измеренном значении сердечного ритма.

  • Характеристический дескриптор: Дескрипторы характеристического поведения. Пример: Дескриптор строения характеристики клиента (CCCD), описывает, должен ли сервер уведомлять клиента в ответе, содержащем значение характеристики.

  • GATT-Client: инициирует команды и запросы к серверу и получает ответы, указания и уведомления, отправляемые сервером.

  • GATT-сервер: принимает входящие команды и запросы от клиента и отправляет ответы, показания и уведомления клиенту.

Профиль сердечного ритма

Профиль сердечного ритма (HRP) [2] является низкоэнергетическим профилем на основе GATT, заданным Bluetooth Special Interest Group (SIG). HRP определяет связь между сервером ГАТТ устройства датчика сердечного ритма, такого как повязка на запястье, и клиентом ГАТТ, таким как смартфон или планшет. HRP широко используется в фитнес-приложениях для сбора измерений сердечного ритма.

Проверка на установку пакета поддержки

% Check if the 'Communications Toolbox Library for the Bluetooth Protocol'
% support package is installed or not.
commSupportPackageCheck('BLUETOOTH');

Сценарий клиент-сервер BLE HRP

В этом сценарии 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 response». Указатель является уникальным идентификатором атрибута, который динамически назначается сервером.

Запрос клиента на услуги на сервере

Функция generateATTPDU генерирует PDU ATT, соответствующий данной подпроцессе, как указано в спецификации ядра 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' путем отправки 'Read by type request' ATT PDU. Сервер отвечает доступными характеристиками и связанными с ними указателями, отправляя ATT PDU 'Read by type response'.

Запрос клиента на характеристики на сервере

% 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;

Получение запроса клиента на сервере

Декодирует полученный запрос и возвращает список доступных характеристик в ответе типа Read by 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.
[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

Экспорт в файл PCAP

Этот пример использует 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.

Визуализация сгенерированных блоков ATT PDU

Поскольку сгенерированные пакеты профиля сердечного ритма соответствуют стандарту Bluetooth, можно открыть, проанализировать и визуализировать файл PCAP с помощью стороннего анализатора пакетов, такого как Wireshark [3]. Данные, показанные на этих рисунках, используют пакеты профиля сердечного ритма, сгенерированные в этом примере.

  • Запрос на обнаружение службы

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

  • Уведомление о значении измерения сердечного ритма

Заключение

Этот пример продемонстрировал моделирование устройств BLE с профилем сердечного ритма с помощью сценария клиент-сервер GATT, как указано в спецификации ядра Bluetooth [1]. Можно использовать анализатор пакетов, чтобы просмотреть сгенерированные системы координат.

Приложение

В примере используются следующие функции:

  • bleATTPDUConfig: Создайте объект строения для PDU BLE ATT

  • bleATTPDU: BLE ATT PDU генерация

  • bleATTPDUDecode: BLE ATT PDU декодирование

  • blePCAPWriter: Создайте BLE PCAP или PCAPNG файл средства записи объект

В примере используются следующие помощники:

  • helperBLEGATTClient: предоставляет методы в профиль типового атрибута

  • helperBLEGATTServer: Создает объект сервера GATT

  • helperBLEAttributeValueConfig: создайте объект строения для значения атрибута BLE

  • helperBLEGenerateAttributeValue: генерация значений атрибута BLE

  • helperBLEDecodeAttributeValue: декодер значений атрибутов BLE

  • helperBLEDecodeData: Декодирует полученный сигнал и извлекает данные приложения

  • helperBLEPrependAccessAddress: заполняет PDU канального слоя адресом доступа

  • helperBLETransmitData: Передайте данные приложения путем генерации волны BLE

  • helperBluetoothID: идентификаторы Bluetooth и их имена, присвоенные Bluetooth Special Interest Group (SIG)

  • helperBLEVisualizeHRPFrame: Визуализация систем координат профиля сердечного ритма (HRP), обмененных в примере HRP.

  • helperBLEPlotHRPFrames: постройте график обмена системами координат данных между сервером профиля сердечного ритма и клиентом

Избранная библиография

  1. Веб-сайт Bluetooth ® Technology. Bluetooth Technology Website | Официальный сайт Bluetooth Technology. Доступ к 8 июля 2020 года. https://www.bluetooth.com/.

  2. «Разработка/LibpcapFileFormat - Wireshark Wiki». Доступ к 8 июля 2020 года. https://wiki.wireshark.org/Development/LibpcapFileFormat.

  3. Группа, The Tcpdump. «Общий репозиторий Tcpdump/Libpcap». Доступ к 8 июля 2020 года. https://www.tcpdump.org.

Похожие темы