Why could this code give invalid value in ERA?

if (Toybox has :SensorHistory && Toybox.SensorHistory has :getBodyBatteryHistory) {
    var lastvalue_0 = Toybox.SensorHistory.getBodyBatteryHistory({:period => new Time.Duration(900)}).next();
    if (lastvalue_0 != null && lastvalue_0 has :data && lastvalue_0.data != null) {
        _percentage = lastvalue_0.data.toFloat();
    }
}
I don't know what else I can do anymore?
  • You should provide more details, like the crash itself including the line #,  the target.  As a guess, line 2, do a null check on the value before doing the "next".  The history could be empty.

  • Yeah I pushed an update so I can't get the ERA report anymore :/

    But basically the error only said invalid value and this line specifically

    var lastvalue_0 = Toybox.SensorHistory.getBodyBatteryHistory({:period => new Time.Duration(900)}).next();

    But the thing is this is the Pretty monkey optimized code, in my original code I do check first if lastvalue_0 is not null before I do .next() on it. But from the documentation getBodyHistory never returns null, only next() can return null which I check on it. Pretty Monkey C also converts my code to that it doesn't check for null on getbodybatteryhistory. So I'm pretty sure that that is not the issue. The error appears on a real device as it comes from ERA from my live watch face. It has only 1 occurence, but I just wonder how it could have crashed on this code. I'm trying to just get 0 ERA crash reports. But no mather what I do I always get some occurences on random places in ERA. 

  • What you want to do is this:

    var xyz = Toybox.SensorHistory.getBodyBatteryHistory({:period => new Time.Duration(900)});
    if(xyz!=null) {
        var lastvalue_0 =xyz.next();
        ...
    }

  • I'll just state the obvious since it hasn't been said outright: unfortunately, the documentation is wrong. The associated type information is also most likely wrong.

    Here's a similar bug report:

    UserProfile.getUserActivityHistory() can return null, contrary to documentation and SDK type information

    Unfortunately, a not insignificant source of bugs in CIQ apps is taking the documentation at face value. There's even example code which either won't compile, or worse, will crash when it runs.

  • The problem is that's exactly what I'm doing but Pretty monkey C converts my code to the one I posted above. That would mean I would need to manually adjust the code Pretty monkey C optimizer creates. 

  • That would be insane,if a function can actually return null while documentation states it doesn't. That would mean you cannot trust anything and you would need to null check basically everything. That would even mean the code generated by pretty monkey c optimizer would be incorrect and would pretty much make that unusable as well :/ 

  • Since the get*History() calls were introduced, I've always null checked the return.  Looks like the doc is wrong.  When a device is first turned on, there is no history.

  • But maybe the creator of Prettier Monkey C should also be notified then?

    Because the code

    var xyz = Toybox.SensorHistory.getBodyBatteryHistory({:period => new Time.Duration(900)});
    if(xyz!=null) {
    var lastvalue_0 =xyz.next();
    ...
    }

    Actually convers into the following when using prettier monkey C


    var lastvalue_0 = Toybox.SensorHistory.getBodyBatteryHistory({:period => new Time.Duration(900)}).next();

  • I let the Garmin compiler do my optimization.  See this whole thread about prettier and maybe report it there

    https://forums.garmin.com/developer/connect-iq/f/discussion/288367/prettier-code-formatter-for-monkey-c

  • Garmin compiler doesn’t optimize your code :) it just compiles it. Pretty monkey C first optimizes your code and then compiles the optimized version with the standard garmin compiler. Pretty monkey C does some things to your code that can easily shave off another 10kb of memory if not more, but are things you wouldn’t want to do yourself as that would make your code terrible to read and work with. Like it replaces all variable names with very short codes and puts recurring things into enums and such. It works really well and it’s nice I can just keep my normal code in a very well readable way and pretty monkey c stores a super optimized hard to read version seperate for the compiler to use and actually run. Specially on older watches or instinct where there’s only 92kb or even 62kb memory shaving off 10kb with pretty monkey is a huge difference.