Emanuel
Emanuel

Reputation: 915

BLE Heart Rate Senser Value Interpretation

I have an Android App where I get Heart Rate Measurements from a Polar H10 Device. I'm totally lost on how to interpret the heart rate. Various links to the bluetooth.com site are resulting in 404 errors unfortunately.

The characteristics value is i.e. [16, 59, 83, 4]

From what I understood the second byte (59) is the heart rate in BPM. But this does not seem to be decimal as the value goes up to 127 and then goes on -127, -126, -125, ... It is not hex either.

I tried (in kotlin)

characteristic.value[1].toUInt() 
characteristic.value[1].toInt()
characteristic.value[1].toShort()
characteristic.value[1].toULong()
characteristic.value[1].toDouble()

All values freak out as soon as the -127 appears.

Do I have to convert the 59 to binary (59=111011) and see it in there? Please give me some insight.

### Edit (12th April 2021) ###

What I do to get those values is a BluetoothDevice.connectGatt(). Then hold the GATT. In order to get heart rate values I look for

Then I enable notifications by setting 0x01 on the descriptor. I then get ongoing events in the GattClientCallback.onCharacteristicChanged() callback. I will add a screenshot below with all data.

From what I understood the response should be 6 bytes long instead of 4, right? What am I doing wrong?

On the picture you see the characteristic on the very top. It is linked to the service 180d and the characteristic holds the value with 4 bytes on the bottom.

The characteristic 0x2a37

Upvotes: 1

Views: 3010

Answers (2)

Rob Napier
Rob Napier

Reputation: 299345

See Heart Rate Value in BLE for the links to the documents. As in that answer, here's the decode:

Byte 0 - Flags: 16 (0001 0000)

Bits are numbered from LSB (0) to MSB (7).

  • Bit 0 - Heart Rate Value Format: 0 => UINT8 beats per minute
  • Bit 1-2 - Sensor Contact Status: 00 => Not supported or detected
  • Bit 3 - Energy Expended Status: 0 => No Present
  • Bit 4 - RR-Interval: 1 => One or more values are present

So the first byte is a heart rate in UInt8 format, and the next two bytes are an RR interval.

To read this in Kotlin:

characteristic.getIntValue(FORMAT_UINT8, 1)

This return a heart rate of 56 bpm.

And ignore the other two bytes unless you want the RR.

Upvotes: 3

Emanuel
Emanuel

Reputation: 915

It seems I found a way by retrieving the value as follows

val hearRateDecimal = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT8, 1)

2 things are important first - the format of UINT8 (although I don't know when to use UINT8 and when UINT16. Actually I thought I need to use UINT16 as the first byte is actually 16 (see the question above) second - the offset parameter 1

What I now get is an Integer even beyond 127 -> 127, 128, 129, 130, ...

Upvotes: 0

Related Questions