public final class HeartRateMeasurement
- Object
- HeartRateMeasurement
A decoded Heart Rate Measurement, characteristic 0x2A37.
Parsers in this package are public and static so they can be unit tested without a radio and reused by apps doing their own GATT work.
Wire format
Byte 0 is a flags field; the payload that follows is variable-length and entirely determined by it.
| Bit | Meaning |
|---|---|
| 0 | value format: 0 = uint8, 1 = uint16 little-endian |
| 1 | sensor contact detected |
| 2 | sensor contact supported |
| 3 | energy expended field present |
| 4 | RR-interval field present |
| 5-7 | reserved – ignored, not asserted zero |
Three things that are easy to get wrong
Sensor contact. Bit 1 is meaningful only when bit 2 is set. A strap
that does not implement contact detection sends both bits clear, which
means unsupported – not not touching skin. Reporting “poor contact”
for such a device is a very common bug, so
isSensorContactDetected() is documented to be read only alongside
isSensorContactSupported().
Energy expended is kilojoules, not kilocalories, despite most fitness UIs showing kcal. Divide by 4.184.
RR intervals arrive in batches. The field is not one value but the
entire remainder of the payload, as many uint16 values as fit – a
strap notifying at 1 Hz while the heart beats faster sends two or three
per notification. Dropping any of them silently corrupts every
heart-rate-variability calculation downstream, so getRrIntervalCount()
exists and callers must loop.
Methods
public static HeartRateMeasurement parse(byte[] value) | Decodes a 0x2A37 value. |
public int getHeartRate() | The heart rate in beats per minute. |
public boolean isSensorContactSupported() | Whether this device reports skin contact at all. |
public boolean isSensorContactDetected() | Whether the sensor is in contact with skin. |
public boolean hasEnergyExpended() | Whether this notification carried the energy-expended field. |
public int getEnergyExpendedKilojoules() | Energy expended since the last reset, in kilojoules. |
public double getEnergyExpendedKilocalories() | Energy expended since the last reset, in kilocalories – the kilojoule value divided by 4.184. |
public int getRrIntervalCount() | How many RR intervals this notification carried. |
public double getRrIntervalMillis(int i) | RR interval i in milliseconds, converted from the wire’s 1/1024-second units. |
public String toString() | Returns a string representation of the object. |
Inherited methods
Method details
parse
public static HeartRateMeasurement parse(byte[] value)Decodes a 0x2A37 value.
Returns null for a null, empty, truncated or otherwise malformed
payload – never throws. A notification callback is the wrong
place to discover that a device sent a short packet, and one
misbehaving strap should not take down the app.
getHeartRate
public int getHeartRate()isSensorContactSupported
public boolean isSensorContactSupported()false,
isSensorContactDetected() carries no information.isSensorContactDetected
public boolean isSensorContactDetected()isSensorContactSupported() is true; always false otherwise,
which must not be shown to the user as poor contact.hasEnergyExpended
public boolean hasEnergyExpended()getEnergyExpendedKilojoules
public int getEnergyExpendedKilojoules()Energy expended since the last reset, in kilojoules. Zero when
hasEnergyExpended() is false.
Reset with SensorSession.resetEnergyExpended().
getEnergyExpendedKilocalories
public double getEnergyExpendedKilocalories()getRrIntervalCount
public int getRrIntervalCount()getRrIntervalMillis
public double getRrIntervalMillis(int i)i in milliseconds, converted from the wire’s
1/1024-second units.Throws
ArrayIndexOutOfBoundsException- if
iis outside[0, getRrIntervalCount()).
toString
public String toString()