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