Integrating Training Status into Watchface

Hi all,
I'm currently working on developing a Watchface and would like to integrate the Training Status feature. I've already searched through the Garmin Connect IQ API but couldn't find clear instructions on how to access the Training Status.
Could someone please assist me and explain how I can integrate the Training Status into my Watchface? Are there specific methods or functions in the API that I can use?
Thanks.

  • If you're developing for newer touchscreen watches that support CIQ 4.2.0 (e.g. Fenix 7, Forerunner 165/255/265/955/965, Vivoactive 5, Venu 2/3, Epix Gen 2), then you can use the Complications feature to get the training status as a string.

    Overview: [https://developer.garmin.com/connect-iq/core-topics/complications/]

    API doc: [https://developer.garmin.com/connect-iq/api-docs/Toybox/Complications.html]

    - Full list of supported devices is on this page

    - Search for: COMPLICATION_TYPE_TRAINING_STATUS

  • Thank you for the response. How can I access the training status data? I've selected the Complication Subscriber permission in the manifest file, but I'm unable to retrieve the training status using Complications.getComplication(26). Are there any additional steps or settings I need to configure to access it?

  • See the sample posted in https://forums.garmin.com/developer/connect-iq/f/discussion/349473/simple-example-wf-that-shows-a-bunch-of-things

    There, the complication for HR is used on devices with complications, but it's basically the same for this.

  • I'm unable to retrieve the training status using Complications.getComplication(26)

    26 (or Complications.COMPLICATION_TYPE_TRAINING_STATUS) isn't a Complications.Id (as required by getComplication()), it's a number. So I would expect that to either crash at runtime (if type checking is disabled) or to trigger a type check error at compile time.

    This is a Complications.Id:

    var trainingStatusComplicationsId = new Complications.Id(Complications.COMPLICATION_TYPE_TRAINING_STATUS);

    Here's a partial example:

    App:

    import Toybox.Application;
    import Toybox.Lang;
    import Toybox.WatchUi;
    import Toybox.Complications;
    
    class ComplicationFaceApp extends Application.AppBase {
        function initialize() {
            AppBase.initialize();
        }
    
        var trainingStatusComplicationId;
        function onStart(state as Dictionary?) as Void {
            trainingStatusComplicationId = new Complications.Id(Complications.COMPLICATION_TYPE_TRAINING_STATUS);
            Complications.registerComplicationChangeCallback(self.method(:onComplicationChanged));
            Complications.subscribeToUpdates(trainingStatusComplicationId);
        }
    
        function onComplicationChanged(complicationId as Complications.Id) as Void {
            if (ComplicationFaceView != null && complicationId == trainingStatusComplicationId) {
                try {
                    var complication = Complications.getComplication(complicationId);
                    System.println("complication value = " + complication.value);
                    complicationFaceView.updateTrainingStatus(complication.value);
                } catch (e) {
    
                }
            }
        }
    
        var complicationFaceView;
        function getInitialView() as Array<Views or InputDelegates>? {
            complicationFaceView = new ComplicationFaceView();
            return [ complicationFaceView ] as Array<Views or InputDelegates>;
        }
    }
    

    Layout xml:

    <layout id="WatchFace">
        <label id="TrainingStatusLabel" x="center" y="center" font="Graphics.FONT_LARGE" justification="Graphics.TEXT_JUSTIFY_CENTER" color="Graphics.COLOR_BLUE" />
    </layout>

    View:

    import Toybox.Graphics;
    import Toybox.Lang;
    import Toybox.System;
    import Toybox.WatchUi;
    
    class ComplicationFaceView extends WatchUi.WatchFace {
    
        function initialize() {
            WatchFace.initialize();
        }
    
        function onLayout(dc as Dc) as Void {
            setLayout(Rez.Layouts.WatchFace(dc));
        }
    
        var trainingStatus = null;
    
        function onUpdate(dc as Dc) as Void {
            if (trainingStatus != null) {
                var view = View.findDrawableById("TrainingStatusLabel") as Text;
                // '"" +' is leftover code from when this was used for heart rate (which is a number)
                view.setText("" + trainingStatus); 
            }
            View.onUpdate(dc);
        }
    
        function updateTrainingStatus(updatedTrainingStatus) {
            trainingStatus = updatedTrainingStatus;
            WatchUi.requestUpdate();
        }
    }

    Note that this doesn't seem to work properly in the sim (SDK 6.4.2). The returned training status is always "No Result" even when it's changed via Settings > Set Training Status. Hopefully it works on a real watch (haven't given it a try yet.)

    However, the same code works as expected in the simulator with Complications.COMPLICATION_TYPE_HEART_RATE (for example).

  • I'm in a reverse situation; it works in the simulator, but on the watch, the watch face crashes.

  • On the watch, you can find the crash logs in the apps/logs/ciq_log.* files and see what happened.

    If you installed from the app store, also check your ERA reports.

  • I've looked into it, but I must admit it doesn't help. Apparently, there seems to be an issue with the initialize method.

    Should the code in ComplexWF work if I simply replace "hrId = new Id(Complications.COMPLICATION_TYPE_HEART_RATE);" with "new Id(Complications.COMPLICATION_TYPE_TRAINING_STATUS);" in line 86 of the ComplexWFView class?   

    When I do that, it works in the simulator but crashes on the watch. I'm getting the same error messages.

  • What device?  It could be that COMPLICATION_TYPE_TRAINING_STATUS isn't available on that device.  What is the error message you see?

  • It is a Venu 2 Plus. 

    This is the error message:

    Error: Unhandled Exception
    Time: 2024-04-04T14:24:38Z
    Part-Number: 006-B3851-00
    Firmware-Version: '17.04'
    Language-Code: deu
    ConnectIQ-Version: 4.2.3
    Filename: ComplexWF
    Appname: ComplexWF
    Stack:
      - pc: 0x10000ba4
        File: 'C:\Users\**\Documents\ComplexWF\source\ComplexWFView.mc'
        Line: 88
        Function: initialize
      - pc: 0x100000f7
        File: 'C:\Users\**\Documents\ComplexWF\source\ComplexWFApp.mc'
        Line: 36
        Function: getInitialView
  • That's with COMPLICATION_TYPE_TRAINING_STATUS and not HR, correct? And no other changes?

    And HR works for you?