我的应用程序正在从智能心脏设备接收信息。现在我可以看到脉冲值了。你能帮我解析 RR Interval 值吗?我如何检查设备是否支持 RR 间隔值?
你的任何建议
谢谢
我的应用程序正在从智能心脏设备接收信息。现在我可以看到脉冲值了。你能帮我解析 RR Interval 值吗?我如何检查设备是否支持 RR 间隔值?
你的任何建议
谢谢
你检查过蓝牙规格吗?下面的示例代码是用 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;
}
}
这篇文章有点旧,但还没有给出完整的答案。当我遇到这篇文章时,它确实对我有所帮助,我想分享我的最终代码。希望它会帮助其他人。
Daniel Judge 提供的代码实际上是正确的,但正如他已经写的那样,它是 C#。与 Simon M 最后提出的代码相比,他的代码要好一些,因为 Daniel Judge 的代码考虑到一条消息中可以有两个以上的 RR 值。这是Heart_rate_measurement 特性的实际规格
我已将 Daniel Judge 他的代码翻译成 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);
}
}
}
编辑:这对我有用,我得到了正确的 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);
}
}
}
}
解析“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");
}
}
在@Brabbeldas 解决方案中,我必须使用不同的标志来获取 rri 值。但可能取决于使用的设备。
if ((reportData[0] & 0x10) == 0)
代替
if ((reportData[0] & 0x04) == 0)