Значение сердечного ритма в BLE

Мне трудно получить действительное значение из характеристик HR. Я явно неправильно обрабатываю значения в Dart.

Пример данных:

List<int> value = [22, 56, 55, 4, 7, 3];

Поле флагов: Я преобразовываю первый элемент в основном массиве байтов в двоичный, чтобы получить флаги

22 = 10110 (as binary)

это заставляет меня поверить, что это U16 (бит [0] == 1)

Значение ЧСС:

Поскольку он 16-битный, я пытаюсь получить байты в индексах 1 и 2. Затем я пытаюсь буферизовать их в ByteData. Оттуда я конвертирую их в Uint16 с Endian, установленным на Little. Это дает мне значение 14136. Очевидно, я упускаю что-то фундаментальное в том, как это должно работать.

Буду очень признателен за любую помощь в прояснении того, что я не понимаю в том, как обрабатывать 16-битные значения BLE.

Спасибо.

  /*
Constructor - constructs the heart rate value from a BLE message
 */
  HeartRate(List<int> values) {
    var flags = values[0];
    var s = flags.toRadixString(2);
    List<String> flagsArray = s.split("");

    int offset = 0;

    //Determine whether it is U16 or not
    if (flagsArray[0] == "0") {
      //Since it is Uint8 i will only get the first value
      var hr = values[1];
      print(hr);
    } else {
      //Since UTF 16 is two bytes I need to combine them
      //Create a buffer with the first two bytes after the flags
      var buffer = new Uint8List.fromList(values.sublist(1, 3)).buffer;
      var hrBuffer = new ByteData.view(buffer);
      var hr = hrBuffer.getUint16(0, Endian.little);
      print(hr);
    }
  }

Эти данные имеют неправильную длину. Если вы читаете org.bluetooth.characteristic.heart_rate_measurement, полезная нагрузка должна иметь длину от 2 до 5 байт (если только нет RR, чего я здесь не вижу), в зависимости от флагов. Поэтому я сильно подозреваю, что вы создаете value неправильно. Обратите внимание, что биты отсчитываются от LSB, а не от MSB (поэтому вы читаете их в обратном порядке). BLE также всегда имеет обратный порядок байтов, поэтому вам нужно сдвинуть второй байт на 8 бит, если вы читаете uint16. Но давайте начнем с того, откуда вы берете данные, потому что это выглядит неправильно.

Rob Napier 24.12.2020 22:05

Спасибо, Роб, я ценю ответ. Возможно, я неправильно получаю данные (в этом много нового), но я получаю их из примера проекта "flutter_blue". Вот что печатает на экран, когда дергаю характеристику (0x2A37). Вот еще один, намного короче (который может быть более надежным) [22, 56, 55, 4, 7, 3]. Учитывая, что биты LSB, означает ли это, что бит 8vs16 на самом деле равен 0 в моем примере? Я добавил полный список в OP. Пожалуйста, дайте мне знать, если вам нужно что-нибудь еще.

mornindew 24.12.2020 22:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
1 922
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Определить формат

Сайт Bluetooth был недавно реорганизован (~ 2020 г.), и, в частности, они избавились от некоторых средств просмотра документов, что значительно усложняет поиск и чтение IMO. Вся документация находится в документе Heart Rate Service (HRS), ссылка на который находится на главной странице GATT , но для анализа формата лучшим известным мне источником является XML для org.bluetooth. характеристика.сердечный ритм_измерение. (После реорганизации я не знаю, как можно найти эту страницу без поиска. Кажется, она больше не связана.)

Байт 0 — флаги: 22 (0001 0110)

Биты нумеруются от LSB (0) до MSB (7).

  • Бит 0 — формат значения сердечного ритма: 0 => UINT8 ударов в минуту
  • Бит 1-2 — Состояние контакта датчика: 11 => Поддерживается и обнаружено
  • Бит 3 — состояние израсходованной энергии: 0 => отсутствует
  • Бит 4 — RR-Interval: 1 => присутствует одно или несколько значений

Значение RR-интервалов объясняется в документе HRS, указанном выше. Похоже, вам просто нужно значение частоты сердечных сокращений, поэтому я не буду вдаваться в них здесь.

Байт 1 - UINT8 ударов в минуту: 56

Поскольку бит 0 флагов равен 0, это количество ударов в минуту. 56.

Байты 2-5 - UINT16 RR Интервалы: 55, 4, 7, 3

Вы, вероятно, не заботитесь об этом, но здесь есть два значения UINT16 (может быть произвольное количество значений RR-Interval). BLE всегда имеет обратный порядок байтов, поэтому [55, 4] равно 1079 (55 + 4<<8), а [7, 3] равно 775 (7 + 3<<8).

Я считаю, что документы немного сбивают с толку. XML предполагает, что эти значения указаны в секундах, но в комментариях говорится: «Разрешение 1/1024 секунды». Нормальным способом выразить это было бы <BinaryExponent>-10</BinaryExponent>, и я уверен, что они имели в виду именно это. Итак, это будут:

  • RR0: 1,05 с (1079/1024)
  • RR1: 0,76 с (775/1024)

Роб, я действительно ценю время, которое вы потратили, чтобы четко объяснить это, и вы правы! Документация не так ясна, как эта. Большое спасибо! И так, чтобы я знал, что я на 100% ясен... Если бы первый флаг был 1, тогда я бы сделал ту же самую логику, чтобы получить BPM? hr = (значения[1] + значения[2] << 8 Верно ли это?

mornindew 26.12.2020 22:00

Точно. Я не знаю, насколько это распространено за пределами медицинских устройств (поскольку 8 бит дадут вам 255 ударов в минуту, и я надеюсь, что в этот момент задействуется врач), но вполне возможно, что вы столкнетесь с этим.

Rob Napier 27.12.2020 17:24

Привет @RobNapier, я до сих пор не понимаю, как интерпретировать значение частоты сердечных сокращений в байте 1. По мере увеличения значения оно переходит в отрицательные значения, такие как 126, 127, -127, -126, -125, ... Я поднял вопрос по этой теме. Может быть, вы можете пролить свет на это. Спасибо! -> stackoverflow.com/questions/67024800/…

Emanuel 09.04.2021 18:49

@Emanuel UINT8 означает 8-битное целое число без знака, поэтому, если вы видите отрицательные значения, это просто означает, что вы привели его к целочисленному типу данных со знаком. Убедитесь, что вы используете беззнаковое целое число.

Gruff 19.08.2021 16:24

Я пытаюсь сделать сопутствующее приложение для своих умных часов. Я пытаюсь получить частоту сердечных сокращений и ударов в минуту через устройство. Я не знаю, что и с чего начать. Если бы кто-то из вас был готов помочь, было бы здорово.

Simran Sharma 11.06.2022 04:46

Другие вопросы по теме