Home > Enterprise >  Decode data value of Characteristic UUID 2A37
Decode data value of Characteristic UUID 2A37

Time:02-03

How get the RR interval value from Characteristic UUID 2A37, Service UUID 180D?

I have tried to decode the value:

(0x) 10-54-AA-02-99-02

I have refer to the GrooverFromHolland's explaination from this post to generate the bpm and rr interval.

And I have built my solution in c :

#include <iostream>
#include <cmath>

using namespace std;

const int RR_INTERVAL_PRESENT_BIT = 4;
const int HEART_RATE_FORMAT_BIT = 0;
const int RR_INTERVAL_UNIT = 1024;

int main() {
  // characteristic UUID value
  unsigned char characteristic[] = {0x10, 0x54, 0xAA, 0x02, 0x99, 0x02};

  // read the flags
  unsigned char flags = characteristic[0];
  int heartRateFormat = (flags & (1 << HEART_RATE_FORMAT_BIT)) ? 2 : 1;
  int rrIntervalPresent = (flags & (1 << RR_INTERVAL_PRESENT_BIT)) ? 1 : 0;

  // calculate heart rate and rr-interval
  int heartRate = 0;
  int rrInterval = 0;
  int index = 1;
  if (heartRateFormat == 2) {
    heartRate = (characteristic[index] << 8) | characteristic[index   1];
    index  = 2;
  } else {
    heartRate = characteristic[index];
    index  = 1;
  }

  if (rrIntervalPresent) {
    rrInterval = (characteristic[index] << 8) | characteristic[index   1];
    rrInterval = round(rrInterval / (double)RR_INTERVAL_UNIT * 1000);
  }

  cout << "Heart rate: " << heartRate << " bpm" << endl;
  cout << "RR interval: " << rrInterval << " ms" << endl;

  return 0;
}

The output for the bpm is 84 bpm and the rr-interval value is 42502 ms

I have tried to compare my answer with value obtained from the rNF connect.

And obviously my `rr-interval value is wrong. Does anyone have an idea? Thanks.

CodePudding user response:

Your problem is about the byte order or endianness of your multi field value. As this answer suggests that GATT attributes are supposed to be in little endian (least significant byte first). Thats also what GrooverFromHolland mentioned in your linked post:

Note:

  1. Byte-pairs in SIG specifications are Least Significant Byte First, so for uint16 representation in Windows swap the bytes of a byte-pair first!

You can check this with a Hex-to-Decimal-Converter:

0xAA02 -> 43522
0x02AA -> 682

So you probably want to change your implementation to:

  if (rrIntervalPresent) {
    rrInterval = (characteristic[index   1] << 8) | characteristic[index];
    rrInterval = round(rrInterval / (double)RR_INTERVAL_UNIT * 1000);
  }

CodePudding user response:

I noticed that the rr-interval is refer to byte 3 and byte 4, I have changed the rrInterval to double instead of int.

Refer to:

So you probably want to change your implementation to:

if (rrIntervalPresent) {
   rrInterval = (characteristic[index   1] << 8) | characteristic[index];
   rrInterval = round(rrInterval / (double)RR_INTERVAL_UNIT * 1000);
 }

I have changed it to:

  if (rrIntervalPresent) {
    rrInterval = (characteristic[index   1] << 8) | characteristic[index   2];
    rrInterval = rrInterval / (double)RR_INTERVAL_UNIT * 1000;
  }

And it shows the correct output 649.414 ms. I'm not sure does this implementation is correct...

CodePudding user response:

Please refer to section 3.105.2 of the document 'GATT Specification Supplement'. RR-intervel is the last field of 'Heart Rate Measurement' characteristic therefore the code should also verify the presence of Energy-Expended field.

  • Related