Invalid field size in some samples files

Hi,

I just downloaded the latest version of FIT SDK(FitSDKRelease_21.141.00.zip). Then check the sample files included in it with the FIT protocol. Then I find some of them have invalid field size.

The protocol indicates that for a definition message, there will be several field definition. If the field type is 2, then it is a uint8 so its size should be 1. But the actual field size is 4.

For example:

1. In activity_multisport.fit, the 6th definition message is:

Global Message Num: 19. Field Count: 28. Dev Field Count: 0

The 19th field(starting from 0) has the following value:

- pFieldDef 
num 0x66 'f' unsigned char
size 0x04 '\x4' unsigned char
type 0x02 '\x2' unsigned char

All other definition messages(totally 4, including the above one) in this file with global message num 19 and field count 28 will have this issue. 

And definition message with global message num 19 and field count 27 will have the same issue in 18th field definition.

The similar cases occur in the following sample files:

05/08/2024 02:03 AM 136,846 activity_lowbattery.fit
05/08/2024 02:03 AM 3,195 activity_multisport.fit
05/08/2024 02:03 AM 56,694 activity_poolswim_with_hr.fit
05/08/2024 02:03 AM 25,121 HrmPluginTestActivity.fit
05/08/2024 02:03 AM 2,087 MonitoringFile.fit
05/08/2024 02:03 AM 82 Settings.fit
05/08/2024 02:03 AM 170 WeightScaleMultiUser.fit
05/08/2024 02:03 AM 90,970 WithGearChangeData.fit

So why these file do not follow the FIT protocol?

Thanks

  • MesgNum 19: lap

    FieldNum 0x66 (102): avg_left_power_phase

    Its value is an array of uint8, how to determine: defsize%typesize ≈ 4%1 == 0 (true), how many element: 4/1=4, it means [4]uint8

    Ref: developer.garmin.com/.../

    The Size indicates the size of the defined field in bytes. The size may be a multiple of the underlying FIT Base Type size indicating the field contains multiple elements represented as an array.

  • Thank you. Then how to know if a field is an array? Based on the field type, it does not indicate whether the data is one element or several element array.

    And based on the fit_example.c below:

    static const FIT_LAP_MESG_DEF lap_mesg_def =
    {
    0, // reserved_1
    FIT_ARCH_ENDIAN, // arch
    FIT_MESG_NUM_LAP, // global_mesg_num
    84, // num_fields
    { // field_def_num, size, base_type
    FIT_LAP_FIELD_NUM_TIMESTAMP, (sizeof(FIT_DATE_TIME)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_START_TIME, (sizeof(FIT_DATE_TIME)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_START_POSITION_LAT, (sizeof(FIT_SINT32)*1), FIT_BASE_TYPE_SINT32,
    FIT_LAP_FIELD_NUM_START_POSITION_LONG, (sizeof(FIT_SINT32)*1), FIT_BASE_TYPE_SINT32,
    FIT_LAP_FIELD_NUM_END_POSITION_LAT, (sizeof(FIT_SINT32)*1), FIT_BASE_TYPE_SINT32,
    FIT_LAP_FIELD_NUM_END_POSITION_LONG, (sizeof(FIT_SINT32)*1), FIT_BASE_TYPE_SINT32,
    FIT_LAP_FIELD_NUM_TOTAL_ELAPSED_TIME, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TOTAL_TIMER_TIME, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TOTAL_DISTANCE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TOTAL_CYCLES, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TOTAL_WORK, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TOTAL_MOVING_TIME, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TIME_IN_HR_ZONE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TIME_IN_SPEED_ZONE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TIME_IN_CADENCE_ZONE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_TIME_IN_POWER_ZONE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_ENHANCED_AVG_SPEED, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_ENHANCED_MAX_SPEED, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_ENHANCED_AVG_ALTITUDE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_ENHANCED_MIN_ALTITUDE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_ENHANCED_MAX_ALTITUDE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,
    FIT_LAP_FIELD_NUM_MESSAGE_INDEX, (sizeof(FIT_MESSAGE_INDEX)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_TOTAL_CALORIES, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_TOTAL_FAT_CALORIES, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_SPEED, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MAX_SPEED, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_POWER, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MAX_POWER, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_TOTAL_ASCENT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_TOTAL_DESCENT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_NUM_LENGTHS, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_NORMALIZED_POWER, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_LEFT_RIGHT_BALANCE, (sizeof(FIT_LEFT_RIGHT_BALANCE_100)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_FIRST_LENGTH_INDEX, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_STROKE_DISTANCE, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_NUM_ACTIVE_LENGTHS, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_ALTITUDE, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MAX_ALTITUDE, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_GRADE, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_AVG_POS_GRADE, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_AVG_NEG_GRADE, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_MAX_POS_GRADE, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_MAX_NEG_GRADE, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_AVG_POS_VERTICAL_SPEED, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_AVG_NEG_VERTICAL_SPEED, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_MAX_POS_VERTICAL_SPEED, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_MAX_NEG_VERTICAL_SPEED, (sizeof(FIT_SINT16)*1), FIT_BASE_TYPE_SINT16,
    FIT_LAP_FIELD_NUM_REPETITION_NUM, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MIN_ALTITUDE, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_WKT_STEP_INDEX, (sizeof(FIT_MESSAGE_INDEX)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_OPPONENT_SCORE, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_STROKE_COUNT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_ZONE_COUNT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_VERTICAL_OSCILLATION, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_STANCE_TIME_PERCENT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_STANCE_TIME, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_PLAYER_SCORE, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_TOTAL_HEMOGLOBIN_CONC, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MIN_TOTAL_HEMOGLOBIN_CONC, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MAX_TOTAL_HEMOGLOBIN_CONC, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_SATURATED_HEMOGLOBIN_PERCENT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MIN_SATURATED_HEMOGLOBIN_PERCENT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_MAX_SATURATED_HEMOGLOBIN_PERCENT, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_AVG_VAM, (sizeof(FIT_UINT16)*1), FIT_BASE_TYPE_UINT16,
    FIT_LAP_FIELD_NUM_EVENT, (sizeof(FIT_EVENT)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_EVENT_TYPE, (sizeof(FIT_EVENT_TYPE)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_AVG_HEART_RATE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_MAX_HEART_RATE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_AVG_CADENCE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_MAX_CADENCE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_INTENSITY, (sizeof(FIT_INTENSITY)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_LAP_TRIGGER, (sizeof(FIT_LAP_TRIGGER)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_SPORT, (sizeof(FIT_SPORT)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_EVENT_GROUP, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_SWIM_STROKE, (sizeof(FIT_SWIM_STROKE)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_SUB_SPORT, (sizeof(FIT_SUB_SPORT)*1), FIT_BASE_TYPE_ENUM,
    FIT_LAP_FIELD_NUM_GPS_ACCURACY, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_AVG_TEMPERATURE, (sizeof(FIT_SINT8)*1), FIT_BASE_TYPE_SINT8,
    FIT_LAP_FIELD_NUM_MAX_TEMPERATURE, (sizeof(FIT_SINT8)*1), FIT_BASE_TYPE_SINT8,
    FIT_LAP_FIELD_NUM_MIN_HEART_RATE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_AVG_FRACTIONAL_CADENCE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_MAX_FRACTIONAL_CADENCE, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_TOTAL_FRACTIONAL_CYCLES, (sizeof(FIT_UINT8)*1), FIT_BASE_TYPE_UINT8,
    FIT_LAP_FIELD_NUM_MIN_TEMPERATURE, (sizeof(FIT_SINT8)*1), FIT_BASE_TYPE_SINT8,
    }
    };

    The 19th field is below:

          FIT_LAP_FIELD_NUM_ENHANCED_MIN_ALTITUDE, (sizeof(FIT_UINT32)*1), FIT_BASE_TYPE_UINT32,

    it is a 4-byte UINT32.

    Also how you find the field number definition in SDK?

  • The document used for code generation is Profile.xlsx that comes along with the FitSDKRelease_21.141.00.zip, you may grasp some knowledges from it even though how to read the file it's not that straightforward. For details and how the generation works I'll leave it for somebody from Garmin to answer. I hope it helps. 

  • Thank you. If I am correct, the profile and message definitions are different from version to version. So the message definition for one version may not suitable for another?

    I just check Profile.xlsx, and find the 19th field in lap message as below:

    19 avg_power uint16 watts total_power / total_timer_time if non_zero_avg_power otherwise total_power / total_elapsed_time 1

    So it seems it is neither a 8-bit field, nor a 4 element array of 8-bit, also not a 32bit field. But a 16 bit field?

  • AFAIK, there will only be addition for new releases, what's changed will be published in their release notes: forums.garmin.com/.../news-announcements

  • 19 here is the field number, not the global mesg num. The field that you were looking for is 0x66 (102 in base10) which is avg_left_power_phase. 

  • OK. I see. I can see this field in profile is shown a '[N]' in array column, indicating it can be an array. Is there a way to know if a field can be array without looking up on the profile?