1212from fitparse .processors import FitFileDataProcessor
1313from fitparse .profile import FIELD_TYPE_TIMESTAMP , MESSAGE_TYPES
1414from fitparse .records import (
15- DataMessage , FieldData , FieldDefinition , DevFieldDefinition , DefinitionMessage , MessageHeader ,
16- BASE_TYPES , BASE_TYPE_BYTE , DevField ,
15+ Crc , DataMessage , FieldData , FieldDefinition , DevFieldDefinition , DefinitionMessage , MessageHeader ,
16+ BASE_TYPES , BASE_TYPE_BYTE ,
1717 add_dev_data_id , add_dev_field_description , get_dev_type
1818)
19- from fitparse .utils import calc_crc , fileish_open , FitParseError , FitEOFError , FitCRCError , FitHeaderError
19+ from fitparse .utils import fileish_open , FitParseError , FitEOFError , FitCRCError , FitHeaderError
2020
2121
2222class FitFile (object ):
2323 def __init__ (self , fileish , check_crc = True , data_processor = None ):
2424 self ._file = fileish_open (fileish , 'rb' )
2525
2626 self .check_crc = check_crc
27+ self ._crc = None
2728 self ._processor = data_processor or FitFileDataProcessor ()
2829
2930 # Get total filesize
@@ -55,34 +56,40 @@ def _read(self, size):
5556 if size <= 0 :
5657 return None
5758 data = self ._file .read (size )
58- self ._crc = calc_crc (data , self ._crc )
59+ if size != len (data ):
60+ raise FitEOFError ("Tried to read %d bytes from .FIT file but got %d" % (size , len (data )))
61+
62+ if self .check_crc :
63+ self ._crc .update (data )
5964 self ._bytes_left -= len (data )
6065 return data
6166
6267 def _read_struct (self , fmt , endian = '<' , data = None , always_tuple = False ):
63- fmt_with_endian = "%s%s" % (endian , fmt )
68+ if fmt .startswith ('<' ) or fmt .startswith ('>' ):
69+ # fmt contains endian
70+ fmt_with_endian = fmt
71+ else :
72+ fmt_with_endian = "%s%s" % (endian , fmt )
6473 size = struct .calcsize (fmt_with_endian )
6574 if size <= 0 :
6675 raise FitParseError ("Invalid struct format: %s" % fmt_with_endian )
6776
6877 if data is None :
6978 data = self ._read (size )
7079
71- if size != len (data ):
72- raise FitEOFError ("Tried to read %d bytes from .FIT file but got %d" % (size , len (data )))
73-
7480 unpacked = struct .unpack (fmt_with_endian , data )
7581 # Flatten tuple if it's got only one value
7682 return unpacked if (len (unpacked ) > 1 ) or always_tuple else unpacked [0 ]
7783
7884 def _read_and_assert_crc (self , allow_zero = False ):
7985 # CRC Calculation is little endian from SDK
80- crc_expected , crc_actual = self ._crc , self ._read_struct ('H' )
81-
82- if (crc_actual != crc_expected ) and not (allow_zero and (crc_actual == 0 )):
83- if self .check_crc :
84- raise FitCRCError ('CRC Mismatch [expected = 0x%04X, actual = 0x%04X]' % (
85- crc_expected , crc_actual ))
86+ crc_computed , crc_read = self ._crc .value , self ._read_struct (Crc .FMT )
87+ if not self .check_crc :
88+ return
89+ if crc_computed == crc_read or (allow_zero and crc_read == 0 ):
90+ return
91+ raise FitCRCError ('CRC Mismatch [computed: %s, read: %s]' % (
92+ Crc .format (crc_computed ), Crc .format (crc_read )))
8693
8794 ##########
8895 # Private Data Parsing Methods
@@ -94,7 +101,7 @@ def _parse_file_header(self):
94101 self ._bytes_left = - 1
95102 self ._complete = False
96103 self ._compressed_ts_accumulator = 0
97- self ._crc = 0
104+ self ._crc = Crc ()
98105 self ._local_mesgs = {}
99106 self ._messages = []
100107
0 commit comments