You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Cordova的蓝牙心率监测器(含RR间隔)数据解析问题求助

Hey there! Let's break down how to parse that heart rate data from your Polar H7 using cordova-plugin-ble-central—those raw RR intervals can feel like a mystery at first, but once you unpack the Bluetooth spec format, it all makes sense.

解析蓝牙心率监测器数据的分步指南

First, let's recall that the heart rate measurement characteristic (UUID: 00002a37-0000-1000-8000-00805f9b34fb) sends data as a byte array. The first byte is a flags byte that tells you exactly what data follows, and how to interpret it. Let's build out the parsing logic step by step.

1. 解析标志位(关键!)

The first byte controls everything about the rest of the data. Here's what each bit means (from least significant to most):

  • Bit 0: Heart rate format (0 = 8-bit integer, 1 = 16-bit integer)
  • Bits 1-2: Sensor contact status (00 = no contact support, 01 = supported but not touching, 10 = supported and touching)
  • Bit 3: Whether energy expended data is included (0 = no, 1 = yes)
  • Bits 4-5: Whether raw RR intervals are included (00 = none, 01 = one interval, 10 = multiple intervals)
  • Bits 6-7: Reserved for future use

Let's write a helper function to decode this:

function parseHrFlags(flagsByte) {
  return {
    isHeartRate16Bit: !!(flagsByte & 0x01),
    sensorContactStatus: (flagsByte >> 1) & 0x03,
    hasEnergyData: !!(flagsByte & 0x08),
    hasRrIntervals: !!(flagsByte & 0x10) || !!(flagsByte & 0x20)
  };
}

2. 解析心率值

Next, we pull the actual heart rate value based on the flag we just parsed. Bluetooth uses little-endian byte order, so we need to account for that with 16-bit values:

function parseHeartRate(dataView, flags, offset) {
  if (flags.isHeartRate16Bit) {
    return dataView.getUint16(offset, true); // true = little-endian
  } else {
    return dataView.getUint8(offset);
  }
}

3. 解析能量消耗数据(可选)

If the flags say energy data is included, it's a 16-bit value right after the heart rate:

function parseEnergyExpended(dataView, offset) {
  return dataView.getUint16(offset, true); // Unit: kilojoules
}

4. 解析原始RR间隔(Polar H7的重点)

This is what you care about for raw RR intervals! Polar H7 sends multiple intervals at once, each as a 16-bit value representing time in 1/1024 seconds. We'll convert that to milliseconds for easier use:

function parseRrIntervals(dataView, offset) {
  const intervals = [];
  // Loop until we've processed all remaining bytes
  while (offset < dataView.byteLength) {
    const rawRr = dataView.getUint16(offset, true);
    // Convert 1/1024s to ms: rawRr * (1000 / 1024) ≈ rawRr * 0.9765625
    intervals.push(rawRr * 0.9765625);
    offset += 2; // Each RR interval takes 2 bytes
  }
  return intervals;
}

整合到你的onData函数

Now let's put all these pieces together in your existing callback. We'll convert the incoming buffer to a DataView for easy byte-level access:

onData: function(buffer) {
  const dataView = new DataView(buffer);
  let currentOffset = 0;

  // Step 1: Parse flags
  const flags = parseHrFlags(dataView.getUint8(currentOffset));
  currentOffset += 1;

  // Step 2: Parse heart rate
  const heartRate = parseHeartRate(dataView, flags, currentOffset);
  currentOffset += flags.isHeartRate16Bit ? 2 : 1;

  // Step 3: Parse energy data (if present)
  let energyExpended = null;
  if (flags.hasEnergyData) {
    energyExpended = parseEnergyExpended(dataView, currentOffset);
    currentOffset += 2;
  }

  // Step 4: Parse RR intervals (if present)
  let rrIntervals = [];
  if (flags.hasRrIntervals) {
    rrIntervals = parseRrIntervals(dataView, currentOffset);
  }

  // Use your parsed data!
  console.log(`Current Heart Rate: ${heartRate} BPM`);
  if (energyExpended) {
    console.log(`Energy Expended: ${energyExpended} kJ`);
  }
  if (rrIntervals.length > 0) {
    console.log(`Raw RR Intervals (ms): ${rrIntervals.join(', ')}`);
  }
}

针对Polar H7的小提示

  • Polar H7 typically batches multiple RR intervals in one data packet, so don't be surprised if rrIntervals has 2-3 values at a time
  • Double-check you're subscribed to the correct characteristic: 00002a37-0000-1000-8000-00805f9b34fb (heart rate measurement)
  • If you're still stuck, print the raw byte array first: console.log(new Uint8Array(buffer)) and manually decode it using the flag rules—this helps spot where the parsing logic might be off

内容的提问来源于stack exchange,提问作者Guy McLean

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:35:07