Acknowledged

SDK 7.3.0 --> BodyBatteryHistory broken

function getIteratorBodyBattery() {
    // Check device for SensorHistory compatibility
    if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) {
        return Toybox.SensorHistory.getBodyBatteryHistory({});
    }
    return null;
}

var intBB = 0;
var sensorIterBodyBattery = getIteratorBodyBattery();
if (sensorIterBodyBattery != null) {
    intBB = sensorIterBodyBattery.next().data / 100;
}

Line 12:
intBB = sensorIterBodyBattery.next().data / 100;
stops with error in SDK 7.3.0:
Details: Failed invoking <symbol>

There is no probnlem with that in SDK 7.2.1:

SDK 7.2.1
sensorIterBodyBattery:
----------------------

mMax = 37 (Lang.Number)
mMin = 35 (Lang.Number)
mNewestSampleTime = Lang.Object
mOldestSampleTime = Lang.Object

Values with SDK 7.3.0:

SDK 7.3.0
sensorIterBodyBattery:
----------------------

mMax = 0 (Lang.Number)
mMin = 127 (Lang.Number)
mNewestSampleTime = Lang.Object
 mDateTime = 0 (Lang.Number)
mOldestSampleTime = Lang.Object
 mDateTime = 0 (Lang.Number)

The minimum-value is 127 (body battery cannot be greater than 100) and die maximum value is 0 (max is smaller than min).
The setup of the simulator is identically.
IMHO there is bug in
Toybox.SensorHistory.getBodyBatteryHistory({})

Is there an idea to fix that?

Greetings,
Ronny

  • Okay, I finally have e better understanding of what's going on. Basically, if you use 'null' or request a large enough period, you'll receive a crash. We're going to get a fix out in an upcoming point release of the SDK, but in the meantime, you should be able to work around this by providing the :period a Number or Duration, but you may still encounter this crash if you request a large number of samples.

  • I'm revisiting this because of a separate conversation I've been having about this, and I realize I misunderstood the nature of the issue. Like you said, the :period option cannot be null, even though the docs state this is allowed (there is probably more it than that... the other person I'm speaking with gets it to work if a Number is supplied to :period). So it appears there is a bug after all. I'll get this reported.

  • I appreciate the details you've provided. I don't believe there is a bug, but perhaps there was one that we have since addressed. I wasn't able to identify a specific fix related to this in 7.3.0. I'm surprised this worked without problems in 7.2.1, because I agree with 's and 's analysis that the problem is due to null values getting returned by the iterator that you were attempting to perform operations with.

  • Hi Brandon,
    with regard to your request I did some trouble shooting and null checks. First the code (that is finally working):

    function getIteratorBodyBattery() {
        // Check device for SensorHistory compatibility
        var twoHours = new Time.Duration(7200);
        if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) {
            return Toybox.SensorHistory.getBodyBatteryHistory({
                :period => twoHours,
                :order => SensorHistory.ORDER_NEWEST_FIRST
            });
        }
        return null;
    }
    
    var sensorIterBodyBattery = getIteratorBodyBattery();
    var intBB = 0;
    var bbTop = 125;
    var bbBottom = 235;
    var bbMiddle = 0;
    var intBBData;
    var intBBNext;
    if (sensorIterBodyBattery != null) {
        intBBNext = sensorIterBodyBattery.next();
        if (intBBNext != null) {
            intBBData = intBBNext.data;
            if (intBBData != null) {
                intBB = intBBData / 100;
                bbMiddle = bbBottom - ((bbBottom - bbTop) * intBB);
                dc.setColor(0xff5555, 0x000000);
                dc.fillRectangle(123, 128, 52, bbMiddle - bbTop);
                dc.setColor(0x55ff55, 0x000000);
                dc.fillRectangle(123, 128 + bbMiddle - bbTop, 52, bbBottom - bbMiddle);
            } else {
                dc.setColor(0xffffff, 0x000000);
                dc.fillRectangle(123, 128, 52, 114);
            }
        } else {
            dc.setColor(0xaaaaaa, 0x000000);
            dc.fillRectangle(123, 128, 52, 114);
        }
    } else {
        dc.setColor(0x5555ff, 0x000000);
        dc.fillRectangle(123, 128, 52, 114);
    }
    var BodyOutline = Application.loadResource( Rez.Drawables.BodyOutline ) as BitmapResource;
    dc.drawBitmap(123, 128, BodyOutline);

    I implemented null checks for every step in between --> every object that could be null will draw the body battery indicator in a different color. The problem is obviously caused by the option ":period" in the method

    Toybox.SensorHistory.getBodyBatteryHistory({})

    According to the API-doc the option :period could have 3 states:

    • null
    • number
    • duration

    If :period is "null" or any number, then the return leads to a null-value of ".next()" of the SensorHistoryIterator - in my code:
    intBBNext = sensorIterBodyBattery.next();
    intBBNext is null --> the body battery indicator get the color light gray.
    body battery no data (light gray)

    Only if :period is a duration, the body battery value will be return properly:
    body batterie OK

    I tested on real device (fenix 7x)

    I hope, these checks will help you to find the problem in the body battery history.

    With best regards
    Ronny

  • I'll hold off reporting this until you are able to confirm you're not just getting a null value. If you're doing null checks and continue to run into this problem, we can dig into it further.