So I took the plunge on 7-16-2023 and downloaded version 21.115 of their SDK, release date June 20, 2023.
-rw-r--r-- 1 tom tom 9964330 Jul 16 17:42 FitSDKRelease_21.115.00.zipNot that big really. They say it includes code for C, C++, C#, Java, JavaScript, Objective-C, and Python.
The "C" subdirectory has an "examples directory with encode.c and decode.c. The code is provided along with Visual Studio "accessory files". It could be interesting (as an experiment) to copy the decode.c and the various support files into a directory and try to work up a Makefile to build it under linux and see how that develops.
It turned out to be a 5 minute job with no surprises:
# 7-16-2023 # Tom Trebisky # Makefile for the Garmin SDK decode.c example under linux OBJS = decode.o fit_convert.o fit_crc.o fit.o fit_example.o decode: $(OBJS) cc -o decode $(OBJS)Interestingly, two files were not required:
fit_product.c fit_ram.cRunning it, I get:
./decode usage: decode.exeThis message is funny, as this file came from my Garmin66i and every other open source FIT utility I have run on it works just fine../decode /home/tom/c.fit Testing file conversion using /home/tom/c.fit file... File is not FIT.
Digging a bit deeper, I see that two calls are made to FitConvert_Read
They return:
0 -- FIT_CONVERT_CONTINUE 5 -- FIT_CONVERT_DATA_TYPE_NOT_SUPPORTEDHow far do I want to go with buggy code release by Garmin?
The file "decoder.py" has an entry point "read()" in the Decoder class.
Anyway, let's just try this before spending any time with possible buggy code:
I create the file "tom" in the "py" directory as follows:
#!/bin/python from garmin_fit_sdk import Decoder, Stream #path = "Activity.fit" path = "/home/tom/c.fit" stream = Stream.from_file(path) decoder = Decoder(stream) messages, errors = decoder.read() print(errors) print(messages)It works! The output is by no means neat and organized, but I can see valid data from my FIT file in the blob of ascii that it spews out.
Looking at decoder.py, this is nice clean code, well written, and a pleasure to look through.
I add to the above demo program:
!/bin/python from garmin_fit_sdk import Decoder, Stream path = "/home/tom/c.fit" stream = Stream.from_file(path) decoder = Decoder(stream) messages, errors = decoder.read() # list ne = len(errors) # hash nm = len(messages) print ( f"{ne} errors" ) print ( f"{nm} messages" ) print ( messages.keys()) # dict_keys(['file_id_mesgs', 'file_creator_mesgs', 'device_info_mesgs', 'record_mesgs', 'event_mesgs', 'lap_mesgs', 'session_mesgs', 'activity_mesgs']) for k in messages.keys() : print ( f"{k} -- {len(messages[k])}" ) # 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 for m in messages["event_mesgs"] : print ( m ) rm = messages["record_mesgs"] m = rm[0] print ( m )I get output like this:
{'timestamp': datetime.datetime(2023, 7, 12, 20, 40, 30, tzinfo=datetime.timezone.utc), 'data': 0, 'event': 'timer', 'event_type': 'start', 'event_group': 0, 'timer_trigger': 'manual'} {'timestamp': datetime.datetime(2023, 7, 13, 10, 25, 25, tzinfo=datetime.timezone.utc), 'data': 0, 'event': 'timer', 'event_type': 'stop_all', 'event_group': 0, 'timer_trigger': 'manual'} {'timestamp': datetime.datetime(2023, 7, 12, 20, 40, 30, tzinfo=datetime.timezone.utc), 'position_lat': 378104392, 'position_long': -1322736078, 'enhanced_speed': 0.12, 'enhanced_altitude': 2211.2, 'altitude': 12607.0, 'speed': 65.535, 'temperature': 27}
Tom's backpacking pages / tom@mmto.org