How to obtain HRV from Garmin ANT+ on Android

28 Views Asked by At

I am trying to calculate HRV (Heart rate variability) from ANT+ of my Garmin Vivosmart 5 watch on Android. Garmin does not output HRV directly, and instead uses proprietary stress level which is seemingly related, but not the same number as HRV. I tried EliteHRV app, however it told me that my garmin is inaccurate, and produced a lot of mis-detections, so I decided to write my own, trying to address issues with the way the data is collected. Is code below the correct way of deriving HRV from ANT+ data?

override fun subscribeToEvents(pcc: AntPlusHeartRatePcc) {
    pcc.subscribeHeartRateDataEvent { estTimestamp, _, computedHeartRate, heartBeatCount , sBeatTime , _ ->
        val device = getDevice(pcc)
        device.hr = computedHeartRate
        device.hrTimestamp = estTimestamp
        device.rr = -1.0;
        device.hrv = -1.0;

        var tdiff = device.hrTimestamp - previousTime; // detect connection loss
        if (tdiff < 500 && (heartBeatCount - previousBeat) > 0L) {
            //Section 5.3.6.3 https://err.no/tmp/ANT_Device_Profile_Heart_Rate_Monitor.pdf
            var rr  = (sBeatTime - sPreviousBeatTime).toDouble() / (heartBeatCount - previousBeat) * 1000.0;
            var maxrrvals = 40; //stat window size
            while (rrVals.size >= maxrrvals){
                rrVals.removeFirst()
            }
            rrVals.add(rr)
            device.rr = rr;
            if (rrVals.size == maxrrvals) {
                // From https://downloads.hindawi.com/journals/mse/2012/931943.pdf
                // https://stackoverflow.com/questions/24624039/how-to-get-hrv-heart-rate-variability-from-hr-heart-rate
                var rmssdTotal : Double = 0.0;
                var rmssdCount : Int = 0
                for (i in 1 until rrVals.size) {
                    var diff = rrVals[i] - rrVals[i-1]
                    //remove train of consecutive identical values
                    if (diff == 0.0) {
                        continue
                    }
                    rmssdCount += 1
                    rmssdTotal += (diff).pow(2.0)
                }
                if (rmssdCount >= maxrrvals * 0.25) { //ensure we have some stats
                    var rmssd = kotlin.math.sqrt(rmssdTotal / rmssdCount)
                    // from https://help.elitehrv.com/article/54-how-do-you-calculate-the-hrv-score
                    device.hrv = kotlin.math.ln(rmssd) / 6.5 * 100.0
                }
            }
        }
        previousTime = device.hrTimestamp;
        previousBeat = heartBeatCount
        sPreviousBeatTime = sBeatTime
        listener.onDataUpdated(device)
    }
}
0

There are 0 best solutions below