Start Datafield with recording

Former Member
Former Member
Hi, how to begin the start of a datafield with pressing the Enter button?
I want to start at the same time the recording will start,
(e.g. the function compute(info)).
Hopefully this explanation was clear.

Thanks
  • You can check info.timerTime. If it is null, the recording session has not been started. You can also monitor that field to tell if the session is paused.
  • I'm copying a post from this thread to maintain continuity...

    but info.timerTime only starts when FIT data is simulated.

    Yes. On a device it will be non-null after the user starts their activity, and it will stop increasing when the activity is paused.


    In the simulator it will be null until you start simulating. That is just the way it works.
  • You can check info.timerTime. If it is null, the recording session has not been started. You can also monitor that field to tell if the session is paused.


    Seems like if we do this.. the way to do this is much more complicated than what I imagine.
    Esentially, I am just looking if TimerTime is increasing. If, yes I save the prev timerTime into a variable and then later compare it. if it's increasing, then it's still ongoing, if not then I reckon the activity has stopped.

    There apparently are holes in this process esp if I do some heavy CPU math calculations (I want to detect when the activity is stopped as I want to write out a LOG file) then the watch starts to skip seconds.. 1,3,5,7, etc.. and this causes a log to be written and then complicates things again.
    if ( TTSec == TTSec2 && TTSec > 0) {
    if ( flag == 0) {
    var dateInfo = Time.Gregorian.info( Time.now(), 0);
    Sys.println(dateInfo.year + "-" + dateInfo.month + "-");
    flag = 1;
    }
    } else {
    TTSec2 = TTSec;
    flag = 0;
    }
    }
  • There apparently are holes in this process esp if I do some heavy CPU math calculations (I want to detect when the activity is stopped as I want to write out a LOG file) then the watch starts to skip seconds.. 1,3,5,7, etc.. and this causes a log to be written and then complicates things again.


    I'm missing something. Are you concluding that the process of verifying that the timer is stopped is causing delays such enormous delays? It is really only an integer comparison, an integer assignment, and a boolean assignment when the timer is running. I'd say it is very unlikely to be the source of the problem.

    if ( TTSec == TTSec2 && TTSec > 0) {
    if ( flag == 0) {
    var dateInfo = Time.Gregorian.info( Time.now(), 0);
    Sys.println(dateInfo.year + "-" + dateInfo.month + "-");
    flag = 1;
    }
    } else {
    TTSec2 = TTSec;
    flag = 0;
    }



    Technically you aren't checking that the value is increasing, you're checking that it has changed and assume that it is increasing. That all seems fine and dandy. I'm assuming that you have something in place to handle TTSec being null because I think the comparison against 0 might be a problem.

    Anyway, are you sure it isn't your 'heavy CPU math calculations' that is causing the problem? I'm using the technique in datafields that are available in the store, and I do not see this behavior.

    Travis
  • You are right in all respects. i was not being clear.
    I'm doing heavy Math calculations for my Indoor Bike Trainer and the formula is a 3rd level polynomial and I need to QUAD power it to get Normalised Power (R). That is one of the things which I noticed.

    When this happens and when i do the checking, i want to write to a log file, the writing to the log file makes everything dog slow and thus skips seconds.

    I'm gonna try a different approach using MOD and checking every 10secs.
    Not sure if it will work tho.
  • Didnt work.
    somehow I can't get it to determine if the timer is increasing or otherwise and then do something with that info.
  • I'm sorry, but I don't really understand what you're saying.

    Things I believe we know...

    • When an activity is active, you're seeing the timer skip every other second.
    • You log some data in the application. This is slow, so you don't want to do it all of the time.
    • You do some math in the application. This is slow, but you do want to do this all of the time.
    • You've tried to detect when an activity session is active and this doesn't work.
    • You've tried to do logging once every 10 seconds, but this doesn't work either.


    Is all of this right?

    For item #1, it seems that we don't really know what the cause is. It sounds like you believe it is #2, but it doesn't sound like you know it isn't #3. If you disable all of the logging and just do the math, do you see the timer skip?

    For the last two items, I don't have any idea what you mean when you say they don't work. For #4, are you saying that you simply cannot detect if the timer is counting or not? That seems trivial, and I'm very surprised if you can't get it to tell you if the counter is changing or not. I believe this code should prove that the functionality does work (I just wrote it, and have not tested it, but it certainly seems correct).

    class MyDataField extends Ui.SimpleDataField {

    var mPreviousTimer;

    function initialize() {
    SimpleDataField.initialize();
    }

    function compute(info) {
    var text = null;

    // timer has not yet started or session has ended
    var currentTimer = info.timerTime;
    if (currentTimer == null) {

    if (mPreviousTimer == null) {

    text = "Not Started";

    }
    else {

    text = "Last Tick";

    }

    }

    // timer has started
    else {

    // this is the first tick of the timer in this activity session
    if (mPreviousTimer == null) {

    text = "First Tick";

    }

    // timer is ticking
    else if (mPreviousTimer != currentTimer) {

    text = "Ticking";

    }

    // timer is not ticking
    else {

    text = "Paused";

    }

    }

    mPreviousTimer = currentTimer;

    return text;
    }
    }


    Assuming that code works when tested independently, you should be able to plug it into your application pretty easily, and it should continue to work.

    As for #5, you say that doing your logging once every 10 seconds doesn't work either. What do you mean by doesn't work? Are you saying the timer still misses every other second or that it misses every 10 seconds? If it misses one second in 10, then I think it is safe to say that the math and the logging together are putting you over the threshold. If it still happens that you miss one of every other second, then it isn't the logging.

    Travis
    • When an activity is active, you're seeing the timer skip every other second.
    • You log some data in the application. This is slow, so you don't want to do it all of the time.
    • You do some math in the application. This is slow, but you do want to do this all of the time.
    • You've tried to detect when an activity session is active and this doesn't work.
    • You've tried to do logging once every 10 seconds, but this doesn't work either.




    My Answers
    • The timer is not skipping until I hit a high Speed / wattage calculation and it "possibly" takes more time to update the datafield screen. This in turn caused the chain reaction
    • I want to log the "summary" data once user stops the activity. (by default, the native save/resume/discard menu item comes out. When this happens, I want to write an output to a log
    • yes. The goal is to convert speed into Power per trainer resistance
    • I can detect activity start, but am having trouble determining when user has stopped it. I tot I figured it out, but then i started seeing timer skips
    • no. i tried checking to see if the timer is incrementing every 10sec


    This is code snippet of what I ended up with in the onupdate function
    if ( TIMER != PTIMER ) {
    DFields(dc,info);
    } else {
    DFinSess(dc,info);
    if ( flag == 0 ) {
    var DI = Time.Gregorian.info( Time.now(), 0);
    Sys.println(DI.year + "-" +
    DI.month + "-" +
    DI.day + "," +
    OF(DI.hour) + ":" + OF(DI.min) + ":" + OF(DI.sec) +
    ",Timer," + TTMin +":" + TTSec1 +
    ",ASPD," + AvgSpd + ",Dist," + Dist +
    ",NP," + NP + ",AP," + AP + ",RT," + VI
    );
    flag = 1;
    }
    }
    if (TIMER >= 1) { PTIMER = TIMER; }
    }


    This "seems" to work OK for now. Need more extensive testing..
    the "flag" is there to ensure that I only write to the log 1 time.

    the TIMER>=1 may not be needed but I'll leave it there for now.

    I can't really use the simlator to test this code out, need actual device (then again, perhaps usage of a FIT file would do it, but I didn't try and only used the simulator to "simulate data")

    resultant..

    1) I use my trainer along with the Speed to power Curve
    2) I do conversion from speed to power
    3) I do calculation for Normalised Power (r) and Average Power as well as Variable Index(R) which I call Ratio (RT)
    4) at the end of the activity, when I press stop, the default data screen would change from displaying current data to showing Activity Summary as well as write a log file with the resultant data as CSV

    basically a poor man's attempt at training with Power. I use the Activity summary screen to take a picture to be uploaded into Strava :-p since we can't yet write the custom data into the FIT file.

    Hope the above is clear.. Thanks a bunch!

    I may move this to an actual app later on as I would like to calculate my Aerobic Decoupling and Efficiency Factor (http://help.trainingpeaks.com/hc/en-us/articles/204071724-Aerobic-Decoupling-and-Efficiency-Factor) but seems like 16kb is WAY too little for me to use to get these calculated.

    367BikeFields-Turbo --> https://apps.garmin.com/en-US/apps/ad65c289-aac9-49e8-8532-638f85596bbc
  • state as Activity.Info attribute?

    It would be nice if Garmin could provide the state of the application as a attribute of Activity.Info.
    The Activity knows about the state, so why calculating in every datafield again?
    Instead of a property it could also be implemented as methods for start/stop which could be overwritten in the appBase class.

    @Garmin: would that be possible in a comming SDK-version? I would be happy and many others, too.
  • If you compare the current {SDKROOT}/bin/api.db with that of previous versions, you'll see what appears related to what you're looking for.

    onTimerLap 8389751
    onTimerPause 8389749
    onTimerReset 8389752
    onTimerResume 8389750
    onTimerStart 8389747
    onTimerStop 8389748