简体   繁体   English

从Polar H10(UWP)获得心率变异性

[英]Getting Heart-rate variability from Polar H10 (UWP)

I am running the BLE sample from github (Windows) and trying to get the heart rate variability from Polar H10. 我正在从github(Windows)运行BLE样本,并尝试从Polar H10获得心率变异性。

However the only services and characteristics it shows me are following: 然而,它向我展示的唯一服务和特征如下:

// 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.  
     }
}

Now, I know that Polar H10 does give you heart rate variability. 现在,我知道Polar H10确实可以为您提供心率变异性。 So why it is not showing me ? 那么为什么它没有给我看?

Does anyone have any idea? 有人有什么主意吗?

EDIT:: 编辑::

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];
        }

      }
   }
 }

If you can read the heartbeat in notifications than there is also the rr-interval. 如果您可以在通知中读取心跳,则还会显示rr-interval。 The rr-interval is represented 2 bytes( uint16). rr-interval表示2个字节(uint16)。 You need the rr-interval to calculate heart rate variability in your app. 您需要rr-interval来计算应用中的心率变异性。

To get the rr-interval you have to read the flags from the first byte you receive. 要获得rr-interval,您必须从您收到的第一个字节读取标志。 You read the flags as binary from right to left. 您从右到左读取标记为二进制。

bit 0 = 0: Heart Rate Value Format is set to UINT8. 位0 = 0:心率值格式设置为UINT8。 Units:BPM (1 byte). 单位:BPM(1个字节)。
bit 0 = 1: Heart Rate Value Format is set to UINT16. 位0 = 1:心率值格式设置为UINT16。 Units:BPM (2 bytes). 单位:BPM(2个字节)。

bit 1 and 2: Sensor Contact Status bits. 位1和2:传感器触点状态位。 These are not relevant for this. 这些与此无关。

bit 3 = 0: Energy Expended field is not present. 位3 = 0:不存在能量消耗字段。
bit 3 = 1: Energy Expended field is present. 位3 = 1:存在能量消耗字段。 Format = uint16. Format = uint16。 Units: kilo Joules. 单位:千焦耳。

bit 4 = 0: RR-Interval values are not present. bit 4 = 0:不存在RR-Interval值。
bit 4 = 1: One or more RR-Interval values are present. bit 4 = 1:存在一个或多个RR-Interval值。 Format = uint16. Format = uint16。 unit 1/1024 sec. 单位1/1024秒

bit 5, 6 and 7: reserved for future use. 第5,6和7位:保留供将来使用。

If your first byte for example = 16 = 0x10 = 0b00010000 then byte 2 = is heart rate. 如果您的第一个字节例如= 16 = 0x10 = 0b00010000,则字节2 =是心率。

Byte 3 and 4 are the rr-interval. 字节3和4是rr间隔。
Byte 5 and 6 (if present) rr-interval. 字节5和6(如果存在)rr-间隔。

To calculate heart rate variability you have to sample the rr-interval values over a period of time and take the Standard Deviation of those intervals. 要计算心率变异性,您必须在一段时间内对rr-间隔值进行采样,并采用这些间隔的标准偏差。 To calculate the Standard Deviation: 要计算标准差:

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!

How to do that in code, I leave that up to You or you can google it. 如何在代码中执行此操作,我将其留给您或您可以谷歌它。

Note: 注意:

  1. Byte-pairs in SIG specifications are Least Significant Byte First, so for uint16 representation in Windows swap the bytes of a byte-pair first! SIG规范中的字节对是最低字节优先,因此对于Windows中的uint16表示,首先交换字节对的字节!
  2. rr-interval is not miliseconds but 1/1024 seconds. rr-interval不是毫秒,而是1/1024秒。 This is to prevent loosing the decimal numbers in an unsigned division. 这是为了防止在无符号除法中丢失十进制数。

According to the official documentation , the UUID of the heart rate measurement is 00002a37-0000-1000-8000-00805f9b34f - which matches the output from your question 2a37 . 根据官方文档 ,心率测量的UUID是00002a37-0000-1000-8000-00805f9b34f - 它与您的问题2a37的输出相匹配。

The docs provide the following sample for Android: 这些文档为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);
        }
    }
}

Which shows you how to interpret the HR measurement value (which is byte array). 其中显示了如何解释HR测量值( byte数组)。

In UWP you can follow the samples and documentation here to wire up the GattCharacteristic 's ValueChanged event, which will give you the current value of a given characteristic in GattValueChangedEventArgs : 在UWP中,您可以按照此处的示例和文档来连接GattCharacteristicValueChanged事件,该事件将为您提供GattValueChangedEventArgs给定特征的当前值:

characteristic.ValueChanged += Characteristic_ValueChanged;

Handled like this: 处理方式如下:

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 provides a ReadBytes as well as ReadByte method, so you should be able to rewrite the sample Java code to UWP. DataReader提供了ReadBytesReadByte方法,因此您应该能够将示例Java代码重写为UWP。 Unfortunately I don't have a Polar device at my disposal so this part I must leave up to you :-) . 不幸的是,我没有Polar设备,所以这部分我必须留给你:-)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM