BLE 中的心率值

Posted

技术标签:

【中文标题】BLE 中的心率值【英文标题】:Heart Rate Value in BLE 【发布时间】:2020-12-24 20:36:45 【问题描述】:

我很难从 HR 特征中获得有效值。我显然没有正确处理 Dart 中的值。

示例数据:

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

标志字段: 我将主字节数组中的第一项转换为二进制以获取标志

22 = 10110 (as binary)

这让我相信它是 U16 (bit[0] is == 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 也始终是 little-endian,因此如果您确实读取 uint16,则需要将第二个字节移动超过 8 位。但是让我们从获取数据的位置开始,因为它看起来不对。 谢谢你 Rob - 我很感激你的回复。有可能我获取的数据不正确(大部分都是新的),但我是从“flutter_blue”示例项目中获取的。这就是我拉特征(0x2A37)时打印到屏幕上的内容。这是另一个更短的(可能更可靠) [22, 56, 55, 4, 7, 3] 鉴于这些位是 LSB,那么这是否意味着在我的示例中 8vs16 位实际上是 0?我将完整列表添加到 OP。如果您还需要什么,请告诉我。 【参考方案1】:

您更新后的数据看起来好多了。以下是如何解码它,以及您从头开始自己解决这个问题的过程。

确定格式

Bluetooth 网站最近(~2020 年)进行了重组,特别是他们摆脱了一些文档查看器,这使得查找和阅读 IMO 变得更加困难。所有文档都在Heart Rate Service (HRS) 文档中,从主要的GATT page 链接,但仅用于解析格式,我所知道的最好的来源是org.bluetooth.characteristic.heart_rate_measurement 的XML。 (改版后,不搜索不知道怎么找到这个页面,好像没有链接了。)

字节 0 - 标志:22 (0001 0110)

位从 LSB (0) 到 MSB (7) 编号。

位 0 - 心率值格式:0 => UINT8 次/分钟 位 1-2 - 传感器接触状态:11 => 支持并检测到 位 3 - 能量消耗状态:0 => 不存在 位 4 - RR 间隔:1 => 存在一个或多个值

RR 间隔的含义在上面链接的 HRS 文档中进行了解释。听起来你只是想要心率值,所以我这里就不赘述了。

字节 1 - UINT8 BPM:56

由于标志的第 0 位为 0,因此这是每分钟的节拍数。 56.

字节 2-5 - UINT16 RR 间隔:55、4、7、3

您可能不关心这些,但这里有两个 UINT16 值(可以有任意数量的 RR-Interval 值)。 BLE 始终是 little-endian,因此 [55, 4] 是 1,079 (55 + 4

我相信文档对此有点困惑。 XML 建议这些值以秒为单位,但 cmets 说“分辨率为 1/1024 秒”。表达这一点的正常方式是&lt;BinaryExponent&gt;-10&lt;/BinaryExponent&gt;,我敢肯定这就是他们的意思。所以这些将是:

RR0:1.05s (1079/1024) RR1:0.76 秒 (775/1024)

【讨论】:

Rob - 我非常感谢您花时间清楚地解释这一点,您是对的!文档并不像这样清晰。非常感谢!所以我知道我是 100% 清楚的......如果第一个标志是 1,那么我会做完全相同的逻辑来获得 BPM? hr = (values[1] + values[2] 没错。我不知道这在医疗设备之外会有多普遍(因为 8 位将使您达到 255 bpm,此时我希望医生参与其中),但您肯定有可能遇到它。 嗨@RobNapier我仍然不明白如何解释字节1中的心率值。随着值的增加,它会变成负值,如126、127、-127、-126,- 125,... 我就这个话题提出了一个问题。也许你可以在这方面带来一些启示。谢谢! -> ***.com/questions/67024800/… @Emanuel UINT8 表示 8 位无符号整数,因此如果您看到负值,则表示您已将其转换为有符号整数数据类型。确保您使用的是无符号整数。

以上是关于BLE 中的心率值的主要内容,如果未能解决你的问题,请参考以下文章

当 BLE 设备不再可见时处理

Fleck websocket 实现问题。无法使用套接字。发送

iOS Swift 将基本心率数据作为广播消息探索,无需配对

.wav 文件中的心率 (BPM) 计算

如何从 Swift 中的 Health Kit Sdk 中获取卡路里和心率?

树莓派 3 BLE 设备