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

时间:2018-10-18 21:04:17

标签: c# uwp bluetooth-lowenergy

我正在从github(Windows)运行BLE示例,并尝试从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 :(得分:2)

如果您可以阅读通知中的心跳信号,则还有rr-interval。 rr间隔表示为2个字节(uint16)。 您需要使用rr-interval来计算应用中的心率变异性。

要获取rr-interval,您必须从收到的第一个字节中读取标志。 您从右到左将标志读为二进制。

位0 = 0:心率值格式设置为UINT8。单位:BPM(1字节)。
位0 = 1:心率值格式设置为UINT16。单位:BPM(2个字节)。

位1和2:传感器接触状态位。这些与此无关。

位3 = 0:“能量消耗”字段不存在。
位3 = 1:存在能源消耗字段。格式= uint16。单位:千克焦耳。

位4 = 0:不存在RR间隔值。
位4 = 1:存在一个或多个RR间隔值。格式= uint16。单位1/1024秒。

第5、6和7位:保留供将来使用。

例如,如果您的第一个字节= 16 = 0x10 = 0b00010000,则字节2 =是心率。

字节3和4是rr-interval。
字节5和6(如果存在)rr-interval。

要计算心率变异性,您必须在一段时间内采样rr-interval值,并采用这些间隔的标准差。 要计算标准偏差:

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!

如何在代码中执行此操作,我留给您决定,或者您可以在Google中进行搜索。

注意:

    SIG规范中的
  1. 字节对是最低有效字节在先,  因此,对于Windows中的uint16表示形式,请先交换一个字节对的字节!
  2. rr-interval不是毫秒,而是1/1024秒。  这是为了防止丢失无符号除法中的小数。

答案 1 :(得分:1)

根据官方documentation,心率测量的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);
        }
    }
}

其中将向您展示如何解释HR测量值(即byte数组)。

在UWP中,您可以按照示例和documentation here来连接GattCharacteristic的{​​{1}}事件,这将为您提供{{1}中给定特性的当前值}:

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方法,因此您应该能够将示例Java代码重写为UWP。不幸的是,我没有Polar设备可供使用,因此这部分我必须交给您:-)。