How to get current Hearth Rate on Watch Faces?

Former Member
Former Member
I developed a quick Watch Face and want to display the current Hearth Rate exactly same way as Hearth Rate widget.

I used this code to achieve that:

var HRH=Act.getHeartRateHistory(1, true);
var HRS=HRH.next();
var HRSnow=HRS.heartRate;

if(HRSnow!= Act.INVALID_HR_SAMPLE){
heartRateText = HRSnow;
}

The problem with this is that it refreshes (only) each minute, so it's not accurate at all. Is there a way to get last Hearth Rate calculated by device and get it refreshed every second?

  • One problem with the code you show above is that if appInfo.currentHeartRate() changes from a valid value to null between the test and assigning currentHeartRate you will get an exception. Do the assign first and then test the variable for null.
  • One other thing to note here is that on watches like the f5x, D2 Charlie, and Descent Mk1, Activity.Info.currentHeartRate will be null due to hardware differences with other watches, so you'll keep falling back into the HR history, and therefore using onPartialUpdate() for the HR only will show changes every 60-90 seconds or so.
  • OK, here for completness, my whole code without any abbreviations like "Act.", so it is more easy to use this code. (I "invested" some hours on it)
    function GetHeartRate()
    {
    var heartRateText = "000";
    var currentHeartRate = Activity.Info.currentHeartRate; // or Activity.getActivityInfo().currentHeartRate; ?
    if(currentHeartRate != null)
    {
    heartRateText = currentHeartRate;
    }
    else
    {
    var heartRateHistory = ActivityMonitor.getHeartRateHistory(1, true); //newestFirst = true
    var heartRateSample = heartRateHistory.next();
    var heartRate = heartRateSample.heartRate;
    if(heartRateSample == ActivityMonitor.INVALID_HR_SAMPLE)
    {
    heartRateText = "---";
    }
    else
    {
    heartRateText = heartRate;
    }
    System.println( "Heart Rate: " + heartRateText );
    }
    return heartRateText;
    }

  • My code above does an update only every 60 seconds on my Fenix 5, as history data is probably only save with this frequence. My heart rate sensor is running all the time, so it should be possible to get data more often.
    On the WatchFace from Optimus HR (https://apps.garmin.com/de-DE/apps/31543af2-8d8a-4299-8348-37439829fb5f) it is so. How is this implemented?
  • The code to get the hr is what's been posted here, but to update the screen with the data, you need to be using onPartialUpdate(). I do it in a number of watchfaces. See this thread on the basics of that:

    https://forums.garmin.com/forum/developers/connect-iq/158133-?376929=

    Somewhere in there I think there some tricks on how to do HR and seconds and stay under the power budget.

  • I used onPartialUpdate()!
    But as the underlying data does only change every minute (ActivityMonitor.getHeartRateHistory) it is "useless" therefore.
    Activity.Info.currentHeartRate; is always null on my Fenix 5.
    The HR leds on the watch are always on, so HR gets measured always and there must be a way to get this data!

    And the WatchFace from "Optimus HR " (https://apps.garmin.com/de-DE/apps/3...8-37439829fb5f) works with HR every second on my Fenix 5.


  • There's probably something wrong in your logic to get the heart rate then it seems. I use 1hz to update the HR in a number of watchfaces and that works fine on the f5. How/when are you calling the code to read the HR? Post your full code for getting the HR.

    update: another thought. Does it seem to work for a minute or two and then stop? It could be you are exceeding the 30ms avg for the power budget when using onPartialUpdate. You want to be careful about how much you do during onPartialUpdate, expecially when it comes to how much of the screen you update.



  • I had it in both, then I removed it from onPartialUpdate as it did not work.
    At the moment I do it in onUpdate()only, which is called every second, when I switch to a widget and back to the watchface. (for about 10 seconds it calls onUpdate() every second)
    But during this 10 seconds, the HR never changes. It changes once a minute. SAD!

    The history probably has no value for every second?

    (I belive) HR is comming from ActivityMonitor, here my code:

    function GetHeartRate()
    {
    var heartRateText = "000";
    var heartRate = -1;
    var currentHeartRate = Activity.Info.currentHeartRate; // or Activity.getActivityInfo().currentHeartRate; ?
    if(currentHeartRate != null)
    {
    heartRateText = currentHeartRate;
    }
    else
    {
    var heartRateHistory = ActivityMonitor.getHeartRateHistory(1, true); //newestFirst = true
    var heartRateSample = heartRateHistory.next();
    heartRate = heartRateSample.heartRate;
    //if(heartRate != ActivityMonitor.INVALID_HR_SAMPLE)
    //{
    heartRateText = heartRate;
    //}
    /*else
    {
    heartRateText = "---";
    }*/
    }
    System.println( "Heart Rate: " + heartRateText );
    return heartRateText;
    }
  • You should be using Activity.getActivityInfo().currentHeartRate to get currentHeartRate

    At times you return a string and at other times a number. Try

    heartRateText=currentHeartRate.toString();

    for example.

    Also, HR doesn't always change every second. I know with my watchfaces, it can remain the same for a few seconds, and in fact, that's something I make use of in onParttialUpdate. I only update the screen when it does change (it helps with the power budget)


  • YES....finally it works!
    It is all a litte strange naming, using Activity.getActivityInfo() when in fact no Activity (CLIMB, RUN...) is active, but just the WATCH.
    What is the difference between Activity.getActivityInfo() and Activity.Info ?
    Thanks a lot.

    (used Activity.getActivityInfo().currentHeartRate for Fenix 5)