Fit Contributor MESG_TYPE_SESSION does not show up in Fit file

I am a bit stuck with displaying an average value in the summary. I am using MESG_TYPE_SESSION for this as shown in the code below.

The recording for the data works fine with MESG_TYPE_RECORD.

Simulator does not create the MESG_TYPE_SESSION fields. I also tried it on my watch: Does not work neither - there is nothing displayed in the summary but graphs from recording are nice.

Unfortunately, I could not find an answer in the forums. Do you have any idea?

// In 'class AppDelegate extends WatchUi.BehaviorDelegate' calling this 'onSelect()' if '(session != null) && (session.isRecording() != false)'
    var fieldStrideLengthAvg = session.createField("stride_length_avg", 3, FitContributor.DATA_TYPE_FLOAT, { :mesgType=>FitContributor.MESG_TYPE_SESSION, :units=>"m" });
    fieldStrideLengthAvg.setData(avgStrideLength);
    session.stop();
    session.save();

// In fitContributions.xml:
    <fitField id="3"
	sortOrder="4"
	precision="2"
	chartTitle="@Strings.chart_title_stride_length_avg"
	dataLabel="@Strings.data_label_stride_length_avg"
	unitLabel="@Strings.unit_label_stride_length_avg"
	displayInActivityLaps="true"
	displayInChart="true"
	displayInActivitySummary="true"
	fillColor="#0E73AD" />

  • You have to create all FIT fields, even SESSION fields, before you start recording.

  • I changed the order of creating the fields:

    function onSelect() {
       	if (Toybox has :ActivityRecording) { 
    		if ((session == null) || (session.isRecording() == false)) {
       	        // Start session:
    	       	session = createSession();  // Own function to create session
    		    if (session != null) {
    		        createFields();         // Own function to create fields
    		   		session.start();
    		    }
    	    }
    	    else {
                saveAvgSessionData();       // Own function to save 
                App.stopRecording(true);    // Own funciton to stop recording and remove session
    	    }
       	}
       	return true;
    }
    
    function createFields() {
    	if (session != null && !session.isRecording()){
    	    // ... Some recording fit fields: ...
    		fieldStrideLength = session.createField("stride_length", 1, FitContributor.DATA_TYPE_FLOAT, { :mesgType=>FitContributor.MESG_TYPE_RECORD, :units=>"m" });
    		// ... Some session fit fields: ...
    		fieldStrideLengthAvg = session.createField("stride_length_avg", 3, FitContributor.DATA_TYPE_FLOAT, { :mesgType=>FitContributor.MESG_TYPE_SESSION, :units=>"m" });
    	}
    }
    
    // Stride length is recorded every second...
    
    function saveAvgSessionData() {
        // ... Calcutlate avgStrideLength ...
    	fieldStrideLengthAvg.setData(avgStrideLength);
    }

    However, I still cannot see the average stride length data in my fit files... :(

  • Try calling saveAvgSessionData() every second (or as often as you write RECORD data). It's counter-intuitive, but setData() only queues the *next* value to be written, and you may be calling it too late here.

    (You can see an example of this in the SDK's MoxyField sample, although it's a data field and not a device app.)

  • I just tried that. Did also not work :/

    Am I correct that the session data collected here should be added to the fit file at the end where it says "Data,13,session,timestamp ..."?

    I am getting annoyed by this problem... Is there any other reason why it should not show up in the fit file?

  • I have just checked that if I replace MESG_TYPE_SESSION by MESG_TYPE_RECORD, then it is correctly recorded in the fit file as record data. Hence, there must be some issue with the Session. Could it be that I am leaving the session in a strange way that does not allow saving the session data correctly?

  • When you are at the end, do you do both session.stop() and session.save()?

  • What does App.stopRecording(true) do?

    Does it call ActivityRecording.Session.save()?

  • Yes. App.stopRecording(save) stops the session and saves it if save is set true:

    class App extends Application.AppBase {
    
        // ...
        
        function stopRecording(save) {
    		if( Toybox has :ActivityRecording ) {
                if ((session != null) && session.isRecording()) {
    		       	session.stop();
    		       	if (save) {
    			   		session.save();
    			   	}
    			   	else {
    			   		session.discard();
    			   	}
    			    session = null;
    		    }
            }
        } 
        
    }

  • Make sure to do the session.stop() before the session.save()

    is looks like if isRecording is false (the session is stopped) you won't do the save.

  • This was the issue! :D Yesterday, I have just added an extra stop for the menu selection option which calls session.stop() before calling App.stopRecording(true)

    Thanks!

    .. what a stupid mistake ..