Subcategories

  • Discussion about suunto plus development

    45 Topics
    481 Posts
    S
    Environment Watch: Suunto Vertical 2, firmware 2.53.42 (HW 1424B3) 3 SuuntoPlus apps enabled (my own app, main.js ~7.8 KB minified, plus Weather and Movement) Device logs available; reproduced across many sessions Symptom The trigger is repeatedly toggling one app off and on inside the SuuntoPlus enable/disable menu, without leaving that menu. Do this a few times in a row and the re-enable intermittently fails: the script load aborts, the firmware force-unloads the other enabled zapps trying to free memory, then disables my app — and the watch UI becomes unresponsive for ~45 seconds to a minute (it recovers on its own or with the USB cable). The key observation: the moment I leave the enable/disable menu, everything is fine again. Leaving the menu is exactly what triggers the JS discard (Evidence 1 below), which frees the leaked contexts — so a toggle followed by a menu exit never fails; only repeated in-menu toggling does. I have reproduced this while an activity was recording; the device logs below are from those sessions. Evidence from device logs 1. JS discard runs when all zapps are disabled together — but not on a single-app disable. All-disable path (discard runs): 15:37:14 : EVT APPLICATION : Zapp climbl01:Disable 15:37:14 : EVT APPLICATION : Zapp zzmoveen:Disable 15:37:14 : EVT APPLICATION : Zapp zzwethen:Disable 15:37:14 : EVT UI_FRAMEWORK : JS discard disable zapps 15:37:14 : EVT UI_FRAMEWORK : JS will discard Single-app disable → re-enable (no discard anywhere in between): 15:40:35 : EVT APPLICATION : Zapp climbl01:Disable 15:40:35 : EVT ANALYTICS : Zapp disabled i:5 n:Climb Log 15:40:38 : EVT APPLICATION : Zapp climbl01:Load script 15:40:38 : EVT APPLICATION : Zapp climbl01:Enable 2. When the freeze hits, it is an allocation-failure storm during Load script — before any app code runs. Failing toggle (single disable, no discard, re-enable 3 s later): 22:08:15 : EVT APPLICATION : Zapp climbl01:Disable 22:08:18 : EVT APPLICATION : Zapp climbl01:Load script 22:08:18 : ERR APPLICATION : Zapp:relMemCb (exec:zapp) 22:08:18 : EVT APPLICATION : Zapp zzwethen:Disable 22:08:18 : ERR APPLICATION : Zapp 3:RelMem->unload 22:08:18 : EVT APPLICATION : Zapp zzmoveen:Disable 22:08:18 : ERR APPLICATION : Zapp 3:RelMem->unload 22:08:18 : ERR APPLICATION : Zapp:RelMem->None avail 22:08:18 : ERR DUKTAPE : JSalloc:2095 ... 58 failed allocations within this ONE second: JSalloc:1964 x44, JSalloc:2392 x11, JSalloc:2095 x3 ... 22:08:18 : ERR DUKTAPE : Compiling js failed: Error: 1 22:08:18 : WRN APPLICATION : Script load:other 22:08:18 : EVT APPLICATION : Zapp climbl01:Disable So the anatomy of the failure is: the loader burns through 58 failed ~2 KB allocations within one second, gives up (Compiling js failed: Error: 1), and the firmware disables the app it was asked to enable — after having force-unloaded the two other zapps mid-storm (RelMem->unload) without that freeing a usable block. The watch UI was unusable for the next ~45 seconds. What happened afterwards in the same log is just as telling: 22:09:02 : EVT APPLICATION : Zapp climbl01:Load script 22:09:02 : EVT APPLICATION : Zapp climbl01:Enable (retry, ZERO failures) 22:09:12 : EVT APPLICATION : Zapp climbl01:Disable 22:09:14 : EVT APPLICATION : Zapp climbl01:Load script 22:09:14 : EVT APPLICATION : Zapp climbl01:Enable The re-enable at 22:09:02 succeeded with zero allocation failures — nothing changed in between, the retry just worked (this self-healing is consistent across my sessions). The next toggle (22:09:12) produced a second, smaller burst (JSalloc:2392 x7, JSalloc:2412 x1) but the compile recovered within the same load and enabled fine — so a burst is survivable; fatal is only the case where the loader gives up. 3. In the same session, every toggle whose disable logged a JS discard re-enabled cleanly. The three toggle cycles in the minutes right before (disables at 22:06:10, 22:07:32, 22:07:58) each show JS discard disable zapps at the disable and re-enabled without a single allocation failure; the one cycle whose disable logged no discard (22:08:15) is exactly the one that stormed. 4. The failure threshold scales with main.js size — and with nothing else in the app. I isolated the variable with three builds of the same app — identical manifest, identical data store, identical templates and ext files; only main.js changed — all driven through the same pattern (repeated in-menu disable → re-enable, no discard in between): main.js (minified) rapid single-toggle result 7.8 KB (production) fails on the 1st no-discard re-enable (the storm of Evidence 2) 4.0 KB (stripped) 4 clean cycles (1–5 s each), stuck on the 5th (second failure mode, below) 0.27 KB (stub) 19 consecutive clean cycles at ~1/s — indistinguishable from the stock apps The stock apps themselves (~0.5–1.3 KB main.js) never fail at any toggle rate — I rapid-toggled Weather 15 times at ~1 s spacing as a control, every cycle instant. The 4.0 KB build also exposed a second failure mode where the loader never even starts: the disable is logged, and then no Load script appears at all — no JSalloc, no error — for ~45 s, after which the enable completes on its own. While that enable was stuck, the Weather control toggled right through the stuck window, every cycle instant. This is exactly what accumulating un-discarded JS contexts predict — each single-disable leaks one context, a bigger main.js leaves a bigger dead context and needs bigger compile buffers — and it rules out the manifest, settings/variables, data store, and templates as carriers (the 0.27 KB stub ships all of them unchanged and never fails). 5. The leaked context also breaks the next session’s save — dose-dependently. The un-discarded context doesn’t only block the re-enable; it lingers and starves the next ~2 KB contiguous allocation the app makes. After one or more in-menu re-enables during an activity, ending the exercise storms on the same allocation class — this time the failure fires at my end-of-session evalFile (before any of that code runs), the firmware again force-unloads both co-apps, and the UI freezes ~50 s: 17:08:02 : EVT APPLICATION : Zapp climbl01:Disable (single disable, no discard -> leaked context) 17:08:04 : EVT APPLICATION : Zapp climbl01:Enable (re-enable succeeds) ...normal activity, then end the exercise... 17:08:24 : EVT UI_FRAMEWORK : evalFile: .../ext11.js from ui 17:08:24 : ERR APPLICATION : Zapp:relMemCb (exec:zapp) 17:08:24 : ERR APPLICATION : Zapp 3:RelMem->unload (Weather + Movement force-unloaded) 17:08:24 : ERR APPLICATION : Zapp:RelMem->None avail 17:08:24 : ERR DUKTAPE : JSalloc:2137 (x11 -> ~52 s freeze) It is dose-dependent: with two leaked contexts a comparable end recovered after 3 failures; with more accumulated, it took 11 failures and a ~52 s freeze. So the missing discard has a second, downstream cost — a normal end-of-session allocation that is reliable on a fresh/discarded heap fails once un-discarded contexts have piled up. Analysis (proven vs. inferred) Proven from logs: JS discard is only ever logged on the all-zapps-disable path (and on exercise stop), never after a single-app disable. The failure is the script loader failing to allocate ~2 KB blocks (JSalloc:1964/2095/2392) during Load script, i.e. while compiling the app — before any of the app’s own code executes. Force-unloading the other zapps mid-storm does not resolve it (RelMem->None avail continues). A burst of failed allocations is survivable; the fatal case is the loader giving up entirely (Compiling js failed: Error: 1), after which the firmware disables the app. A plain retry ~45 s later succeeds with zero failures — the memory needed is available again without any discard in between. Inferred (my best explanation, happy to be corrected): Without the discard, the disabled app’s dead JS context stays in the shared Duktape heap, leaving it fragmented. Small scattered allocations still succeed at that moment (my app’s localStorage.getObject reads work fine), but the loader’s ~2 KB contiguous compile buffers cannot be placed. After exercise stop — where the discard does run — the same app always re-enables cleanly, which also points at the missing discard rather than plain memory exhaustion. Minimal reproduction Enable 3 SuuntoPlus apps (any activity running). Open the SuuntoPlus enable/disable menu → disable one app, then re-enable it — without leaving the menu. Repeat step 2 a few times, staying in the menu the whole time. Within a handful of in-menu toggles the re-enable storms / freezes (roughly 1 in 6 in my sessions). Leaving the menu at any point clears it. Workarounds I found: leave the enable/disable menu between toggles (this triggers the discard and never fails), or — after a failed enable — simply toggle again, which has so far always succeeded. Questions Is skipping the JS discard on a single-zapp disable intentional, or a bug? If intentional: could the firmware run the discard (or a heap compaction) on single-zapp disable too? That would remove this freeze entirely. Is there official guidance on the JS heap budget and fragmentation behaviour when multiple SuuntoPlus apps are enabled? The apizone docs don’t cover memory. I have full device logs of both the discard asymmetry and the failing Load script storm and am happy to share them or file this through another channel if preferred. Thanks a lot — the platform is great fun to develop for, and this is the last blocker I haven’t been able to engineer around from the app side.
  • Discussions about S+ WatchFaces

    64 Topics
    1k Posts
    N
    @Egika I’m running the latest firmware if I’m not mistaken 2.53.42
  • Discussions about S+ Sports Apps - watch apps which extend functionality of your watch sport modes

    202 Topics
    3k Posts
    Łukasz SzmigielŁ
    2.14 (2026-07-07) The heart-rate zone bar and trend chart now react right away in workouts without speed data — indoor sessions, or while waiting for a GPS fix — where they could previously lag behind by a couple of minutes. The view you selected stays selected after lap and other watch overlays, and the trend keeps averaging smoothly through them. Shows – instead of STABLE until there is enough data to judge your effort. Also, I’ve spammed 30+ manual laps and cycled through screens like mad and all is stable as a rock. Just didn’t manage to breake the app or the watch.
  • How/where/who to ask for new suunto+ integration

    3
    1 Votes
    3 Posts
    1k Views
    Michele SellaM
    @Muhammed-Fasil garmin is getting support for bosch ebike from 04/05/2026. I’d also at least like to know if someone at suunto is working on it or users will need to apply to partner program and do their self. I really hope that bosch will transmit data over standard protocol and not a special link to allow just garmin to do it. At today Riva bike fest a bosch guy told me it is standard bluetooth 5.0 but it was not a tech guy so i would not trust that affermation too much.
  • Watchface Updates?

    2
    0 Votes
    2 Posts
    400 Views
    EgikaE
    @Nordic_Panda yes, exactly like this.
  • 3rd party widgets support

    Moved
    7
    5 Votes
    7 Posts
    2k Views
    Ondřej DeingruberO
    @Egika I am looking for a way specifically how to run a 3rd party app outside a activity, it feels silly to open an activity to check your todo-list or other app that might be more connected do casual daily activities.

Suunto Terms | Privacy Policy