Resting heart rate misreported

The resting heart rate that is being obtained daily from Garmin quite often shows a high heart rate instead of the actual resting heart rate that I see in the Garmin Connect app.
And when I adjust it manually to correct value, it gets overridden.
Not sure if it is a problem on the intervals.icu end or with the values that the Garmin API is providing.

Read this to understand which value to use

Hmm. I had a look and Garmin is sending your resting HR in the daily summaries update. I don’t know what Garmin decides to put in those and why it should be different to Garmin Connect. This is what the Garmin docs say:

restingHeartRateInBeatsPerMinute: Average heart rate at rest during the monitoring period, in beats per minute.

I saw that coming, we will probably have to challenge Garmin on why the numbers are so odd sometimes.
In the plotted chart below it becomes more clear, and it shows it is becoming more frequent.

David, from the intervals.icu side of things, perhaps you could make sure that once I overwrite the value manually, the overwritten value does not get overwritten by the next API call? With that I could fix the data and keep it correct while we figure it out.

If you delay updating resting HR to the next day it shouldn’t be overwritten. I have added minHeartRateInBeatsPerMinute to the logging. Maybe Garmin Connect is using that?

Minimum of heart rate values captured during the monitoring period, in beats per minute.

My Oura ring uses that for the night for resting HR.

It would be very helpful if you could get Garmin to explain where the GC number comes from.

I entered manually the data for the last 4 weeks, but it seems that the past week is still being overwritten, not only the current day.

Garmin uses “Daily RHR is calculated using the lowest 30 minute average in a 24 hour period.” according to this link.

I don’t have access to the developer program to question them specifically why the data provided in Garmin Connect differs from the exposed in the API.

What I do know is that the shown RHR is not the minimum heart rate, as I can see HR datapoints that are lower than the reported RHR in the Garmin Connect chart itself.

I am curious about what numbers are coming from minHeartRateInBeatsPerMinute variable. And if you make it available as a variable that I can plot, I would love to track the minimum HR as well.

You should not use single datapoints as something meaningful because even with a chest strap and in the best conditions, you will have reading and/or xfer errors. Let alone with an optical sensor around your wrist…
RHR is not a single datapoint, it is an avg of at least a couple tens of seconds in a steady state.
Reading the post you linked, I think they use the daily value (lowest 30min/24hr) in one and the 7day rolling avg in the other. My guess would be that they use the rolling avg in Garmin Connect because a change in that value over a longer period is clearly a sign of adaptation. The value from a single day will be much more variable. Simply check that value when you have a hangover and you will understand what I mean :smiling_imp:

1 Like

These are all the pings received for you since I deployed the min logging:

2022-08-11 15:43:13.025 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 14:55:36.892 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 14:55:33.148 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 14:14:15.524 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 14:13:53.104 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 12:18:42.288 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 12:01:55.910 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 12:01:10.731 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=50
2022-08-11 06:09:36.880 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=54
2022-08-11 06:04:14.774 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=54
2022-08-11 06:01:30.884 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=54
2022-08-11 05:46:43.671 : processDailies 2022-08-11 consumedCalories=null restingHeartRateInBeatsPerMinute=58 minHeartRateInBeatsPerMinute=54

Hey @MedTechCD, thanks for the insights. I see what you mean and definitely when drinking there is variance in the RHR. :slightly_smiling_face:

The problem at hand is not an expected normal daily variance in the RHR, but rather an inconsistency between what Garmin Connect correctly shows and the odd data the Garmin API is providing to intervals.icu every now and then.
I am talking about days when, for instance, the RHR is like 58 in Garmin Connect and I see 101 or 87 BPM in intervals.icu. Even the worse hangover ever would not give a change like this. :sweat_smile:

I don’t care much about a single day information, but I care about trends, and the misreported data from Garmin API is tempering with all the rolling averages I can get and plot via intervals.icu. For me, that is the ultimate goal of fixing this issue.

Data is correct for today, I wonder why it is not at some random days.

You can see by the screenshots below. The min HR does not much exactly probably because of the Garmin Connect chart resolution on mobile.


:+1: Should have better checked the absolute values of the anomalies. Those are definitely wrong.
Differences of 10-15 bpm can be legit and are usualy easy to explain: exhaustive race/training, rough night, upcoming illness…
If no trigger can be found, validity must be questioned.

1 Like

Hi @david, today it happened again. I see 104 bpm in interval.icu, while Garmin Connect reports 54 bpm.
Perhaps the logging could gives us a hint today?

I think the issue might be data coming from Google Fit overwriting the Garmin data. I can see an update from Garmin setting your resting HR for the 16th to 54. Please don’t change your Google Fit settings. I am adding some more logging to confirm this.

I really need to make wellness logs user visible somehow!

2 Likes

Thanks for checking. I will keep Google fit settings as they are. I did not know it stored/provided resting HR. I only use it to get the weight from the generic bluetooth scale I have, which integrates with Google fit.

It is Google:

2022-08-20 08:40:43.020 GoogleService       : Athlete i33956 2022-08-18 restingHR=100
2022-08-20 08:40:43.020 GoogleService       : Athlete i33956 2022-08-16 restingHR=104

So if you disable “Resting HR” (and other stuff you don’t want) in the Google box in /settings your Garmin stuff should stand:

Screen Shot 2022-08-20 at 15.01.03

1 Like

Great finding. Thanks a lot for investigating it and identifying the issue.

I will fix my settings right away.

1 Like

Also having issues with the Garmin Resting HR.
Since I turned on the sync it seems to get the daily value fine, but I can’t import the old data.
Tried to use the Garmin Export / Intervals import method, but no bueno.

I can see the data in the Garmin export though. It’s in the files: DI_CONNECT\DI-Connect-User\UDSFile_.json

Here’s a short bit of one of the USD…files of march 15th 2022:
{“userProfilePK”:,“calendarDate”:{“date”:“Mar 15, 2022 12:00:00 AM”},“uuid”:"",“durationInMilliseconds”:86400000,“totalKilocalories”:2237.0,“activeKilocalories”:7.0,“bmrKilocalories”:2230.0,“wellnessKilocalories”:2237.0,“remainingKilocalories”:2237.0,“wellnessTotalKilocalories”:2237.0,“wellnessActiveKilocalories”:7.0,“totalSteps”:879,“dailyStepGoal”:4000,“netCalorieGoal”:3039,“totalDistanceMeters”:724,“wellnessDistanceMeters”:724,“wellnessStartTimeGmt”:{“date”:“Mar 14, 2022 11:00:00 PM”},“wellnessEndTimeGmt”:{“date”:“Mar 15, 2022 11:00:00 PM”},“wellnessStartTimeLocal”:{“date”:“Mar 15, 2022 12:00:00 AM”},“wellnessEndTimeLocal”:{“date”:“Mar 16, 2022 12:00:00 AM”},“highlyActiveSeconds”:172,“activeSeconds”:113,“moderateIntensityMinutes”:0,“vigorousIntensityMinutes”:0,“floorsAscendedInMeters”:6.48,“floorsDescendedInMeters”:2.654,“userIntensityMinutesGoal”:300,“userFloorsAscendedGoal”:10,“minHeartRate”:37,“maxHeartRate”:76,“restingHeartRate”:39,“currentDayRestingHeartRate”:38,“restingHeartRateTimestamp”:“Mar 15, 2022 11:00:00 PM”,“includesWellnessData”:true,“includesActivityData”:false,“includesCalorieConsumedData”:false,“includesSingleMeasurement”:false,“includesContinuousMeasurement”:false,“includesAllDayPulseOx”:true,“includesSleepPulseOx”:false,“source”:0,“allDayStress”:{“userProfilePK”:,“calendarDate”:{“date”:“Mar 15, 2022 12:00:00 AM”},“aggregatorList”:[{“type”:“TOTAL”,“averageStressLevel”:16,“averageStressLevelIntensity”:16,“maxStressLevel”:75,“stressIntensityCount”:1351,“stressOffWristCount”:29,“stressTooActiveCount”:59,“totalStressCount”:1439,“totalStressIntensity”:48634,“stressDuration”:8640,“restDuration”:72420,“activityDuration”:3540,“uncategorizedDuration”:1740,“totalDuration”:86340,“lowDuration”:8520,“mediumDuration”:120},{“type”:“AWAKE”,“averageStressLevel”:17,“averageStressLevelIntensity”:17,“maxStressLevel”:75,“stressIntensityCount”:798,“stressOffWristCount”:23,“stressTooActiveCount”:46,“totalStressCount”:867,“totalStressIntensity”:26099,“stressDuration”:5460,“restDuration”:42420,“activityDuration”:2760,“uncategorizedDuration”:1380,“totalDuration”:52020,“lowDuration”:5340,“mediumDuration”:120},{“type”:“ASLEEP”,“averageStressLevel”:15,“averageStressLevelIntensity”:15,“maxStressLevel”:41,“stressIntensityCount”:553,“stressOffWristCount”:6,“stressTooActiveCount”:13,“totalStressCount”:572,“totalStressIntensity”:22535,“stressDuration”:3180,“restDuration”:30000,“activityDuration”:780,“uncategorizedDuration”:360,“totalDuration”:34320,“lowDuration”:3180}]},“bodyBattery”:{“userProfilePK”:,“calendarDate”:{“date”:“Mar 15, 2022 12:00:00 AM”},“chargedValue”:46,“drainedValue”:33,“bodyBatteryVersion”:1.0,“bodyBatteryStatList”:[{“bodyBatteryStatType”:“HIGHEST”,“statsValue”:100,“bodyBatteryStatus”:“MEASURED”,“statTimestamp”:{“date”:“Mar 15, 2022 4:38:00 PM”}},{“bodyBatteryStatType”:“LOWEST”,“statsValue”:66,“bodyBatteryStatus”:“MEASURED”,“statTimestamp”:{“date”:“Mar 15, 2022 12:13:00 AM”}},{“bodyBatteryStatType”:“MOSTRECENT”,“statsValue”:83,“bodyBatteryStatus”:“MEASURED”,“statTimestamp”:{“date”:“Mar 15, 2022 11:00:00 PM”}},{“bodyBatteryStatType”:“ENDOFDAY”,“statsValue”:83,“bodyBatteryStatus”:“MEASURED”,“statTimestamp”:{“date”:“Mar 15, 2022 11:00:00 PM”}}]},“minAvgHeartRate”:38,“maxAvgHeartRate”:72,“version”:61500004,“averageSpo2Value”:96.0,“lowestSpo2Value”:93,“latestSpo2Value”:97,“latestSpo2ValueReadingTimeGmt”:{“date”:“Mar 15, 2022 11:00:00 PM”},“latestSpo2ValueReadingTimeLocal”:{“date”:“Mar 16, 2022 12:00:00 AM”},“respiration”:{“userProfilePK”:,“calendarDate”:{“date”:“Mar 15, 2022 12:00:00 AM”},“avgWakingRespirationValue”:13.0,“highestRespirationValue”:20.0,“lowestRespirationValue”:9.0,“latestRespirationValue”:14.0,“latestRespirationTimeGMT”:{“date”:“Mar 15, 2022 11:00:00 PM”}}},

It looks to me that the value we need is the “currentDayRestingHeartRate”.
The weird thing is that after importing the data, March 15th 2022 in intervals now tells me I had a resting HR of 53 and a sleep time of almost 19hrs (I wish :wink: ). Clearly something is not syncing right.

I can provide the Garmin Export link via DM if needed.

Could you please DM me that link so I can have a look. Tx.

1 Like

Intervals.icu current gets the resting HR data from the sleepData.json files. I am not sure what the resting HR is in the UDSFile.json files. Unfortunately they do not have proper timestamps: “Sep 22, 2022 12:00:00 AM” is a human formatted date so building import for that is might break for someone in a different locale and date format.

If you can get that data in CSV somehow you can use the Options → Wellness download/upload CSV on the calendar page to import it.

1 Like

Thanks David.
In the end it was the value: currentDayRestingHeartRate in the Garmin file, and the date from restingHeartRateTimestamp converted to yyyy-mm-dd
I merged the json files, converted it to csv, took only the 2 columns needed, did the date conversion, and could import the data that way.
Better to stay away from the “import old data” button from now on :slight_smile:

Now it’s clearly visible when I had my pulmonary embolism :wink:

1 Like