Bluetooth low energy, how to parse R-R Interval value?

前端 未结 5 642
醉梦人生
醉梦人生 2021-01-07 02:18

My application is receiving information from smart heart device. Now i can see pulse value. Could you please help me to parse R-R Interval value? How can i check device supp

相关标签:
5条回答
  • 2021-01-07 02:28

    in @Brabbeldas solution i had to use a different flag to get rri values. but might depend on device used.

    if ((reportData[0] & 0x10) == 0)
    

    instead of

    if ((reportData[0] & 0x04) == 0)
    
    0 讨论(0)
  • 2021-01-07 02:34

    Parse heart rate parameters in "C"

    I uploaded the sample application to 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");
        }
    }
    
    0 讨论(0)
  • 2021-01-07 02:45

    Have you checked the Bluetooth spec? The sample code below is in C#, but I think it shows the way to parse the data in each heart rate packet.

    //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;
        }
    }
    
    0 讨论(0)
  • 2021-01-07 02:51

    This post is a little old but a full answer has not been given. As I run into this post and it did help me at the end, I would like to share my final code. Hopefully it will help others.

    The code provided by Daniel Judge is actually right, but as he already wrote, it is C#. HIs code is a bit better compared to what Simon M came up with at the end as the code of Daniel Judge takes into account there can be more than two RR-values within one message. Here is the actual spec of the Heart_rate_measurement characteristic

    I have translated Daniel Judge his code to 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);
    
            }
    
        }
    
    }
    
    0 讨论(0)
  • 2021-01-07 02:51

    EDIT: this work for me, i get the correct rr values: In some cases you can find two values at the same time for 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);
                    }
    
            }
    
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题