How to properly end an activity session

Former Member
Former Member
Hi,

I am trying to add the ability to restart an activity again in my app (it's a triathlon app where I would like to trigger the end of the first sport and have it start the next activity automatically, but be able to manually reset the start time if I miss my target transition time).
I am using source code from lucramod's awesome TriathlonDuathlonAquathlon. In which the following functions control the start and end of each activity.

function onBegin() {
if( disciplineSession == null ) {
var logtxt = Lang.format("Starting $1$ ($2$ :: $3$)", [stageNames[currentStage], stageSports[currentStage], stageSubSports[currentStage]]);
Sys.println(logtxt);
startTime = Sys.getTimer();
if( TriData.currentDiscipline == 0 || TriData.currentDiscipline == 2 || TriData.currentDiscipline == 4 ){
disciplineSession = Rec.createSession( { :name=>stageNames[currentStage], :sport=>stageSports[currentStage], :subsport=>stageSubSports[currentStage] } );
if( disciplineSession != null )
{
var starttrue = false;
do{
starttrue = disciplineSession.start();
}
while(starttrue == false);

}
}
}
}

function onEnd() {
Sys.println("Saving");
endTime = Sys.getTimer();
if( TriData.currentDiscipline == 0 || TriData.currentDiscipline == 2 || TriData.currentDiscipline == 4 ){
if( disciplineSession != null && disciplineSession.isRecording() )
{
var stoptrue = false;
var savetrue = false;
do{
stoptrue = disciplineSession.stop();
}
while(stoptrue == false);

do {
savetrue = disciplineSession.save();
}
while( savetrue == false );


disciplineSession = null;
Ui.requestUpdate();
}
}
disciplineSession = null;
}


I have added the function :
function onReset() {
Sys.println("Resetting");
endTime = Sys.getTimer();
if( TriData.currentDiscipline == 0 || TriData.currentDiscipline == 2 || TriData.currentDiscipline == 4 ){
if( disciplineSession != null && disciplineSession.isRecording() )
{
var stoptrue = false;
var discardtrue = false;
do{
stoptrue = disciplineSession.stop();
}
while(stoptrue == false);
do {
discardtrue = disciplineSession.discard();
}
while( discardtrue == false );

disciplineSession = null;
Ui.requestUpdate();
}
}
disciplineSession = null;

}


I manually call onReset using a button press before triggering onBegin. This seems to work fine in the simulator but creates corrupt files when run on a watch. The corruption occurs with the reset activity and no further activities are recorded, although the app on the watch does continue to display activity time etc.

My question is, is there anything obviously wrong with the way I have finished and discarded the activity recording. My current thought is that the the corruption is caused because there is not enough of a delay between resetting the activity and starting the new one. In which case is there a better way of resetting the start time of an activity?

Thanks,
Jon
  • I've not really looked at the code, but you're not doing any kind of a delay. In fact, with the base code and what you added, it looks to be trying to use spinlocks, such as:

    whle(discardtrue==false);

    CIQ is single threaded, so on this line, if discardtrue is false at that time, it will always be false, and the watchdog will trigger, and the app will crash.

    The same with the loops in onBegin() and onEnd().

    With things like stop() and save(), they will return when they are complete, and if they return false, they will likely always return false, and the watchdog will trip The do/while is unneeded, and you may want to treat the a "false" as a fatal error, and not something to re-try.

    If you do want a delay for some reason, you'll want to use a timer.

    so for your function, this is all you need. Maybe add a return of "stoptrue and discardtrue" of you want the caller to handle the error state.

    Also, for something like this, you may want to note the device you tested on, and maybe the FW version, as things might work differently, (maybe for native multi-sport support or not, as an example)

    disiplineSession.stop();
    disiplineSession.discard();

    maybe catch the return from the calls, if you want the caller to handle the error case