How to get data out of bluetooth characteristic in Swift
Asked Answered
E

2

9

I've got a Polar h7 device around me right now (it's BTLE) and I've got everything working but I am confused about how to get the BPM our of the characteristic.value now that it is updating. I have to turn some bytes into bpm...

My peripheral is updating:

func peripheral(peripheral: CBPeripheral!, didUpdateValueForCharacteristic characteristic: CBCharacteristic!, error: NSError!) {
    if characteristic.UUID == CBUUID.UUIDWithString(heartRateChar) {
        getInfoAboutHeartRate(characteristic)
    }
}

I am getting info about the heart rate:

func getInfoAboutHeartRate(characteristic:CBCharacteristic) {
    println(characteristic.value)
    var bytes = characteristic.value.bytes
}

I know I need turn those bytes into the BPM.
According to the specs (this is where I get confused) at bluetooth.org, byte 0 is either going to be a 1 or a 0.. If it is a 0 the heart rate value is an uint8 and if it is a 1 then it is a uint16 and I can get the BPM from that.
How do I find out if byte 0 is a 1 or a 0? How to turn that into a uint8 or uint16. And if I do that do I get the BPM straight up or do I have to do something else to it? Right now the BPM comes back as something like <16447d03> which makes sense.

Entrepreneur answered 22/8, 2014 at 22:21 Comment(0)
T
13

This seems like it should be simple enough, but trying to confirm what you're saying. Does “bytes” end up with a value of “16447d03”? It's a pointer to the data, not the data itself, so you need to do something like this to get the actual value:

var data = characteristic.value
var values = [UInt8](count:data.length, repeatedValue:0)
data.getBytes(&values, length:data.length)

In this, “values” is an array containing the actual values.

From a private discussion we had, you listed the output as:

[22, 77, 22, 3] 
[22, 78, 27, 3, 18, 3] 
[22, 79, 2, 3] 
[22, 78, 15, 3] 

The first byte is the flags, which has been 22 in all the cases you've listed. This makes sense as it's all from the same heart rate hardware.

The bits are grouped like this: | 3 bits are reserved | 1 bit for RR-Interval | 1 bit for Energy Expended Status | 2 bits for Sensor Contact Status | 1 bit for Heart Rate Value Format | 22 is 00010110 in binary, which is | 000 | 1 | 0 | 11 | 0 |.

Heart Rate Value Format bit: 0 (Heart Rate Value Format is set to UINT8)
Sensor Contact Status bits: 3 (Sensor Contact feature is supported and contact is detected)
Energy Expended Status bit: 0 (Energy Expended field is not present)
RR-Interval bit: 1 (One or more RR-Interval values are present)

This means that the following byte is the heart rate (C1 field) and the remaining bytes are RR-Interval values, whatever they are (C4 field).

So for this data the heart rates were 77, 78, 79, 78.

Tercentenary answered 22/8, 2014 at 23:22 Comment(7)
Why did you shift it 3?Entrepreneur
Yeah, you're right, should have been 7. I was thinking chars for some reason. I've fixed that.Tercentenary
So technically you don't need data.getBytes(&bytes, length:data.length) right? If so is bytes the same bytes in my question?Entrepreneur
[0, 0, 0, 0] [0, 0, 0, 0, 0, 0] [0, 0, 0, 0] [0, 0, 0, 0, 0, 0] [0, 0, 0, 0]Entrepreneur
Let us continue this discussion in chat.Tercentenary
I misread your question about data.getBytes(&bytes, length:data.length). In editing my answer I renamed bytes to values but missed that line. Sorry.Tercentenary
swift3 version: var values = [UInt8](repeating: 0, count: data.count); data.copyBytes(to: &values, count: data.count)Sabo
R
1

If anyone's wondering how to calculate the RR value. Taking the first array as an example:

[22, 77, 22, 3] in binary is 0001 0110  0100 1101  0001 0110 0000 0011

If we break it a part we have:

Flag (8bit) = 22 or 0001 0110
HRV (8bit) = 77 or 0100 1101
RR (16bit) = 22 & 3 or 0001 0110 0000 0011

Because Bluetooth.org says the order is LSO (Least Significant Octet) to MSO (Most significant Octet) 22 and 3 need to be swapped leaving:

790 or 0000 0011 0001 0110

Because the resolution is 1/1024 seconds. The RR value = 790/1024 = 0.77s.

Reitareiter answered 30/5, 2016 at 4:36 Comment(1)
I have bought a Mio Link and my raw value is: [16, 59, 207, 3] [16, 59, 17, 4] How do you calculate the RR value with this example? The exact same way?Tappet

© 2022 - 2024 — McMap. All rights reserved.