Some basic questions about understanding FIT formats and the SDK enumeration

I'm working on writing some workout FIT files using a language that is not supported by the SDK.  Since my use case is primarily just for workouts, I thought I could wade through the documentation and understand how to build them.

Unfortunately I'm a bit stuck finding the appropriate data in the documentation.  Here's a sample of a workout fit file that I'm stuck trying to understand.

         x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
     0 : 0e 10 4d 08 ce 03 00 00 2e 46 49 54 29 b7 40 00 [..M......FIT).@.]
    10 : 00 00 00 07 03 04 8c 04 04 86 07 04 86 01 02 84 [................]
    20 : 02 02 84 05 02 84 00 01 00 00 3c 92 68 24 e8 d4 [..........<.h$..]
    30 : 3a 3e ff ff ff ff 01 00 fe ff ff ff 05 40 00 00 [:>...........@..]
    40 : 31 00 03 02 14 07 00 02 84 01 01 02 00 00 00 00 [1...............]
    50 : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [................]
    60 : 00 00 00 00 40 00 00 1a 00 0c 05 04 8c 08 20 07 [....@......... .]
    70 : 0a 04 86 06 02 84 07 02 84 0c 02 84 0e 02 84 04 [................]
    80 : 01 00 09 01 00 0b 01 00 0d 01 00 0f 01 00 00 20 [............... ]
    90 : 00 00 00 52 75 6e 20 57 6f 72 6b 6f 75 74 00 6e [...Run Workout.n]
    A0 : 6f 74 65 73 00 00 00 00 00 01 01 00 00 00 20 00 [otes.......... .]
    B0 : 03 09 01 00 00 00 00 03 00 ff ff ff ff ff ff 01 [................]
    C0 : 01 ff ff ff 40 00 00 1b 00 0f 00 10 07 02 04 86 [....@...........]
    D0 : 04 04 86 05 04 86 06 04 86 08 c8 07 fe 02 84 0a [................]

So you have the file header:

         x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
     0 : 0e 10 4d 08 ce 03 00 00 2e 46 49 54 29 b7 [..M......FIT).]

Then right after it there's the definition message

         x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf
     0 : 40 00 00 00 00 07 [@.....]

This indicates there's 7 fields following the first 6 bytes, correct?

Field: 03 04 8c
Field: 04 04 86
Field: 07 04 86
Field: 01 02 84
Field: 02 02 84
Field: 05 02 84
Field: 00 01 00

So if this is correct so far, each 3 bytes are: the Field Definition Number, how many bytes are needed, type of variable.

  1. Do the bytes needed, directly follow the 3 bytes?
  2. Unfortunately it's not at all clear to me how to find the meaning of these 3 bytes. The SDK overview just says see the File Enum and each language has its own way of sorting these out and it would take me a while to walk through the code to understand what its doing.

I'm hoping a little nudge in the right direction will quickly help me figure out how to encode/decode these messages.

  • Take a look at the Protocol documentation. https://developer.garmin.com/fit/protocol/ 

    The first byte of each record indicates if the record is a message definition or data. If it is a data record the header byte will also indicate which message definition to use to interpret the data. That is a 4 bit value, so there can only be 16 definitions in play at anytime. The idea is that it is a one to many message definition record to data record, and that the local message type (0-15) may be reused if there is the need for more than 16 message definitions. 

    You probably find yourself stepping through the decoder for one of the existing SDKs to figure a few things out too.

  • Thanks for the help. In the case I posted, it's a definition message and I'm wondering how to interpret what is going on and if I'm understanding how it's parsed correctly.  (see my 2 questions).

    Also how does the definition message define a local message type and associate it to a specific FIT message?

  • Thanks I've used that website too.  One of the biggest problems I'm having is find a resource that spells out the enumeration clearly.  For example in the Profile.xlsx that comes in the SDK for FIT 21.101 there is no list for the value for message names.  Like file_id = 0, capabilities = 1... etc.  There seems to be no definitive set of definitions. The Profile.xlsx is good for field definitions but I feel like I'm going crazy trying to piece all the specs together and I can't seem to find a message name list. So I feel like I'm missing something...

  • In Profile.xlsx on the Types tab is the mesg_num list. That is the list of message numbers.

  • Tabs...of course. I was going crazy.

  • By the way, what does it mean if there are items lacking a field definition number:

    file_id
    0 type file
    1 manufacturer manufacturer
    2 product uint16
    favero_product favero_product
    garmin_product garmin_product
    3 serial_number uint32z
    4 time_created date_time
    5 number uint16
    8 product_name string

    Like favero_product and garmin_product?

  • Search this page for "Dynamic Fields", although they are more commonly referred to as sub-fields. 
    https://developer.garmin.com/fit/protocol/

    Sub-fields allow for an alternative interpretation of the main field based on the value of a reference field in the same message. The reference fields column columns are missing from the table above, but the garmin_product sub-field and the favero_product sub-field used the manufacturer field as their reference. In the case of the garmin_product field, when the manufacturer field is Garmin, then the product field should be interpreted using the properties of the garmin_product sub-field.

    A more interesting example can be found in the target_value and duration_value fields in the workout_step message. The sub-fields use different scales and units to reinterpret the value in the main field. 

    Sub-fields are meant as a way to keep the file compact by allowing a single field to hold similar but mutually exclusive values.