Получение вариабельности сердечного ритма от Polar H10 (UWP) - PullRequest
0 голосов
/ 19 октября 2018

Я запускаю образец BLE с github (Windows) и пытаюсь получить вариабельность сердечного ритма от Polar H10.

Однако единственные услуги и характеристики, которые он мне показывает, следующие:

// first layer keys are serviceUuid's
// second layer keys are characteristicUuid's
// with their respective name/description as values
{
    "1800"    /* Generic Access */                      : {
        "2a00": "Device Name",
        "2a01": "Appearance",
        "2a02": "Peripheral Privacy Flag",
        "2a03": "Reconnection Address",
        "2a04": "Peripheral Preferred Connection Parameters"
    },
    "1801"    /* Generic Attribute */                   : {
        "2a05": "Service Changed"
    },
    "180d"    /* Heart Rate */                          : {
        "2a37": "Heart Rate Measurement",
        "2a38": "Body Sensor Location"
    },
    "180a"    /* Device Information */                  : {
        "2a23": "System ID",
        "2a24": "Model Number String",
        "2a25": "Serial Number String",
        "2a26": "Firmware Revision String",
        "2a27": "Hardware Revision String",
        "2a28": "Software Revision String",
        "2a29": "Manufacturer Name String"
    },
    "180f"    /* Battery Service */                     : {
        "2a19": "Battery Level"
    },
    "6217ff4b-fb31-1140-ad5a-a45545d7ecf3" /* unknown */: {
        "6217ff4c-c8ec-b1fb-1380-3ad986708e2d": "unknown", /* read:true */ // value = 
         uInt16Array [3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
        "6217ff4d-91bb-91d0-7e2a-7cd3bda8a1f3": "unknown" /* write:true, 
         indicate:true, descriptors:{ descriptorUuid: "2902" }*/
     {
         /* 6172 */
         this service has all the numbers which I have no idea about. 
         Example: 10905, 10906, and etc.  
     }
}

Теперь я знаю, что Polar H10 дает вам вариабельность сердечного ритма.Так почему это не показывает мне?

У кого-нибудь есть идеи?

РЕДАКТИРОВАТЬ ::

private static ushort ParseHeartRateValue(byte[] data)
    {
        //ushort offset = 1;
        // Heart Rate profile defined flag values
        const byte heartRateValueFormat = 0x04;

        byte flags = data[0];
        ushort offset = 1;
        bool HRC2 = (flags & 1) == 1;
        if (HRC2) //this means the BPM is un uint16
        {
            short hr = BitConverter.ToInt16(data, offset);
            offset += 2;
        }
        else //BPM is uint8
        {
            byte hr = data[offset];
            offset += 1;
        }

        //see if EE is available
        //if so, pull 2 bytes

        bool ee = (flags & (1 << 3)) != 0;
        if (ee)
            offset += 2;

        // see if RR is present 
        // if so, the number of RR values is total bytes left / 2(size of uInt 16)

        bool rr = ((flags & 1 << 4) != 0);
        if (rr)
        {
            int count = (data.Length - offset) / 2;
            for (int i = 0; i < count; i++)
            {
                //each existence of these values means an R-Wave was already detected
                //the ushort means the time (1/1024 seconds) since last r-wave

                ushort value = BitConverter.ToUInt16(data, offset);

                double intervalLengthInSeconds = value / 1024.0;
                offset += 2;

            }
        }
        bool isHeartRateValueSizeLong = ((flags & heartRateValueFormat) != 0);

        if (isHeartRateValueSizeLong)
        {
            return BitConverter.ToUInt16(data, 1);
        }
        else 
        {
            return data[1];
        }

      }
   }
 }

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Если вы можете прочитать сердцебиение в уведомлениях, то есть также rr-интервал.Интервал rr представлен 2 байтами (uint16).Вам нужен rr-интервал для расчета вариабельности сердечного ритма в вашем приложении.

Чтобы получить rr-интервал, вы должны прочитать флаги с первого полученного байта.Вы читаете флаги как двоичные справа налево.

бит 0 = 0: Формат значения частоты пульса установлен в UINT8.Единицы: BPM (1 байт).
бит 0 = 1: Формат значения частоты пульса установлен на UINT16.Единицы: BPM (2 байта).

бит 1 и 2: биты состояния контакта датчика.Это не относится к этому.

бит 3 = 0: поле Energy Expended отсутствует.
bit 3 = 1: поле Energy Expended присутствует.Формат = uint16.Единицы: килоджоулей.

бит 4 = 0: значения интервала RR отсутствуют.
бит 4 = 1: присутствует одно или несколько значений интервала RR.Формат = uint16.единица 1/1024 сек.

биты 5, 6 и 7: зарезервировано для будущего использования.

Если ваш первый байт, например, = 16 = 0x10 = 0b00010000, то байт 2 = является частотой сердечных сокращений.

Байты 3 и 4 - это интервал rr.
Байты 5 и 6 (если имеются) - интервал rr.

Для расчета вариабельности сердечного ритма вам необходимо выбрать значения rr-интервала за определенный период времени и взять стандартное отклонение этих интервалов.Чтобы рассчитать стандартное отклонение:

1. Work out the Mean (the simple average of the numbers)
2. Then for each number: subtract the Mean and square the result
3. Then work out the mean of those squared differences.
4. Take the square root of that and we are done!

Как это сделать в коде, я оставляю это на ваше усмотрение, или вы можете погуглить его.

Примечание:

  1. Байт-пары в спецификациях SIG являются наименее значимыми байтами в первую очередь, поэтому для представления uint16 в Windows поменяйте местами байты пары байтов первыми!
  2. rr-интервал не миллисекунды, а 1/1024 секунды.Это необходимо для предотвращения потери десятичных чисел в беззнаковых делениях.
0 голосов
/ 19 октября 2018

Согласно официальной документации , UUID измерения частоты сердечных сокращений равен 00002a37-0000-1000-8000-00805f9b34f, что соответствует выводу из вашего вопроса 2a37.

Документы содержат следующий примердля Android:

if (characteristic.getUuid().equals(HR_MEASUREMENT)) {
    byte[] data = characteristic.getValue();
    int hrFormat = data[0] & 0x01;
    boolean sensorContact = true;
    final boolean contactSupported = !((data[0] & 0x06) == 0);
    if( contactSupported ) {
        sensorContact = ((data[0] & 0x06) >> 1) == 3;
    }
    int energyExpended = (data[0] & 0x08) >> 3;
    int rrPresent = (data[0] & 0x10) >> 4;
    final int hrValue = (hrFormat == 1 ? data[1] + (data[2] << 8) : data[1]) & (hrFormat == 1 ? 0x0000FFFF : 0x000000FF);
    if( !contactSupported && hrValue == 0 ){
        // note does this apply to all sensors, also 3rd party
        sensorContact = false;
    }
    final boolean sensorContactFinal = sensorContact;
    int offset = hrFormat + 2;
    int energy = 0;
    if (energyExpended == 1) {
        energy = (data[offset] & 0xFF) + ((data[offset + 1] & 0xFF) << 8);
        offset += 2;
    }
    final ArrayList<Integer> rrs = new ArrayList<>();
    if (rrPresent == 1) {
        int len = data.length;
        while (offset < len) {
            int rrValue = (int) ((data[offset] & 0xFF) + ((data[offset + 1] & 0xFF) << 8));
            offset += 2;
            rrs.add(rrValue);
        }
    }
}

Показывает, как интерпретировать значение измерения ЧСС (которое составляет byte массив).

В UWP вы можете следить за примерами и документацией здесь, чтобы соединить событие GattCharacteristic ValueChanged, которое даст вам текущее значение данной характеристики в GattValueChangedEventArgs:

characteristic.ValueChanged += Characteristic_ValueChanged;

Обрабатывается так:

void Characteristic_ValueChanged(GattCharacteristic sender, 
                                    GattValueChangedEventArgs args)
{
    // An Indicate or Notify reported that the value has changed.
    var reader = DataReader.FromBuffer(args.CharacteristicValue)
    // Parse the data however required.
}

DataReader предоставляет метод ReadBytes, а также ReadByte, поэтому вы сможете переписать пример Java-кода в UWP.К сожалению, в моем распоряжении нет устройства Polar, поэтому эту часть я должен оставить на ваше усмотрение :-).

...