July 17, 2023

Garmin FIT files - Structure of a FIT file

By adding my own print() statements to the decoder in the Garmin python SDK, I obtained the output below:

The file begins with a header and ends with a 2 byte CRC.

It is important to distinguish records and messages. The file is a bunch of records. These records have different types, which leads to messages.

Inside of that sandwich we have 2 kinds of records. There are definition records and message records. Other records are possible, but don't occur in the FIT file from my Garmin 66i that I am using for this exercise.

We first get a definition record, then one or more message records for which that definition applies.

The python code generates a "format string" for the python "unpack()" function. These are instructive as they show (below) the layout of the various message records. The "<" indicates that the data is little endian. "I" is a 4 byte unsigned integer, "H" is a 2 byte unsigned integer, and "B" is a 1 byte unsigned integer. A "b" os a signed byte, and "i" is a signed 4 byte integer. A number can precide a type letter to indicate that it is repeated. The code "s" indicates a character string. This would generally be preceded by a count, so apparently ome case below is just a single character, the other is a 20 byte string.

Note that we get 8 types of messages. The bulk of the file is the 1175 "record messages"

The first definition (and message) is global type 0, which is "file_id_mesgs". This must be the first message in the file.

TJT - file header
TJT -- record is definition
TJT - message_size = 19
TJT - format string = <IIIHHHB
TJT -- record is message
TJT -- record is definition
TJT - message_size = 23
TJT - format string = <20sHB
TJT -- record is message
TJT -- record is definition
TJT - message_size = 52
TJT - format string = <IIIIIIIHHHHHBBBBBBB6BB
TJT -- record is message
TJT -- record is definition
TJT - message_size = 40
TJT - format string = <IiiIIIIIHHBBbB
TJT -- record is message
 -- 1175 messages
TJT -- record is definition
TJT - message_size = 11
TJT - format string = <IIBBB
TJT -- record is message
 -- 2 messages
TJT -- record is definition
TJT - message_size = 95
TJT - format string = <IIiiiiIIIIiiiiIIIIHHHHHHBBBBBBBBBBB
TJT -- record is message
TJT -- record is definition
TJT - message_size = 102
TJT - format string = <IIiiIIIIiiiiiiIIIIHHHHHHHHBBBBBBBBBBBBsB
TJT -- record is message
TJT -- record is definition
TJT - message_size = 18
TJT - format string = <IIIHBBBB
TJT -- record is message
TJT - read final CRC (2 bytes)

0 errors
8 messages
dict_keys(['file_id_mesgs', 'file_creator_mesgs', 'device_info_mesgs', 'record_mesgs', 'event_mesgs', 'lap_mesgs', 'session_mesgs', 'activity_mesgs'])
file_id_mesgs -- 1
file_creator_mesgs -- 1
device_info_mesgs -- 1
record_mesgs -- 1175
event_mesgs -- 2
lap_mesgs -- 1
session_mesgs -- 1
activity_mesgs -- 1

Have any comments? Questions? Drop me a line!

Tom's backpacking pages / tom@mmto.org