Class HeartRateMeasurement

java.lang.Object
com.codename1.health.sensors.HeartRateMeasurement

public final class HeartRateMeasurement extends Object

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.

  • 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()
      The heart rate in beats per minute.
    • isSensorContactSupported

      public boolean isSensorContactSupported()
      Whether this device reports skin contact at all. When false, isSensorContactDetected() carries no information.
    • isSensorContactDetected

      public boolean isSensorContactDetected()
      Whether the sensor is in contact with skin. Only meaningful when isSensorContactSupported() is true; always false otherwise, which must not be shown to the user as poor contact.
    • hasEnergyExpended

      public boolean hasEnergyExpended()
      Whether this notification carried the energy-expended field. Devices typically include it only every few notifications.
    • 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()
      Energy expended since the last reset, in kilocalories -- the kilojoule value divided by 4.184.
    • getRrIntervalCount

      public int getRrIntervalCount()
      How many RR intervals this notification carried. Often more than one, and zero when the device does not report them.
    • getRrIntervalMillis

      public double getRrIntervalMillis(int i)

      RR interval i in milliseconds, converted from the wire's 1/1024-second units.

      Throws
      • ArrayIndexOutOfBoundsException: if i is outside [0, getRrIntervalCount()).
    • toString

      public String toString()
      Description copied from class: Object
      Returns a string representation of the object. In general, the toString method returns a string that "textually represents" this object. The result should be a concise but informative representation that is easy for a person to read. It is recommended that all subclasses override this method. The toString method for class Object returns a string consisting of the name of the class of which the object is an instance, the at-sign character `@', and the unsigned hexadecimal representation of the hash code of the object. In other words, this method returns a string equal to the value of: getClass().getName() + '@' + Integer.toHexString(hashCode())
      Overrides:
      toString in class Object