Unexpected Type Error with CIQ 3.3

Hi all,

I’ve been running my app on CIQ 3.4+ devices and am now trying to port it to CIQ 3.3.

Unfortunately, I get a runtime error when starting the app (e.g., on Edge 830), and it’s hard to trace:

Error: Unexpected Type Error
Details: Failed to start CIQ Application
Stack:

So there’s no stack trace. The crash happens right after returning from getInitialView().

What I’ve checked so far:

  • Verified that String.substring usage matches the CIQ 3.3 definition.

Does anyone know of other CIQ 3.3 limitations or gotchas that could cause this?

Thanks,
Robert

  • Not to state the obvious, but it sounds like the device doesn't like what's being returned from getInitialView()?

    Is it your openhab app? Is it a version of the code which isn't on github.

    If I run the current code for openhab on edge830 in the sim, I get a different, straightforward error on startup:

    Error: Array Out Of Bounds Error
    Details: Failed invoking <symbol>
    Stack:
      - getCurrentView() at .../openhab-garmin/source/user-interface/view-handling/ViewHandler.mc:32 0x1000a2a3
      - <globals/ErrorView/<statics>/<>get>() at .../openhab-garmin/source/user-interface/error-handling/ErrorView.mc:40 0x10008143
      - createOrUpdate() at .../openhab-garmin/source/user-interface/error-handling/ErrorView.mc:26 0x100080f8
      - getInitialView() at .../openhab-garmin/source/OHApp.mc:78 0x1000a694

    It's straightforward if you look at the code referenced in the stack trace.

    After making a few changes it runs for me.

    So I assume that either:

    - you're testing with different code

    or

    - you're running on a real edge830 (which I don't have access to)

  • Is it your openhab app? Is it a version of the code which isn't on github.

    If I run the current code for openhab on edge830 in the sim, I get a different, straightforward error on startup:

    Yes, that’s the app, thanks for testing it. I had committed the changes around the time you wrote, so you were probably working with an older version of the code.

    The error I mentioned only appears when connecting to a real server, so you won’t be able to reproduce it locally. Without a server, the error view is shown instead, and that part seems to work fine.

    The issue occurs when I return a CustomMenu implementation in getInitialView.

    I’ve also managed to reproduce another error: if I first return a “normal” View in getInitialView and then switch to the CustomMenu on CIQ 3.3, I get:

    Exception: Base view is not allowed to switch to native view for widgets 
    It seems that a CustomMenu cannot be used as the root/base view in CIQ 3.3, which might also explain the first error.
  • Oh I see.

    Exception: Base view is not allowed to switch to native view for widgets 

    There's actually a very good reason for this. At least on a watch, the initial view for a literal full-screen widget (not a glance) cannot accept any input other either than onSelect() / KEY_ENTER.

    The reason is that the "widget loop" (carousel of full-screen widgets that you navigate by pressing UP/DOWN from the watch face) is comprised of all the initial views of each widget (native or CIQ). As you scroll to the next/previous widget, if the widget is a CIQ app, the app is loaded and its initial view is displayed [*]. This initial view cannot take any other input because the only things you can do from here are:

    - "open the widget" (onSelect() / KEY_ENTER)

    - go the next/previous widget (by pressing KEY_UP/KEY_DOWN or using the touchscreen to scroll)

    As you can imagine, a menu wouldn't work here because the it would need to handle KEY_UP/KEY_DOWN and swipe up/swipe down, and that would conflict with widget scrolling. If the menu would take precedence, you would no longer be able to scroll widgets. If scrolling widgets were to take precedence, then the menu would be useless.

    This is also the reason that you're not allowed to programmatically exit or pop the initial view on a real CIQ widget (not glance) - both those things will result in a crash. By the logic of the device firmware, there's nowhere for the watch to pop "to". The only way for the user to cleanly exit a widget is for them to press BACK (swipe right) on the initial view, and for the initial view to *not* prevent the default onBack() action from happening - onBack() must not return true.

    Ofc by the logic of us devs, the firmware could just return us to the watchface, same as if the user pressed BACK on any full-screen widget's top-level view (native or CIQ), but hey, they didn't ask us.

    [*] This is obviously quite inefficient, which is why CIQ widgets would briefly display a screen with their name and launcher icon while they were (automatically) being loaded on scroll. The glance system is obviously much better, where the CIQ glance view runs in a smaller/leaner "process" that can be loaded much faster.

    The error I mentioned only appears when connecting to a real server, so you won’t be able to reproduce it locally.

    Does your server ever return anything other than a JSON object? `{ ... }`

    Numbers, booleans, arrays, strings, and null are all valid JSON, but makeWebRequest won't accept them (when the response type is json). When the response type is json, makeWebRequest wants the top level of the response to be an object, presumably so it can consistently return a Monkey C Dictionary.

    I don't like that design, but hey, they didn't ask me. 

  • The reason is that the "widget loop" (carousel of full-screen widgets that you navigate by pressing UP/DOWN from the watch face) is comprised of all the initial views of each widget (native or CIQ). As you scroll to the next/previous widget, if the widget is a CIQ app, the app is loaded and its initial view is displayed [*]. This initial view cannot take any other input because the only things you can do from here are:

    Thanks, understood. Actually my other app (evcc) does support older watches, and I do have a special glance-like first view there.
    Do you by any chance know how this works on the Edge devices? Is there also something like a widget carousel there?

  • Does your server ever return anything other than a JSON object? `{ ... }`

    There are some error cases where due to a bug in the server it returns a 200 code but an empty response. This is reported as error by the API. But by and large it is always JSON.

  • I'm not quite sure if I ran into the same issue as you. I use a Menu2 as initial view and tried to launch it on a GPSMap device and it threw the same error you encountered, although it supports Menu2.
    I ended up doing this:

  • Do you by any chance know how this works on the Edge devices? Is there also something like a widget carousel there?

    i don't have first hand experience with this stuff, but I do know that the latest Edges have followed suit from the watches and changed CIQ widgets to glances.

    Unlike watches, these new Edges still have the concept of widgets along with glances. As far as I can tell (based on looking at manuals for newer Edges):

    - widget = settings-related shortcuts that can be easily accessed during an activity (there's a gesture like swiping down from the top of the screen). e.g. user profile, gps, settings, enabled sensors

    - glance = health data, sensor information, activity information and CIQ glances, which are not as easily accessible during an activity (I think multiple gestures are required - go to home screen and swipe up.) Tbf, the manual also says that widgets are accessed by going to the *home screen* and swiping down, but I *think* widgets may also be accessible by swiping down during an activity? At least that's what I gathered from dev complaints about glances being less accessible than widgets, meaning they wish CIQ widgets remained widgets and didn't move to the glances section in new Edges.

    Regardless of what the UX is like for Edge widgets, I think the rules for the top level view are the same as that of watch widgets.

    You may be able to get a better idea of what it's like by looking at youtube video reviews idk.

    This is where it would've been great if the CIQ sim was more like the iOS sim (for example), in the sense that it would actually try to emulate the real OS and UI of the device but oh well.

    Looking at the manuals:


    -  I think edge 1030 only supports widgets, and it talks about a "widget loop" (same concept that the old watches had):

    www8.garmin.com/.../GUID-8932D61A-C839-4704-BB71-3C2383B43A54.html

    https://www8.garmin.com/manuals/webhelp/edge1030/EN-US/GUID-E741F23E-5A41-4490-8D17-8CB05FA626CA.html


    - I think Edge 1040 supports both widgets and glances. The widget section of the manual is more or less identical to that of the edge 1030

    www8.garmin.com/.../GUID-E741F23E-5A41-4490-8D17-8CB05FA626CA.html

    www8.garmin.com/.../GUID-3B7DBF2A-1E1E-40A2-8CF6-84128AAA4230.html


    TL;DR

    - older edges only support widgets and not glances. Widgets seem to be settings/profile-related stuff as well as ciq widgets

    - newer edges support both widgets and glances. Widgets seem to be settings/profile-related stuff. Glances seem to be health, activity, and sensor data, as well as CIQ glances

    - for both older and newer edges, native widgets seem to be more about toggles / quick access to settings (and user profile) as opposed to data? 

    - for newer edges, native glances seem to be more about data. However, since older edges don't have glances, I don't know if the data that glances provide on newer edges was provided as widgets on older edges, or if it just wasn't available at a glance. I don't know anything about edges tbh.

    - I think the rules for widgets/glances are the same for both watches and edges, even if those rules don't necessarily make sense on an edge

    - on an edge, it may or may not be more inconvenient to access glances as opposed to widgets