HRM Dual - extra data in heart rate characteristic data

I just found an oddity with the Garmin Dual HRM when getting the heart rate data via BLE.
The GATT Specification for the heart rate characteristic is quite simple and defines:
  • Flags - 1 byte
  • Heart Rate - 1 or 2 bytes, depending on flags
  • Energy Expended - 0 or 2 bytes, depending on flags
  • RR intervals - 0 or n*2 bytes, depending on flags
What I'm seeing is that the Garmin Dual sends an extra two bytes of obviously incorrect RR data!
From Garmin Dual:
HeartRate.parse_hr_measurement[1:Dual 929843-F86376B40E6D:0]: 10 38 2d 04 35 00 flags: 0010 bpm: 56 rrList: [1044, 52] energy_expended: None
- Flags 0x10, indicates single byte heart rate and RR intervals are present
- Heart Rate 0x38 (56)
- RR 0x042d (1104) and 0x0035 (52)
Comparing the BLE data stream to the ANT+ data stream the 0x00, 0x35 data is extraneous.

It is also close to being outside the bounds of what is possible, it would indicate a heart rate of just about 200 bpm.


  • Which flag in your example tells you that n==2? Maybe it is 1, and the 0x0035 is some extra data that doesn't belong to rrList?
    It might be soething similar to what I see in ANT: https://forums.garmin.com/developer/connect-iq/f/discussion/319492/toybox-ant-message-length that there are 19 bytes in the message, but the payload is only 7 bytes.

    BTW 52ms is too small for rr interval anyway, so I'm pretty sure it doesn't belong there.

  • The GATT Specification Supplement defines the content of the data in 3.106 Heart Rate Measurement. Flags define the RR-Intervals present if bit 4 is set. 

    If bit 4 is set, then skip one byte for Flags, Heart Rate Measurement Value (1 or 2 bytes depending on Flag bit 0), and the Energy Expended (0 or 2 depending on Flag bit 3), then all of the additional data is defined as a uint16 Array.

    So in the above sample, we see [ 0x2d, 0x04, 0x35, 0x00] so two samples. One of which is obviously incorrect. And not seen in the ANT+ data stream (which I'm also collecting.)

    I'm almost suspecting this may be some interaction between the Bluetooth libraries.

    I'm using Python with Bleak and seeing this in two test systems (Windows 11 and Linux) but not in a third (Windows 10.)

    Simply ignoring the incorrect data is a quick workaround if this is the only issue. But I'd like to understand what is happening in case there is some other problem this is just a symptom of.