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

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

Фон

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

Припишите протокол

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

Типичный профиль атрибута

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

Терминология GATT:

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

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

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

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

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

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

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

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

В этом сценарии сервер GATT является повязкой на запястье с датчиком сердечного ритма, и клиент GATT является смартфоном.

% Create objects for GATT-server and GATT-client devices.
gattServer = helperBLEGATTServer;
gattClient = helperBLEGATTClient;

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

Сервисное открытие

Клиенты выполняют сервисную операцию открытия, чтобы получить информацию о доступных сервисах. В обслуживании открытие, клиент вызывает 'Discover all primary services' путем отправки Чтения PDU ATT запроса типа группы. Сервер отвечает доступными сервисами и их связанными указателями путем отправки 'Чтения PDU ATT' ответа типа группы. Указатель является уникальным идентификатором атрибута, которые динамически присвоены сервером.

Клиентский запрос о сервисах в Сервере

Функция 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;

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

Сервер получает Чтение по запросу типа группы от клиента и отправляет список доступных сервисов в Чтении PDU ATT ответа типа группы.

receiveData функция декодирует входящий PDU как сервер GATT и возвращает соответствующий объект настройки PDU ATT и соответствующий 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 и возвращает соответствующий объект настройки PDU 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.
[~, 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' путем отправки 'Считанный PDU ATT' запроса типа. Сервер отвечает доступными характеристиками и их связанными указателями путем отправки 'Чтения PDU ATT' ответа типа.

Клиентский запрос о характеристиках в Сервере

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

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

Декодирует полученный запрос, и возвратите список доступных характеристик в Чтении PDU ATT ответа типа.

% 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' путем отправки 'информационного PDU ATT' запроса. Сервер отвечает доступными характеристическими дескрипторами и их связанными указателями путем отправки 'информационного PDU ATT' ответа.

Клиентский запрос о характеристических дескрипторах в Сервере

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

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

Декодирует полученный запрос и возвращает список доступных характеристических дескрипторов в информационном PDU ATT ответа.

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

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

Декодирует полученный запрос и отправляет ответ в PDU ATT ответа Записи.

% 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

Экспортируйте сгенерированные пакеты в пакетное получение (PCAP) файл. Функция помощника helperBLEExportToPCAP генерирует файл PCAP, содержащий пакеты слоя ссылки BLE, сгенерированные в этом примере.

% Export all the generated packets to PCAP format.
helperBLEExportToPCAP(pcapPackets, 'bleHRP.pcap');

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 PDUs

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

  • Сервисный запрос открытия

  • Сервисный ответ открытия

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

Заключение

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

Приложение

Можно далее исследовать следующее, генерируют и декодируют функции, а также классы настройки:

Выбранная библиография

  1. Спецификация v5.0 Ядра Bluetooth, 06 декабря 2016.

  2. Спецификация v10 Профиля Сердечного ритма, 12 июля 2011 от BLE Принятые спецификации профиля GATT

  3. Программное обеспечение Wireshark: https://www.wireshark.org/