Getting per-second heart rate on a watch face

Hey, I'm trying to make a watch face that displays your heart rate each second, my onPartialUpdate is:

function onPartialUpdate(dc) {
    // The width changes based on the numbers, for now lets just use a constant.
    var w = 50;
    var h = heartRateLabel.height;
    var y = heartRateLabel.locY;
    // The text is aligned to the right, so subtract the width to get x.
    var x = heartRateLabel.locX - w;

    dc.setClip(x, y, w, h);

    dc.setColor(Graphics.COLOR_BLACK, Graphics.COLOR_GREEN);
    dc.fillRectangle(x, y, w, h);

    heartRateLabel.setText(getHeartRate());

    heartRateLabel.draw(dc);
}

function getHeartRate() {
    var hrIterator = ActivityMonitor.getHeartRateHistory(1, true);
    var previous = hrIterator.next();

    if (previous == null || previous.heartRate == ActivityMonitor.INVALID_HR_SAMPLE) {
        return "--";
    }
    return previous.heartRate.format("%02d");
}

The problem is that it only updates once a minute.

I've tried replacing with some dummy data and I know onPartialUpdate is called once per second. Also WatchFaceDelegate#onPowerBudgetExceeded is not called.

I've seen plenty of faces on the store that do it. I'm running this on a Forerunner 645 Music.

Also, is there any way to get the simulator to provide a changing heartrate instead of the constant 80?

  • What you want to start with is Activity.getActivityInfo().currentHeartRate (which is updated very often).

    If that is null, fall back to the newest sample in getHeartRateHistory (which will only change every minute or two on a real watch)

    if that's null, you don't have a heart rate to display.

    In onPartialUpdate I've kept track of what HR is currently being displayed (by way of onUpdate() or onPartialUpdate()), and only update the screen if the HR changed, as you really don't need to update the screen every second.  The HR might only change 20 times a minute, and this preserves your power budget.  No need to update it if you're just updating to the same value.

    With Activity.getActivityInfo().currentHeartRate, if you play back a .fit or simulate data, that will change, so you won't just see the 80 from getHeartRateHistory()

  • Thanks for the quick response! There seem to be so many ways to get the heart rate - Activity.getActivityInfo, ActivityMonitor.getHeartRateHistory, SensorHistory.getHeartRateHistory.

    I'll give that a go when I get home (and thanks for the tip about limiting the updates).

  • What you see in ActMon and SensorHistory is really just the same data.  The difference is that SensorHistory isn't available on some of the older watches where ActMon is.

  • Thanks again - my heart rate is updating!

    Unfortunately it looks like my time is not... My onUpdate is:

    function onUpdate(dc) {
        var clockTime = System.getClockTime();
        
        // Update the view
        View.findDrawableById("MinutesLabel").setText(clockTime.min.format("%02d"));
    
        // Call the parent onUpdate function to redraw the layout
        View.onUpdate(dc);
    }

    I had hoped that updating the text of the label and then calling View.onUpdate would be enough. Do I have to manually draw a black box then redraw the text in onUpdate as well?

  • You are setting a clip region in onPartialUpdate (or should be) but don't seem to be clearing it in onUpdate().  Are you clearing it someplace else?

  • Ah thank you, that was the problem.

    You've been incredibly helpful, thanks again!