【问题标题】:Apple's heart rate monitoring example and byte order of bluetooth heart rate measurement characteristics苹果心率监测示例及蓝牙心率测量特性的字节序
【发布时间】:2012-12-26 09:59:14
【问题描述】:

关于心率测量特性:

http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml

编辑

链接现在在 https://www.bluetooth.com/specifications/gatt/characteristics/ 并寻找“心率测量”。

他们不再提供 XML 查看器,但您需要查看 XML directly

对于this page 上的服务也是如此。

结束编辑

我想确保我阅读正确。这实际上是说 5 个字段吗?强制性的,C1、C2、C3 和 C4?强制在第一个字节,C4 在最后两个字节,C1 和C2 是8 位字段,C3 到C4 都是16 位。总共有 8 个字节。我是否正确阅读了这份文档?

编辑:

我被告知强制标志字段表明某些内容为 0,这意味着它不存在。例如,如果第一位为 0,则 C1 为下一个字段,如果为 1,则为 C2。

结束编辑

在苹果的OSX heart rate monitor example

- (void) updateWithHRMData:(NSData *)data 
{
    const uint8_t *reportData = [data bytes];
    uint16_t bpm = 0;

    if ((reportData[0] & 0x01) == 0) 
    {
        /* uint8 bpm */
        bpm = reportData[1];
    } 
    else 
    {
        /* uint16 bpm */
        bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
    }

    ... // I ignore rest of the code for simplicity
}

它将第一位检查为零,如果不是,则通过将 CFSwapInt16LittleToHost 应用于 reportData[1],将小字节序更改为主机字节顺序。

位检查是如何工作的?我不完全确定字节序。是说不管是小还是大,第一个字节总是必填字段,第二个字节是C1,等等?由于reportData 是一个8 位指针(typedef 指向unsigned char),它会检查必填字段的位0 或位8。

如果该位是第 8 位,则该位保留以供将来使用,为什么要在那里读取?

如果该位为 0,它是 little-endian 并且不需要转换?但是如果是little-endian,根据规范,第一位可能是1,1表示“心率值格式设置为UINT16。单位:每分钟节拍(bpm)”,不会误读吗?

我不明白它是如何进行检查的。

编辑: 我一直说有 C5,那是个错误。仅由 C4 决定,我在上面进行了编辑。

【问题讨论】:

  • 您的链接似乎已损坏。请问可以更新一下吗?
  • @jaaq 链接已更新。

标签: bluetooth bluetooth-lowenergy endianness


【解决方案1】:

我是否正确阅读了这份文档?

恕我直言,你读错了。

C1 到 C4 应该读作条件 1 到条件 4。并且在 org.bluetooth.characteristic.heart_rate_measurement 的表中,如果标志字节的最低位为 0,则满足 C1,否则,满足 C2。

您可以认为它是 C 编程语言中的运行时可配置联合类型(由 flag 确定。请注意,这并不总是正确的,因为 C3 和 C4 使情况变得复杂)。

// Note: this struct is only for you to better understand a simplified case.
// You should still stick to the profile documentations to implement.

typedef struct {
    uint8_t flag;
    union {
        uint8_t bpm1;
        uint16_t bpm2;
    }bpm;
} MEASUREMENT_CHAR; 

位检查是如何工作的?

if ((reportData[0] & 0x01) == 0) 使用按位与运算符有效地检查位。如果有任何疑问,请去找一本 C/C++ 编程介绍书。

在这种情况下,第一个字节始终是标志。 flag 的值动态地确定应该如何处理其余字节。 C3 和 C4 都是可选的,如果标志中的相应位设置为零,则可以省略。 C1 和 C2 互斥。

蓝牙标准中没有字节序歧义,因为它已经很好地解决了应该一直使用小字节序的问题。您应该始终假设那些uint16_t 字段以小端序传输。 Apple 的预防措施只是为了确保代码的最大可移植性,因为他们不会保证未来产品中使用的架构的字节序。

【讨论】:

  • 两个问题: 1. 你写的结构里面有flag,但是我在表中没有看到?所有标志似乎都在第一个字节中。 2.我知道按位运算符,但这不是我要问的,但我认为它检查了错误的字段。根据 Apple 的代码,我希望检查该位是否有字节序(正如 CFSwapInt16LittleToHost 所建议的那样)。你能解释一下为什么它会检查第一个位吗?
  • 不是,它使用了数组的其余部分,跳过了第一个元素。它也不会检查数据的字节顺序,因为它假设很少,它会检查主机。
【解决方案2】:

我明白了。它不是测试字节顺序。相反,它正在测试该字段是 8 位还是 16 位,如果是 16 位,它将从小端转换为主机顺序。但是我看到在转换之前和转换之后它是相同的数字。所以我猜这个系统一开始是小端的,所以我不知道有什么意义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多