Getting settings from Garmin Connect

Sorry to start a new thread on tis but the "Reply" button wasn't working...

Anyway, I've been trying to get app settings from Garmin Connect into a Data Field which I've written (it's my first attempt at this, so apologies for the inept code) and getting the settings from GCM causes the datafield to crash.  The intended use of the datafield requires settings to be changed "in the field", maybe several times in a given ride so I can't rely on carefully chosen defaults.

I've stripped the code down to the bare minimum to try to work out what's going on and I have the following:

settings.xml

<resources>
<properties>

<property id="CloseMinute" type="number">30</property>

</properties>

<settings>


<setting propertyKey="@Properties.CloseMinute" title="@Strings.CloseMinute">
<settingConfig type="numeric" min = "0" max = "59"/>
</setting>


</settings>
</resources>

AudaxDevApp.mc

using Toybox.Application;

class AudaxDevApp extends Application.AppBase {

function initialize() {
AppBase.initialize();


AppBase.initialize();

}

// onStart() is called on application start up
function onStart(state) {
}

function onSettingsChanged() {


CloseMinute = Application.getApp().getProperty("CloseMinute");

}

// onStop() is called when your application is exiting
function onStop(state) {
}

// Return the initial view of your application here
function getInitialView() {
return [ new AudaxDevView() ];
}

}

AudaxDevView.mc

using Toybox.WatchUi;
using Toybox.Time;
using Toybox.System as Sys;
using Toybox.Activity;
using Toybox.Application;

class AudaxDevView extends WatchUi.SimpleDataField {

var CloseMinute = 30;

var OutputType = 11;

// Set the label of the data field here.
function initialize() {
SimpleDataField.initialize();
label = "My Label";
}


function compute(info) {
// See Activity.Info in the documentation for available information.

if (CloseMinute == null) {
OutputType = 1;
} else if (CloseMinute instanceof Number) {
OutputType = 2;
} else if (CloseMinute instanceof Long) {
OutputType = 3;
} else if (CloseMinute instanceof Float) {
OutputType = 4;
} else if (CloseMinute instanceof Double) {
OutputType = 5;
} else if (CloseMinute instanceof String) {
OutputType = 6;
} else {
OutputType = 7;
}

return OutputType;

}
}

As you can see there's no maths so no chance of dividing by zero, as far as I can see the only output to the datafield should be a number corresponding to whatever type the variable CloseMinute actually is.  I was expecting that whatever the getProperty() call returned from GCM there should be an output corresponding to what it is an instance of - even if it is 7 to indicate "none of the above".

On running the datafield it returns a value of "2" which indicates that it is a number, but as soon as I update the setting from GCM the whole datafield (including the label) goes blank.  This suggests to me that it's actually getting the property/setting from GCM that's causing the crash.

This is doubly frustrating as the actual datafield runs exactly as I intend with variables at their initialised (but not updated) values, but this isn't really much use as timings for every ride are different.

  • Have you looked in garmin\apps\logs at the ciq_log file?  If you crashed the details are there.

  • Not sure if you've left this out of the code you posted above, but I don't see a <strings> section in your properties, yet you reference at least one?

    From what you've posted, it looks like you need to add:

    <strings>
    <string id="CloseMinute_S">Some meaningful description</string>
    </strings>
    and change this reference (note the different ID - I don't think you can use the same ID for strings and keys):
    <setting propertyKey="@Properties.CloseMinute" title="@Strings.CloseMinute_S">
    I'm not sure if this could cause the issue you're experiencing, but CIQ can be finicky sometimes....
    One other thing...
    I noticed you're only reading settings in the onSettingsChanged() function.  What about also during app startup (initialize() )?
  • I have a <strings> section as follows:

    <strings>
    <string id="AppName">AudaxDev</string>
    <string id="PacerSpeed">Minimum Speed</string>
    <string id="LastTime">Control Close Time</string>
    <string id="CloseHour">Hr</string>
    <string id="CloseMinute_S">Min</string>
    <string id="AudaxDev">AudaxDev</string>

    </strings>

    I assume that unused strings don't cause a problem.........

    As you can see, I've changed the id for the string which is referenced in the <settings> section to CloseMinute_S and also changed the name in the <settings>:

    <setting propertyKey="@Properties.CloseMinute" title="@Strings.CloseMinute_S">

    Result is the same - crash when settings called from GCM.

    I'm not reading settings at startup but just taking initialised values, this is why the data field works OK when I'm testing it with the initialisation values as known input.  In practice I need to input specific timing details before the start of each ride as every ride is different, 

  • ---
    Error: Symbol Not Found Error
    Details: "Could not find symbol '0000000f'"
    Time: 2021-02-16T21:23:05Z
    Part-Number: 006-B3011-00
    Firmware-Version: '5.30'
    Language-Code: eng
    ConnectIQ-Version: 3.2.4
    Store-Id: 042629e9-069d-4c61-83b6-39cd3c4dc7cb
    Store-Version: 11
    Filename: C2FCEC47
    Appname: AudaxDev
    Stack:
    - pc: 0x10000167

    I'm afraid it's well beyond me to understand what this all means, apart from the date and time.

  • You can try tweaking your code as follows so you can gather more information:

    1) Read settings at init time (so it's easier to test)

    2) Print out type of "CloseMinute" (that you just read from settings) in your data field

    Your current test is only showing that you initialized CloseMinute to a number in your init code, which you already know. At least this way you can verify that an initial read of the setting works (or doesn't)

    var CloseMinute;
    
    function initialize() {
      // temporary code to figure out what you're reading from properties
      // (initialize() is guaranteed to run before compute())
      CloseMinute = Application.getApp().getProperty("CloseMinute");
    }
    
    function compute() {
        var OutputType = 0;
        if (CloseMinute == null) {
            OutputType = 1;
        //...
    
        return OutputType;
    }

    If this code doesn't crash, then you've narrowed it down to onSettingsChanged().

    You could add System.println() statements before and after the code that you assume is crashing, in order to see if it's really crashing on that line.

    function onSettingsChanged() {
        System.println("before getProperty");
        CloseMinute = Application.getApp().getProperty("CloseMinute");
        System.println("after getProperty");
    }

    Follow these instructions to get a log file with your println output:

    developer.garmin.com/.../