HR history min/max readings inaccurate sometimes?

I have put a graph on my watchface using the HR history readings, and it works flawlessly about 99% of the time. But every once in a while I look and it has drawn the graph peaks either way higher, or in the complete opposite direction. The way I'm calculating the peaks should limit it to only taking up ~20 pixels max regardless of the current reading, UNLESS the min & max functions are broken and the HR value can be outside the min/max range:
below is a sample of the graph code. I'm not bothering to check the times of the readings at the moment, just plotting what the last # of results are if they are valid. I've added toFloat() conversion like a madman just in case it was an integer issue with the division, but that didn't help. This code works flawlessly on the simulator (of course) and mostly flawlessly on the actual watch. And most of the time when I notice the graph is messed up, if I move my arm it brings it out of low power mode and the next re-draw fixes the graph....

I guess I just need to check if my actual HR difference is > the supposed max difference and not plot it then? Except one of the times the entire plot was outside the bounds, which isn't even possible unless the max or min got set to something nonsensical. I already have it checking if there is no difference from min to max and telling it to just draw along the bottom of the range.

BTW - this only draws about the last 1 to 2 hours of HR readings rather than all of them. I'd fix it to work off the times, but the simulator is so awful for the HR history... is there any way to set the data yourself so you can test more than just the one plain vanilla case?

var hrIter = Act.getHeartRateHistory(null, true);
var max = hrIter.getMax();
var min = hrIter.getMin();
var maxdiff = max - min;
var hr = hrIter.next();
var height = 18.0;
var bottomY = 28.0;
var minX = 64.0;
var x = screenWidth-65;
var y1 = bottomY.toFloat();

while(hr!=null && x >= minX){

if(hr.heartRate != Act.INVALID_HR_SAMPLE && hr.heartRate > 0){
var y2 = bottomY - (maxdiff > 0 ? (hr.heartRate.toFloat() - min.toFloat())/maxdiff.toFloat() * height.toFloat() : 0.0);
dc.setColor(Gfx.COLOR_LT_GRAY,Gfx.COLOR_TRANSPARENT);
dc.drawLine(x, y1, x, y2); //shade in gray
dc.setColor(Gfx.COLOR_WHITE,Gfx.COLOR_TRANSPARENT);
dc.drawPoint(x, y2); //draw white point at top for actual hr measure
}
x--;
hr = hrIter.next();
}
dc.setColor(Gfx.COLOR_DK_GRAY,Gfx.COLOR_TRANSPARENT);
dc.drawLine(screenWidth-65, 29, 63, 29);

*the watchface prints the current HR in another section
  • To see if I can help find what's happening, I put together a very simple watchface, where I chart the hr from 0 to 254 (I toss the invalid 255 readings) and then draw each 1 pix wide. I did it on a va-hr so that the chart would be 128 px high, and I could just use hr/2 to draw the chart.

    It also displays min,max, and current HR, as well as how many readings in history I used (I only request 148 as that's all I can display, while I noticed you request "all" by passing null).

    The orange lines are the last min/max I got in the getHeartRateHistory() call to watch for "out of bounds". Here's what it looks like in the sim, and it looks fine on a real watch.



    Have you noticed any cases where you can see the strange values? I ran this over night and all looked fine.
  • My code works perfectly fine on the simulator, running constantly for days without a problem.

    It seems to happen when the watch is starting a new HR polling cycle and doesn't have a good HR value... it appears to be setting a new but invalid min and/or max value (ie, min higher than max) or keeping a "last HR" measure that is completely invalid (higher than max or lower than the min) yet not a 255 (INVALID_HR_SAMPLE) and this causes either that single point to go haywire, or sometimes even makes the entire chart to draw inverted. This lasts for about a minute or so and then corrects itself.

    I'm tossing 0s and 255s as invalid already. I'm not testing the min & max for invalid values though, so I guess I should sanity check the min/max values too.
  • After running this for a couple days on a va-hr, I see nothings strange. an occasional 255, but that's it (I still graph those but in pink)..

    Maybe this is f3-hr specific?
  • After running this for a couple days on a va-hr, I see nothings strange. an occasional 255, but that's it (I still graph those but in pink)..

    Maybe this is f3-hr specific?


    Mine's the 235.. so I wouldn't be surprised if there's some crap HR history bug ;)

    I think I'll change mine to request the actual # of readings I can display for one - had forgotten about that after putting the null in to see how much history it would give. Maybe that'll clear up some of the weird readings.
  • Former Member
    Former Member over 9 years ago
    var hrIter = Act.getHeartRateHistory(null, true);
    var min = hrIter.getMin();

    Given the 2 lines of code above can someone tell me if the getMin above resets at midnight ?
  • min and may are based on the number of samples you request or the Duration of the oldest you want.

    "period — If period is null, the entire available history is retrieved. If period is a Duration, then the history for the given Duration is retrieved. If period is a Number, then the last Number entries are retrieved."

    Just create a duration using "midnight and now"
  • Well since changing my watchface to request only a specific # of history items, the bug hasn't popped up again at all - yet anyway... it's been 24 hours now though.

    I'm thinking that something occasionally goes wrong with the functionality of the min/max requests when you request full history. It's the only way it's possible for the above logic to not plot within the bounds given.

    edit: 48+hours now since I changed it, and I haven't seen it go haywire since. Before the change it was going crazy multiple times a day. So definitely something related to passing null to get the full history.