2013-07-02 33 views

回答

7

你檢查Bluetooth spec任何建議?下面的示例代碼使用C#,但我認爲它顯示瞭解析每個心率數據包中數據的方式。

//first byte of heart rate record denotes flags 
byte flags = heartRateRecord[0]; 

ushort offset = 1; 

bool HRC2 = (flags & 1) == 1; 
if (HRC2) //this means the BPM is un uint16 
{ 
    short hr = BitConverter.ToInt16(heartRateRecord, offset); 
    offset += 2; 
} 
else //BPM is uint8 
{ 
    byte hr = heartRateRecord[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 uint16) 
bool rr = (flags & (1 << 4)) != 0; 
if (rr) 
{ 
    int count = (heartRateRecord.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(heartRateRecord, offset); 

     double intervalLengthInSeconds = value/1024.0; 
     offset += 2; 
    } 
} 
+0

感謝您的詳細代碼示例中,+ 1給你。我已經在Objective-C中翻譯並使用了整體。看到我對這篇文章的回答。 – Brabbeldas

+0

我的Wahoo Tickr傳感器有關檢測到的r波的數量的行爲是相當奇怪的。大多數情況下,我只能得到一個似乎是正確的RR讀數。但是當我得到2讀數,這兩個讀數必須加以總結才能得到正確的RR值(bpm:48,rr [0]:0.58,rr [1]:0.62)..但有時它們幾乎是兩個單獨的讀數,但有些不太可能的價值。太大或太小.. – Chriz

0

編輯: 這個工作對我來說,我得到了正確的RR值: 在某些情況下,你可以在同一時間RR找到兩個值。

- (void) updateWithHRMData:(NSData *)datas { 

    const uint8_t *reportData = [datas bytes]; 

    uint16_t bpm = 0; 
    uint16_t bpm2 = 0; 

    if ((reportData[0] & 0x04) == 0) 
    { 
     NSLog(@"%@", @"Data are not present"); 
    } 
    else 
    { 

     bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[2])); 

     bpm2 = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[4])); 

     if (bpm != 0 || bpm2 != 0) { 

       NSLog(@"%u", bpm); 

       if (bpm2 != 0) { 
        NSLog(@"%u", bpm2); 
       } 

     } 

    } 

} 
1

這篇文章有點老,但沒有給出完整的答案。 當我遇到這篇文章,它最終幫助了我,我想分享我的最終代碼。希望它能幫助別人。

Daniel Judge提供的代碼其實是對的,但正如他已經寫過的,它是C#。由於Daniel Judge的代碼考慮到一條消息中可能存在兩個以上的RR值,所以與Simon M在最後提出的代碼相比,HI代碼要好一些。 下面是實際的spec of the Heart_rate_measurement characteristic

我有翻譯丹尼爾判斷他的代碼的Objective-C:

// 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); 

     } 

    } 

} 
+0

嗨!你可以向我解釋* 1000從哪裏來?我知道它與規格「1/1024秒的分辨率」相關,但我不明白操作* 1000 – darksider

0

在@Brabbeldas的解決方案,我不得不使用不同的標誌來獲得RRI值。但可能取決於使用的設備。

if ((reportData[0] & 0x10) == 0) 

代替

if ((reportData[0] & 0x04) == 0) 
0

解析在 「C」 心臟速率參數

我上傳的示例應用程序的GitHub Heart-Rate-Bluegiga

void ble_evt_attclient_attribute_value(const struct ble_msg_attclient_attribute_value_evt_t *msg) 
{ 
    if (msg->value.len < 2) { 
     printf("Not enough fields in Heart Rate Measurement value"); 
     change_state(state_finish); 
    } 


    // Heart Rate Profile defined flags 
    const unsigned char HEART_RATE_VALUE_FORMAT = 0x01; 
    const unsigned char ENERGY_EXPENDED_STATUS = 0x08; 
    const unsigned char RR_INTERVAL = 0x10; 


    unsigned char current_offset = 0; 
    unsigned char flags = msg->value.data[current_offset]; 
    int is_heart_rate_value_size_long = ((flags & HEART_RATE_VALUE_FORMAT) != 0); 
    int has_expended_energy = ((flags & ENERGY_EXPENDED_STATUS) != 0); 
    int has_rr_intervals = ((flags & RR_INTERVAL) != 0); 


    current_offset++; 


    uint16 heart_rate_measurement_value = 0; 


    if (is_heart_rate_value_size_long) 
    { 
     heart_rate_measurement_value = (uint16)((msg->value.data[current_offset + 1] << 8) + 
      msg->value.data[current_offset]); 
     current_offset += 2; 
    } 
    else 
    { 
     heart_rate_measurement_value = msg->value.data[current_offset]; 
     current_offset++; 
    } 


    printf("Heart rate measurment value: %d ", heart_rate_measurement_value); 


    uint16 expended_energy_value = 0; 


    if (has_expended_energy) 
    { 
     expended_energy_value = (uint16)((msg->value.data[current_offset + 1] << 8) + 
      msg->value.data[current_offset]); 
     current_offset += 2; 


     printf(" Expended energy value: %d ", expended_energy_value); 
    } 


    uint16 rr_intervals[10] = {0}; 


    if (has_rr_intervals) 
    { 
     printf(" Rr intervals: "); 


     int rr_intervals_count = (msg->value.len - current_offset)/2; 


     for (int i = 0; i < rr_intervals_count; i++) 
     { 
      int raw_rr_interval = (uint16)((msg->value.data[current_offset + 1] << 8) + 
       msg->value.data[current_offset]); 
      rr_intervals[i] = ((double)raw_rr_interval/1024) * 1000; 
      current_offset += 2; 


      printf("%d ", rr_intervals[i]); 
     } 
     printf("\n"); 
    } 
}