getBodyBatteryHistory invalid value when passing options

Can anybody explain why I'd get an invalid value exception in the on-device CIQ error log for the following code example?

var options = {
    :period => new Toybox.Time.Duration(300),
    :order => Toybox.SensorHistory.ORDER_NEWEST_FIRST
};

/* this causes an invalid value exception */
var iter = Toybox.SensorHistory.getBodyBatteryHistory(options);

/* this succeeds */
var iter = Toybox.SensorHistory.getBodyBatteryHistory(null);

Edit: I forgot to mention this error is observed on an FR255 with current 19.18 firmware.

  • Also, I have the call wrapped something like this and am unable to catch the exception. My watchface log doesn't show any output and the watch displays the IQ! error symbol rather than continuing without these poll results.

    module MyModule {
    
      module BodyBatt {
      
        function poll() {
          ... /* code to get body battery history here */
        }
      
      }
    
      function poll() {
        try {
          BodyBatt.poll();
        } catch (ex) {
          Toybox.System.println("error in MyModule.BodyBatt.poll");
          Toybox.System.println(ex.getErrorMessage());
        }
      }
    }
    
    /* watcface calls MyModule.poll() */

  • Idk why your code is failing with an Invalid Value error, but the reason you can’t catch is because it’s a (fatal) error, not an exception.

    Unfortunately CIQ has a bunch of errors like that which simply terminate the app and can’t be caught. For example, if you try access an out of bounds index in an array, that’s an error, not an exception.

    Having said that, I can’t see anything wrong with your code, so I’m leaning towards the idea that this is a bug in the device. You might want to file a bug report so you can get confirmation either way.

    I assume the same code doesn’t fail in the sim?

  • I discovered that the FR255 works if I pass an integer number of samples for period, and its sampling period seems to be 180s.

    /* fails */
    :period => new Time.Duration(num_seconds_desired), ...
    
    /* works */
    :period => num_seconds_desired/180 + 1, ...

  • Unfortunately when passing options it will fail on several devices. A workaround is to not pass options and filter it after the fact. (*) ( (*) Unfortunately on some devices the amount of entries in the body battery history is huge and will cause a watchdog timeout if you loop all, so exit early...)