diff --git a/fitparse/base.py b/fitparse/base.py index 6af6392..8204fcb 100644 --- a/fitparse/base.py +++ b/fitparse/base.py @@ -348,6 +348,7 @@ def _parse_definition_message(self, header): def _parse_raw_values_from_data_message(self, def_mesg): # Go through mesg's field defs and read them raw_values = [] + raw_values_pos = [] for field_def in def_mesg.field_defs + def_mesg.dev_field_defs: base_type = field_def.base_type is_byte = base_type.name == 'byte' @@ -355,6 +356,7 @@ def _parse_raw_values_from_data_message(self, def_mesg): struct_fmt = str(int(field_def.size / base_type.size)) + base_type.fmt # Extract the raw value, ask for a tuple if it's a byte type + filepos1=self._filesize-self._bytes_left-2 try: raw_value = self._read_struct( struct_fmt, endian=def_mesg.endian, always_tuple=is_byte, @@ -374,7 +376,8 @@ def _parse_raw_values_from_data_message(self, def_mesg): raw_value = base_type.parse(raw_value) raw_values.append(raw_value) - return raw_values + raw_values_pos.append(filepos1) + return raw_values, raw_values_pos @staticmethod def _resolve_subfield(field, def_mesg, raw_values): @@ -420,12 +423,12 @@ def _parse_data_message_components(self, header): raise FitParseError('Got data message with invalid local message type %d' % ( header.local_mesg_num)) - raw_values = self._parse_raw_values_from_data_message(def_mesg) + raw_values, raw_values_pos = self._parse_raw_values_from_data_message(def_mesg) field_datas = [] # TODO: I don't love this name, update on DataMessage too # TODO: Maybe refactor this and make it simpler (or at least broken # up into sub-functions) - for field_def, raw_value in zip(def_mesg.field_defs + def_mesg.dev_field_defs, raw_values): + for field_def, raw_value, raw_value_pos in zip(def_mesg.field_defs + def_mesg.dev_field_defs, raw_values, raw_values_pos): field, parent_field = field_def.field, None if field: field, parent_field = self._resolve_subfield(field, def_mesg, raw_values) @@ -486,6 +489,7 @@ def _parse_data_message_components(self, header): parent_field=parent_field, value=value, raw_value=raw_value, + filepos=raw_value_pos, ) ) @@ -539,10 +543,15 @@ def get_messages(self, name=None, with_definitions=False, as_dict=False): if with_definitions: # with_definitions implies as_dict=False as_dict = False + # this is the position of the start of the first message + filepos=self._filesize-self._bytes_left-2 + self.recpos=[ filepos ] names = self._make_set(name) while not self._complete: message = self._parse_message() + filepos=self._filesize-self._bytes_left-2 # points to next byte in file + self.recpos.append(filepos) # last byte of this record if self._should_yield(message, with_definitions, names): yield message.as_dict() if as_dict else message diff --git a/fitparse/records.py b/fitparse/records.py index f9149e4..68d8271 100644 --- a/fitparse/records.py +++ b/fitparse/records.py @@ -168,7 +168,7 @@ def __str__(self): class FieldData(RecordBase): - __slots__ = ('field_def', 'field', 'parent_field', 'value', 'raw_value', 'units') + __slots__ = ('field_def', 'field', 'parent_field', 'value', 'raw_value', 'units', 'filepos') def __init__(self, *args, **kwargs): super(FieldData, self).__init__(self, *args, **kwargs) @@ -224,12 +224,14 @@ def as_dict(self): 'name': self.name, 'def_num': self.def_num, 'base_type': self.base_type.name, 'type': self.type.name, 'units': self.units, 'value': self.value, 'raw_value': self.raw_value, + 'filepos': self.filepos, } def __repr__(self): return '' % ( self.name, self.value, ' [%s]' % self.units if self.units else '', self.def_num, self.type.name, self.base_type.name, self.raw_value, + self.filepos, ) def __str__(self):