Skip to content

Commit

Permalink
Add support for chained fit files
Browse files Browse the repository at this point in the history
From the SDK:
> The FIT protocol allows for multiple FIT files to be chained together
> in a single FIT file. Each FIT file in the chain must be a properly
> formatted FIT file (header, data records, CRC).

The implementation is to note the total filesize when first loading the
file, then check if there's more data after we finish processing the
number of bytes the initial header specifies. If there is more data, try
to parse it as a fit header, then continue as normal.
  • Loading branch information
pR0Ps committed May 26, 2017
1 parent 9473218 commit e39980a
Showing 1 changed file with 23 additions and 10 deletions.
33 changes: 23 additions & 10 deletions fitparse/base.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import io
import os
import struct

from fitparse.processors import FitFileDataProcessor
Expand All @@ -25,17 +26,14 @@ def __init__(self, fileish, check_crc=True, data_processor=None):
self._file = open(fileish, 'rb')

self.check_crc = check_crc

self._accumulators = {}
self._bytes_left = -1 # Not valid until after _parse_file_header()
self._complete = False
self._compressed_ts_accumulator = 0
self._crc = 0
self._local_mesgs = {}
self._messages = []
self._processor = data_processor or FitFileDataProcessor()

# Start off by parsing the file header (makes self._bytes_left valid)
# Get total filesize
self._file.seek(0, os.SEEK_END)
self._filesize = self._file.tell()
self._file.seek(0, os.SEEK_SET)

# Start off by parsing the file header (sets initial attribute values)
self._parse_file_header()

def __del__(self):
Expand Down Expand Up @@ -89,6 +87,16 @@ def _read_and_assert_crc(self, allow_zero=False):
# Private Data Parsing Methods

def _parse_file_header(self):

# Initialize data
self._accumulators = {}
self._bytes_left = -1
self._complete = False
self._compressed_ts_accumulator = 0
self._crc = 0
self._local_mesgs = {}
self._messages = []

header_data = self._read(12)
if header_data[8:12] != b'.FIT':
raise FitParseError("Invalid .FIT File Header")
Expand Down Expand Up @@ -122,10 +130,15 @@ def _parse_message(self):
if self._bytes_left <= 0:
if not self._complete:
self._read_and_assert_crc()

if self._file.tell() >= self._filesize:
self._complete = True
self.close()
return None

return None
# Still have data left in the file - assuming chained fit files
self._parse_file_header()
return self._parse_message()

header = self._parse_message_header()

Expand Down

0 comments on commit e39980a

Please sign in to comment.