我无法理解字节和uint8_t值。
我正在使用apple创建的示例项目,该项目通过心率服务协议从Bluetooth 4.0心率监测器读取数据。示例项目提供如下心率数据:
- (void) updateWithHRMData:(NSData *)data
{
const uint8_t *reportData = [data bytes];
uint16_t bpm = 0;
if ((reportData[0] & 0x01) == 0)
{
/* uint8 bpm */
bpm = reportData[1];
}
else
{
/* uint16 bpm */
bpm = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[1]));
}
我假设(reportData [0]& 0x01)返回数据数组reportData中的第一个数据位,但我不知道如何访问第二个,(reportData [0]& 0x02)不起作用我以为会的。 理想情况下,我想检查reportData [0]中的所有数据,然后根据它获取reportData [4]或[5]中的rr间隔数据,具体取决于它的存储位置,并迭代它以获取每个值,因为我相信那里可以存储多个值。
我知道一个新手问题,但我很难找到答案,或者确实是用来确定答案的搜索字词。
答案 0 :(得分:2)
执行reportData[0]
时,您将获得第一个字节(索引0处)。当您将该值与reportData[0] & 0x02
组合时,除了第二位之外,您将屏蔽掉所有值。该结果将为0(如果未设置第2位)或者为2(如果第2位设置)。
if ((reportData[0] & 0x02) == 0) {
// bit 2 of first byte is not set
} else {
// bit 2 of first byte is set
}
如果你想检查所有8位,那么你可以这样做:
uint8_t byte = reportData[0];
for (int i = 0; i < 8; i++) {
int mask = 1 << i;
if ((byte & mask) == 0) {
bit i is not set
} else {
bit i is set
}
}
更新:要提取跨越两位的值,您可以执行以下操作:
uint8_t mask = 0x01 | 0x02; // Good for value stored in the first two bits
uint8_t value = byte & mask; // value now has just value from first two bits
如果要提取的值位于更高位,则还有一个额外的步骤:
uint8_t mask = 0x02 | 0x04; // Good for value in 2nd and 3rd bits
uint8_t value = (byte & mask) >> 1; // need to shift value to convert to regular integer
答案 1 :(得分:1)
检查this post以获取示例代码的讨论。该帖子还链接到Bluetooth spec,它可以帮助您理解为什么要执行字节顺序检查(基本上它是Apple确保最大的可移植性)。基本上,第一个字节是描述HRV数据的格式和EE和RR间隔数据的存在/不存在的位字段。所以:
reportData[0] & 0x03
告诉您EE数据是否存在(1 =是,0 =否)和
reportData[0] & 0x04
告诉您RR间期数据是否存在(1 =是,0 =否)
然后您可以使用
获取RR间隔数据uint16_t rrinterval;
rrinterval = CFSwapInt16LittleToHost(*(uint16_t *)(&reportData[idx]));
其中idx
由您执行的存在/不存在测试确定。我假设偏移量没有固定BTW,因为这是你所指示的(即基于存在/不存在的动态偏移) - 我不熟悉BT规范。如果格式 已修复,则在这种情况下,RR数据将偏移7。
答案 2 :(得分:1)
部分原始问题尚未得到解答。 Rory还想知道如何解析所有RR间隔数据,因为在一个消息中可以有多个值(我已经看到多达三个)。 RR间隔数据并不总是位于相同的字节内。这取决于几件事:
以下是Heart_rate_measurement characteristic
的实际规格// 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);
}
}
}