Body Battery NOT available when Watch face downloaded from store, but is when installed via .prg file locally. Any ideas? minApiVersion 3.2.0 Instinct APAC watch.

Further to my initial question about my watch face not appearing in the store. That is not resolved. 

Body Battery NOT available when Watch face downloaded from store, but is when installed via .prg file locally. Any ideas? minApiVersion 3.2.0 Instinct APAC watch.

Here is my code that works in the simulator, works when I export a prg file and load locally on my watch, but fails when accessed via the Garmin IQ App store. 

Not exact code, so might have a typo. The rest of the watch face works, just this little bit fails. Any help is greatly appreciated. 

   var obBBIterator=null;
        var objBodyBattery = null;
        if ((Toybox has :SensorHistory) && (Toybox.SensorHistory has :getBodyBatteryHistory)) {
            // Set up the method with parameters
            obBBIterator =  Toybox.SensorHistory.getBodyBatteryHistory({});
            objBodyBattery = obBBIterator.next();                
        } else {
            System.print("getBodyBatteryIterator: Looks like we coudn't get body battery history from toybox. NOT GOOD. ");
        }
This objBodyBattery is = null when I check from the store!
Thanks so much. 
Code is actually here if anyone is interested. By the way it is VERY BAD code. Poorly organised etc. 

Top Replies

All Replies

  • Turn off compile time optimization of the has check

  • Turn off compile time optimization of the has check

    To do this:

    - Open command palette in VS Code: CTRL-SHIFT-P / CMD-SHIFT-P

    - Select Preferences: Open User Settings

    - Search for Monkey C

    - Add the following text to Monkey C: Compiler Options:

    --disable-api-has-check-removal

    The full list of compiler options is available here: [https://developer.garmin.com/connect-iq/monkey-c/compiler-options/]

    For further context:

    - body battery requires a minimum of API 3.3.0

    - the APAC part number is configured with API 3.2.0 (as noted and previously discussed)

    - even though your *real* APAC device may have API 3.4, the Toybox.SensorHistory has :getBodyBatteryHistory check is apparently being optimized to false at compile time, due to the APAC device configuration which says its API level is 3.2.0. (This does require optimization to be enabled.)

    - this works when you build a PRG locally because in that case, it's the main (WW) part number which is targeted, and that part number is configured with API 3.4.*

    Seems pretty clear to me that --disable-api-has-check-removal should have been the default compiler behavior (once the "api has check removal" optimization was introduced.)

    The current situation is terrible for any kind of future-proofing of apps, and for the specific case where the configuration of APAC devices' API level lags behind their actual API level irl.

  • Seems pretty clear to me that --disable-api-has-check-removal should have been the default compiler behavior (once the "api has check removal" optimization was introduced.)

    I said the same thing when requesting there was an option to turn it off when it was always on.. APAC devices and new System levels were two of the cases I used when asking for a way to turn it off

    And the same for type checking.  It should have been off by default, as it broke many existing apps at the time when it defaulted to on

  • Type checking is a different story, as it only (potentially) prevents your apps from compiling. Once you get your app compiling with type checking enabled, the presence or absence of type checking doesn't change the runtime behavior of your app. As a matter of fact, enabling type checking for a legacy project does have the potential to catch many types of common errors. (We've seen many examples of code with type errors posted in the forums that would not compile if type checking was enabled - I think the most common type error is the failure to check a field for a null value.)

    In fact, several CIQ watchfaces in the store are now crashing because they can't handle a null value for Weather.CurrentConditions.observationLocationName, which was always typed to be String or Null, was always (or usually) returned as a String in the past, but is now deprecated (so it's always null on newer devices / firmware).

    If those watchfaces had been compiled with type checking enabled, the dev would've received a warning or error due to the fact that their code does not properly handle the case where Weather.CurrentConditions.observationLocationName is null.

    On the other hand, the optimization of api has checks at compile time actually does change the runtime behavior of your app, in a silent and surprising way. It changes the semantics (meaning) of every API-related has check in your app. (Type checking doesn't change the meaning of your code, it gives you a warning or error if your code doesn't follow certain rules.)

    I understand why Garmin enables type checking by default. It would sort of defeat the purpose of adding type checking to the language if the vast majority of devs would never use it at any level.

    And clearly the goal is to attract and cater to new devs (same with the move VS Code a few years ago).

    I think any new devs or existing devs who make new apps should absolutely use type checking.

  • In fact, several CIQ watchfaces in the store are now crashing because they can't handle a null value for Weather.CurrentConditions.observationLocationName

    That is a developer error  As I've said for years, you need to null check EVERTHING you see in currentConditions.  The one I see most often is the "Feels Like" temperature

    How does Type Checking help?  It has not found any bugs in my code but likes to complain!

  • Thanks so muchand - you have both solved my problem so quickly. I really appreciate it.  I've also worked out now where can I see what miminum api is for methods, So maybe I don't need to bother you so much. eg under the defintion https://developer.garmin.com/connect-iq/api-docs/Toybox/SensorHistory.html#getBodyBatteryHistory-instance_function after the Since: label. 

  • That is a developer error  As I've said for years, you need to null check EVERTHING you see in currentConditions.  The one I see most often is the "Feels Like" temperature

    I guess those devs haven't been religiously following your forum posts. ¯\_(ツ)_/¯

    If only there was a way for the *compiler* to tell the dev they need to null-check a variable or property.

    I'm not sure why you think "that is a developer error" somehow contradicts what I said about how the type checker could've caught the error. What do you think the purpose of the type checker is? To annoy devs who have projects from before type checking existed?

    As I tried to explain above, the type checker will give you a warning or error [depending on the type check level], if you try to reference a value that might be null. But in fact to take advantage of that feature, you need to set a *higher* type check level than default [either 2 or 3].

    Here's an example of how type checking would prevent me from using Weather.CurrentConditions.observationLocationName without the necessary null check.

    I built this using SDK 7.3.1 [since observationLocationName was not yet deprecated for that SDK] and type check level 3 (the highest level):

    If I use the latest non-beta SDK (7.4.3), I get the same error except it also tells me that observationLocationName is deprecated:

    Same results with 8.0.0-beta as 7.4.3.

    If I set the type check level to 2, the error about the null value becomes a warning.

    With the type check level set to 1 [the default value], the null value warning goes away.

    When type checking is disabled [set to 0], the deprecation warning also goes away.

  • How does Type Checking help?

    The purpose of type checking is to help avoid developer errors. The Monkey C type checker will also tell you if you try to access an undefined symbol, which is another common developer error.

    If you re-read the System 8 release notes, you will see that the new language features in the Monkey C extension require type checking to be enabled (or so the notes say.) As a matter of fact, if you disable type checking, the extension now asks you to turn on type checking to take advantage of the Monkey C language features.

    It has not found any bugs in my code but likes to complain!

    Not sure how you would know since the first advice you give to any dev who's having problems is turn off type checking (even if their problem is clearly unrelated). I highly doubt you would use a type check level higher than default on purpose, which is where you'd get the most benefit out of type checking.

    Also, since most of your apps have presumably been stable for years, it's likely that there were no significant bugs for the type checker to find.

    That doesn't change the fact that type checking could've found bugs in *other* devs' apps (like the seemingly common observationLocationName bug).

    Or do you not care about the quality of other apps in the store? Or the overall experience for all devs (not just you)?

    If you were to build a new app from scratch, the type checker could help find bugs before you even run your app once in the sim or on a real device. That's assuming that you'd be willing to work with the type checker, instead of seeing it as useless at best and a nuisance at worst.

  • I guess I write much more stable code than you do.

  • I guess I write much more stable code than you do.

    Uh, I never said that my code is so broken that I need the type checker.

    I said that the type checker can benefit all devs, including you and me. If you already write great code, the type checker can save you time, again as long as you are willing to work with it.

    If you don't want to use it, that's fine, but it's objectively wrong to say that other devs cannot benefit from it

    I gave an example of apps in store which are crashing because they don't null check observationLocationName. Not sure what that has to do with the quality of my code or your code. Do you want other apps in the store to be higher quality or not? What do you think is more effective: you posting for years that devs should null check all fields, or Garmin adding a built-in type checking feature to the language that will tell a dev when they need to null check a field? As a matter of fact they should've made type-check level 2 the default imo, as the current default level (1) won't find problems like lack of null checks.

    It's just crazy how your attitude to every feature request is that if you don't personally need it, it's worthless. Same as every bug report that doesn't affect you isn't worth reporting.

    It's funny because when CIQ first came out, you were constantly filing bug reports and making feature requests. At some point down the line, you did a 180 and started reflexively invalidating every single bug report and feature request.

    Now you don't even like new features that *Garmin* introduces and wants everyone to use. It would be one thing if you were trying defend Monkey C/CIQ as Garmin currently provides it, but now you are even against Garmin themselves improving the language. Maybe we should just roll CIQ back to 2015.