0
A
回答
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
編輯: 這個工作對我來說,我得到了正確的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");
}
}
相關問題
- 1. IOS藍牙低功耗連接間隔
- 2. 藍牙低功耗通知間隔
- 3. 藍牙低功耗
- 4. Android藍牙低功耗
- 5. 藍牙低功耗Android Studio
- 6. 藍牙低功耗通知
- 7. 藍牙低功耗Rssi Android
- 8. 藍牙低功耗背景
- 9. Android藍牙低功耗readRemoteRssi
- 10. Windows 8藍牙低功耗API示例
- 11. 藍牙低功耗應用程序
- 12. Qt - WINDOWS - 藍牙低功耗工作?
- 13. iOS藍牙低功耗問題
- 14. 藍牙低功耗startLeScan已棄用
- 15. RN4020 PICtail™藍牙低功耗編程
- 16. 藍牙低功耗外設模式
- 17. ios6上的藍牙低功耗; CBPeripheralManagerDelegate
- 18. 支持藍牙低功耗(BTLE)設備
- 19. 藍牙低功耗 - 雙方獲得RSSI?
- 20. 藍牙低功耗唯一標識符
- 21. Android Studio:藍牙低功耗BLE廣告
- 22. Android和低功耗藍牙(BLE)
- 23. 在Linux上的藍牙低功耗API
- 24. 使用藍牙低功耗寫入
- 25. iOS和藍牙低功耗,可能性?
- 26. java中的藍牙低功耗API
- 27. 如何獲取藍牙低功耗設備的rssi值?
- 28. 連接USB與BLE(藍牙低功耗)的藍牙適配器
- 29. 瞭解藍牙低功耗的Android特徵
- 30. 摩托羅拉和低功耗藍牙低功耗客戶端設備
感謝您的詳細代碼示例中,+ 1給你。我已經在Objective-C中翻譯並使用了整體。看到我對這篇文章的回答。 – Brabbeldas
我的Wahoo Tickr傳感器有關檢測到的r波的數量的行爲是相當奇怪的。大多數情況下,我只能得到一個似乎是正確的RR讀數。但是當我得到2讀數,這兩個讀數必須加以總結才能得到正確的RR值(bpm:48,rr [0]:0.58,rr [1]:0.62)..但有時它們幾乎是兩個單獨的讀數,但有些不太可能的價值。太大或太小.. – Chriz