Welcome Guest,Register Now
Log In

ANT Forum

Welcome guest, please Login or Register

   

Mesg.Write() bug, maybe…

Rank

Total Posts: 3

Joined 2015-12-17

PM

I wrote a FIT file utility a few weeks ago for stripping out GPS data from FIT activity files from my Garmin Edge25 when I'm using it on a static trainer and I forget to turn off GPS.

I've just purchased a Garmin Forerunner 230 and I'm getting a NullReferenceException exception thrown when my utility writes the modified FIT data to a new FIT activity file using the Encode.Write() method. The message text is "Object reference not set to an instance of an object."

Then I realised that it doesn't matter whether I alter any of the data in the file or not, simply reading the FIT file using the Decode class and then immediately writing it again using the Encode class fails with the same exception.

After a bit of debugging, I think I can see what's going wrong...

The point of failure is in Mesg.Write() when it's called with the final DeviceInfo message in the Forerunner 230 FIT activity file. At this point, the message definition for a DeviceInfo message contains an entry for a field with a field Num of 15 but this field isn't in this message and also isn't in the field definition created by the Profile class. This means that when Mesg.Write() calls GetField() (see code below) around line 251 in Mesg.cs, a null is returned so Profile.GetField() is called to create a blank field but it also returns a null because it doesn't know anything about this field. The null is added to the fields collection and it's this null that causes the Write() method to fail.

foreach (FieldDefinition fieldDef in mesgDef.GetFields())
            
{
                Field field 
GetField(fieldDef.Num);
                if (
field == null)
                
{
                    field 
Profile.GetField(this.NumfieldDef.Num);
                    
fields.Add(field);
                


The question is, why is field ID#15 in the field definition ? If I look at the activity file then I can see that there are a couple of DeviceInfo messages early in the file:

OnMesgReceived Mesg with global ID#23, its name is DeviceInfo
 
Field0 Index0 ("Timestamp" Field#253) Value: 819276807 (raw value 819276807)
 
Field1 Index0 ("SerialNumber" Field#3) Value: 3914514626 (raw value 3914514626)
 
Field2 Index0 ("Manufacturer" Field#2) Value: 1 (raw value 1)
 
Field3 Index0 ("Product" Field#4) Value: 2157 (raw value 2157)
 
Field4 Index0 ("SoftwareVersion" Field#5) Value: 3.2 (raw value 320)
 
Field5 Index0 ("DeviceIndex" Field#0) Value: 0 (raw value 0)
 
Field6 Index0 ("SourceType" Field#25) Value: 5 (raw value 5)
OnMesgReceived Mesg with global ID#23, its name is DeviceInfo
 
Field0 Index0 ("Timestamp" Field#253) Value: 819276807 (raw value 819276807)
 
Field1 Index0 ("SerialNumber" Field#3) Value: 925379282 (raw value 925379282)
 
Field2 Index0 ("CumOperatingTime" Field#7) Value: 55072 (raw value 55072)
 
Field3 Index0 ("unknown" Field#15) Value: 7805 (raw value 7805)
 
Field4 Index0 ("unknown" Field#16) Value: 361 (raw value 361)
 
Field5 Index0 ("unknown" Field#24) Value: 24652498 (raw value 24652498)
 
Field6 Index0 ("Manufacturer" Field#2) Value: 13 (raw value 13)
 
Field7 Index0 ("Product" Field#4) Value: 2 (raw value 2)
 
Field8 Index0 ("SoftwareVersion" Field#5) Value: 3 (raw value 300)
 
Field9 Index0 ("DeviceIndex" Field#0) Value: 1 (raw value 1)
 
Field10 Index0 ("DeviceType" Field#1) Value: 120 (raw value 120)
 
Field11 Index0 ("unknown" Field#9) Value: 96 (raw value 96)
 
Field12 Index0 ("AntNetwork" Field#22) Value: 1 (raw value 1)
 
Field13 Index0 ("SourceType" Field#25) Value: 1 (raw value 1) 


Note that the second message contains an unknown field with an ID of 15. So, presumably, the processing of this message is causing a field with Num=15 to be added to the field definition for the DeviceInfo message. And this in turn, because field Num=15 isn't in the Profile for the DeviceInfo message, causes Profile.GetField() to return a null instead of a field.

My temporary fix is to create a blank field similar to the one specified by the field definition:

foreach (FieldDefinition fieldDef in mesgDef.GetFields())
            
{
                Field field 
GetField(fieldDef.Num);
                if (
field == null)
                
{
                    field 
Profile.GetField(this.NumfieldDef.Num);
                    if (
field == null)
                    
{
                        field 
= new Field("Unknown"fieldDef.NumfieldDef.Type1.0f0.0fstring.Empty, false);
                    
}

                    fields
.Add(field);
                


I'm not sure whether this should be considered a bug or not but it doesn't seem unreasonable to expect that using the Decode and Encode classes to read a FIT file and write its contents to a new file without any changes should work and it doesn't.      
RankRank

Total Posts: 34

Joined 2013-01-28

PM

Hi Steve,

Thanks for reporting the issue you found. You have identified a bug which will occur in the case where you decode a message from an SDK that has fields defined that are not public. There will be an official fix for this in the next release 16.60.

For the time being it will look something like:

foreach (FieldDefinition fieldDef in mesgDef.GetFields())
            
{
                Field field 
GetField(fieldDef.Num);
                if (
field == null)
                
{
                    field 
Profile.GetField(this.NumfieldDef.Num);
                    if (
field != null)
                    
{
                        fields
.Add(field);
                    
}
                    
else
                    
{
                        
//Field is not defined in the Profile, continue
                        
continue;
                    
}
                }
             
//Code below continues to reference field object
             
//end of foreach