getActivityInfo() Data Type

I'm trying to use getActivityInfo to get the elapsed time and I'm reached the limit of my hacking ability.

The following code returns an unexpected type error for the line where elapseSec = elapseSec / 1000;

What data type is the activityInfo.elapsedTime returning? Can someone point me in the right direction here?

using Toybox.WatchUi as Ui;
using Toybox.Application as App;
using Toybox.System as Sys;
using Toybox.Activity as Act;


class blahView extends Ui.View {

var activityInfo;
var elapseSec=0;

function onUpdate(dc) {
activityInfo = Act.getActivityInfo();
elapseSec = activityInfo.elapsedTime;
elapseSec = elapseSec / 1000;
}
}
  • It's a Toybox.Time.Duration object. I may have over-thought this one.

    -Alpha Monkey
  • I'm okay with it being an object type, provided that the documentation indicates what it actually is (or the types it might be). I've written a helper function that just prints the type of an object, and I'm already kinda tired of using it.
  • I was trying to avoid adding object metadata because it quickly explodes the size of the executable, but without it does cause developer pain. In preview 2 there will be some basic metadata that you can use on the simulator but will be stripped out of the final executable. I'm hoping it goes some distance towards making Monkey C development a little less painful.

    -Alpha Monkey
  • I was trying to avoid adding object metadata because it quickly explodes the size of the executable

    Wha? Documentation affects the size of the resulting binary?
  • Documentation doesn't affect the binary size, but reflection data (runtime available symbol names) blow up the size of the binary by quite a bit. That's the reason we don't have any reflection functions built into Monkey C at this point.

    -Alpha Monkey
  • After some more debug on this...

    The root of the problem was that I needed to start the Fit Data Simulate button in the Simulator before running the code. It does return a number once I did that in the correct order. It crashes the code again just as soon as I stop the Fit Data Simulate.

    This leads to a different problem though. The getActivityInfo() does not seem to return a null when the FitData Simulate is stopped. I use the following code to trap this, but it seems like the null check should be sufficient.

    Is this just an issue where the simulator acts different than the watch?

    if ( activityInfo != null) //Should be null if the activity is not running, but the simulator doesn't work that way
    {
    if (activityInfo.elapsedTime instanceof Toybox.Lang.Number) // Should be able to remove this check on the watch. Simulator doesn't return null when Fit Data Simulate is stopped
    {
    elapseSec = activityInfo.elapsedTime / 1000;
    hr = elapseSec/3600;
    min = elapseSec/60%60;
    sec = elapseSec%60;
    Sys.println(elapseSec);
    }
    }
  • I have the same issue: I have code which I copied from an example which crashes the simulator unless the Fit Data Simulate button is pressed before running the code and I also get an error if you stop the simulation as follows:

    File pushed successfully
    Connection Finished
    Closing shell and port
    Found Transport: tcp
    Connecting...
    Connecting to device...
    Device Version 0.1.0
    Device id 1 name "A garmin device"
    Shell Version 0.1.0
    Failed invoking <symbol>
    Unexpected Type Error
    @PC = 0x10000030
    Unexpected Type Error
    Unexpected Type Error


    Any ideas?
  • What about creating a boolean variable initially set to true called "timerStopped".  Set the variable to true when the timer starts and set it false again when the timer stops.  That's what I had to do.  It's a lame workaround, but it works...

  • The original issue was that there was no null check when accessing the elapsedTime field.

    elapseSec = activityInfo.elapsedTime;
    elapseSec = elapseSec / 1000;
    
    // ...

    should have been written as:

    if (activityInfo.elapsedTime != null) {
        elapseSec = activityInfo.elapsedTime;
        elapseSec = elapseSec / 1000;
        
        // ...
    }

    If you are building for a device with ConnectIQ 2.1.0 support, there is the timerState flag. You should be able to use this to tell what the timer state is.

  • And in the case of a device app and not a data field, the app is the one that does the pause, so the app knows the state.