onTimeReset and onTimeStop. Data not saved in FIT file when calling Field.setData

Hi,

I want to save some Session data once the activity has ended, and I do it inside onTimeReset event. I save lap data too, and I do it inside onTimerLap event. This lap data has to be saved when stop button has pressed, so you can see last lap data and the total data along the activity. Something like that:

function onTimerLap() {
LapField1.setData(...);
LapField2.setData(...);
...
}

function onTimerStop() {
LapField1.setData(...);
LapField2.setData(...);
...
SessionField1.setData(...);
SessionField2.setData(...);
...
}

function onTimerReset() {
LapField1.setData(...);
LapField2.setData(...);
...
SessionField1.setData(...);
SessionField2.setData(...);
...
}

When run in simulator all works fine and the Stop an Reset events are called and the code inside then executed, as in Lap event. But when run in watch (Forerunner 735XT with last firmware update) only the Lap event is executed, and neither the Stop nor Reset events are called, or the code inside them is not executed.

There is a very strage thing about Timer events. If I copy the code inside the event to a function, and then call this function, the function is not called from inside the events. If there is some code before the function call, it's executed, but not the function calling and the code after the funcion call. And this error occurs both on simulator and watch. Function saveLapData() is not called from inside none of the events. So I have to repeat same code inside the events instead of call another funtion to do the job.

function saveLapData() {
LapField1.setData(...);
LapField2.setData(...);
...
}

function onTimerLap() {
Code here is executed properly;
saveLapData; // not executed
}

function onTimerReset() {
Code here is executed properly;
saveLapData; // not executed
SessionField1.setData(...); // not executed
SessionField2.setData(...); // not executed
...
}

I've tried with 2.x.x and 3.x.x SDK versions, and the same with all of them.

Regards,
  • The workaround is to call setData() unconditionally (every second) for your lap/session data. It’s a waste of CPU cycles, but nothing will actually be written to the file until the actual event happens (lap added, or end of activity.)

    ---
    I also had a problem with writing data in onTimerLap() (sometimes it wasn’t written, as if it was too late at that point), so I switched to just calling setData() for laps unconditionally. I have had success writing session data in onTimerStop(), tho, not in onTimerReset().

    Note that onTimerReset() doesn't get called for Forerunners (in the real device), regardless of what the sim does. When you save or discard an activity, the app just restarts (*) without calling onTimerReset(). I believe that some Fenix watches do call onTimerReset() (without restarting the app) however. And maybe Edge devices, although I really don't know for sure.

    (* As if you killed the app and ran it again.)

    You can see this by doing anything at all in onTimerReset() (like logging something) and seeing that it's never called.
    ---

    In fact, in the SDK's MoxyField sample, that is exactly how it’s done. setField is never called in the timer callbacks. setField is called for everything (record, lap, session) once per second in compute().

    I think it's too bad that the SDK documentation for setData() implies that you should not call setData() unless you have data that will actually be written right now, though, because I think it steers us in the wrong direction.
  • I'm pretty sure onTimeLap is called after the lap data is written to the .fit so when you do the setData in onTimerLap it will be used for the next lap.

    not sure if this is a typo in posting, but

    saveLapData; // not executed

    should be

    saveLapData();

    You're not calling the function without the parens
  • Yes, what Jim said. And also, to reiterate, onTimerReset() doesn't get called for many watches. To expand on my previous comment, I don't think any of this is documented very well at all. So many things in CIQ depend on looking at examples, trying things out or asking other people who've done it before.

    To be clear, setData() doesn’t actually write anything. It just sets a value to be written when the watch decides it’s time to write to the file, so I think it’s okay to call it once per second.
  • Here's a little DF project that shows what happens with onTimer* calls. Add a file named dfstate.txt in the logs directory to save the info on a watch.
  • I'm pretty sure onTimeLap is called after the lap data is written to the .fit so when you do the setData in onTimerLap it will be used for the next lap.

    not sure if this is a typo in posting, but

    saveLapData; // not executed

    should be

    saveLapData();

    You're not calling the function without the parens


    Sorry, it was an error on description. It is wright in code.
  • Many thanks all of you for the answers. I've rewrote code to save all data in compute function. Next day I run I'll test the app and tell you the results.
  • I'm waking this thread to be sure that we look into this...

    There is a very strage thing about Timer events. If I copy the code inside the event to a function, and then call this function, the function is not called from inside the events. If there is some code before the function call, it's executed, but not the function calling and the code after the funcion call. And this error occurs both on simulator and watch. Function saveLapData() is not called from inside none of the events. So I have to repeat same code inside the events instead of call another funtion to do the job.


    It sounds like an error occurred inside the onTimer.. function, and it isn't getting reported. I took a peek at the code really quick and I'm not seeing how this could be happening.
  • Travis.ConnectIQ Thanks Travis, i'm looking into trying to reproduce this.

    There is a very strage thing about Timer events. If I copy the code inside the event to a function, and then call this function, the function is not called from inside the events. If there is some code before the function call, it's executed, but not the function calling and the code after the funcion call. And this error occurs both on simulator and watch. Function saveLapData() is not called from inside none of the events. So I have to repeat same code inside the events instead of call another funtion to do the job.


    I tried reproducing this issue. I might be misunderstanding something. I'm hoping someone can clarify. Are you saying that if you execute this code:

    function onTimerLap() {
    state="Timer Lap";
    Sys.println(state);
    outside(state);
    }

    function outside(value){
    System.println("outside called by: " + value);
    }

    my outside() function won't be called when onTimerLap() executes?
    I tried this on FR735XT fw9.40 device and outside() was successfully called. i called my outside() function from all onTimer...() functions and it appeared to work for all that were executed.

    Is there something i'm missing? Would you be willing to post the code from the function that was failing to execute so I could test that to see if maybe the problem is coming from there?
  • Travis.ConnectIQ Thanks Travis, i'm looking into trying to reproduce this.



    I tried reproducing this issue. I might be misunderstanding something. I'm hoping someone can clarify. Are you saying that if you execute this code:

    function onTimerLap() {
    state="Timer Lap";
    Sys.println(state);
    outside(state);
    }

    function outside(value){
    System.println("outside called by: " + value);
    }

    my outside() function won't be called when onTimerLap() executes?
    I tried this on FR735XT fw9.40 device and outside() was successfully called. i called my outside() function from all onTimer...() functions and it appeared to work for all that were executed.

    Is there something i'm missing? Would you be willing to post the code from the function that was failing to execute so I could test that to see if maybe the problem is coming from there?


    Hi all,

    I've changed my code so much to save FIT data in every iteration inside compute() function. Session fields are stored right, but lap fields are stored in the next lap so in lap1 was stored 0, in lap2 was stored lap1 value, and so on.
    I'm going to change again and save the data like my first post, and I'll tell you again how it goes:

    function onTimerLap() {
    storeLapData()
    saveLapData();
    }

    function storeLapData() {
    // field1 stores the total amount and it's incremented in every iteration of compute()
    // lapField1 stores the difference between two consecutive laps
    lapField1 = field1 - lapField1;
    lapField2 = field2 - lapField2;
    ...
    }

    function saveLapData() {
    save FIT data here
    }
  • I attach two screen shots with total session fields (saved right values), and lap fields shifted one lap