1

最近我一直在玩 CoreBluetooth,虽然我可以连接到一些设备,但我似乎永远无法正确读取数据(特征值)。

现在我正在连接 Wahoo BT 心率监测器,我正在接收所有信号,但我无法将数据转化为任何有意义的数据。(是的,我知道有一个 API,但我试图在没有它的情况下进行连接,以正确获得与 CoreBluetooth 一起工作的东西)。

到目前为止,我还无法将 NSData (characteristic.value) 变成任何明智的东西。如果您对如何理解这些数据有任何建议,我们将不胜感激。

4

3 回答 3

2

下面是一些代码来完全解析所有心率测量特征数据。

如何处理数据取决于几件事:

  • BPM 是写入一个字节还是两个字节?
  • 有EE数据吗?
  • 计算 RR 间隔值的数量,因为一条消息中可以有多个值(我已经看到最多三个)。

这是Heart_rate_measurement 特性的实际规格

// Instance method to get the heart rate BPM information
- (void) getHeartBPMData:(CBCharacteristic *)characteristic error:(NSError *)error
{
    // Get the BPM //
    // https://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml //

    // Convert the contents of the characteristic value to a data-object //
    NSData *data = [characteristic value];

    // Get the byte sequence of the data-object //
    const uint8_t *reportData = [data bytes];

    // Initialise the offset variable //
    NSUInteger offset = 1;
    // Initialise the bpm variable //
    uint16_t bpm = 0;


    // Next, obtain the first byte at index 0 in the array as defined by reportData[0] and mask out all but the 1st bit //
    // The result returned will either be 0, which means that the 2nd bit is not set, or 1 if it is set //
    // If the 2nd bit is not set, retrieve the BPM value at the second byte location at index 1 in the array //
    if ((reportData[0] & 0x01) == 0) {
        // Retrieve the BPM value for the Heart Rate Monitor
        bpm = reportData[1];

        offset = offset + 1; // Plus 1 byte //
    }
    else {
        // If the second bit is set, retrieve the BPM value at second byte location at index 1 in the array and //
        // convert this to a 16-bit value based on the host’s native byte order //
        bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));

        offset =  offset + 2; // Plus 2 bytes //
    }
    NSLog(@"bpm: %i", bpm);



    // Determine if EE data is present //
    // If the 3rd bit of the first byte is 1 this means there is EE data //
    // If so, increase offset with 2 bytes //
    if ((reportData[0] & 0x03) == 1) {
        offset =  offset + 2; // Plus 2 bytes //
    }



    // Determine if RR-interval data is present //
    // If the 4th bit of the first byte is 1 this means there is RR data //
    if ((reportData[0] & 0x04) == 0)
    {
        NSLog(@"%@", @"Data are not present");
    }
    else
    {
        // The number of RR-interval values is total bytes left / 2 (size of uint16) //

        NSUInteger length = [data length];
        NSUInteger count = (length - offset)/2;
        NSLog(@"RR count: %lu", (unsigned long)count);

        for (int i = 0; i < count; i++) {

            // The unit for RR interval is 1/1024 seconds //
            uint16_t value = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[offset]));
            value = ((double)value / 1024.0 ) * 1000.0;

            offset = offset + 2; // Plus 2 bytes //

            NSLog(@"RR value %lu: %u", (unsigned long)i, value);

        }

    }

}
于 2014-10-28T08:55:56.693 回答
1

那么,您应该实施使用心率服务的心率配置文件(请参阅此处)。如果您查看心率服务规范,您将看到心率测量特性的格式根据数据包的最低有效八位字节中设置的标志而变化。

这意味着您需要设置代码来处理动态数据包大小。

所以你的一般过程是:

  1. 获取value属性的第一个字节并检查它:
    • 心率测量是 8 位还是 16 位?
    • 是否支持传感器接触?
    • 是否检测到传感器接触?
    • 是否支持能量消耗?
    • 是否支持 RR 间隔测量?
  2. 如果心率测量值为 8 位(字节 0 的位 0 为 0),则将下一个字节转换为其预期格式(提示:它是 uint8_t)。如果是 16 位(即字节 0 的位 0 为 1),则将接下来的两个字节转换为 uint16_t。
  3. 如果支持能量消耗(字节 0 的位 3 为 1),则将下一个字节转换为 uint16_t。
  4. 对 RR 间隔执行相同的操作。

使用 NSData - 尤其是与核心蓝牙一起使用 - 需要一些时间来适应,但一旦你掌握了这个概念,它并没有那么糟糕。

祝你好运!

于 2013-04-10T21:28:02.287 回答
0

好吧...当您读取characteric 的值时,您必须做的是:
NSData *data = [characteritic value]; theTypeOfTheData value; [data getByte:&value lenght:sizeof(value)];
但是,theTypeOfTheData可以是设备开发人员认为的任何内容。所以它可能是 UInt8、UInt16 或 struct(带或不带位域)...您必须通过联系设备的开发人员或查看是否有一些文档来获取信息。
例如,与我的同事一起,我们根据需要使用占用较少空间的数据类型(因为设备没有无限内存)。查看特征的描述符。它可以指出数据的类型。

于 2013-04-02T09:54:22.410 回答