def _parse_definition_message(self, header): # Read reserved byte and architecture byte to resolve endian endian = '>' if self._read_struct('xB') else '<' # Read rest of header with endian awareness global_mesg_num, num_fields = self._read_struct('HB', endian=endian) mesg_type = MESSAGE_TYPES.get(global_mesg_num) field_defs = [] for n in range(num_fields): field_def_num, field_size, base_type_num = self._read_struct('3B', endian=endian) # Try to get field from message type (None if unknown) field = mesg_type.fields.get(field_def_num) if mesg_type else None base_type = BASE_TYPES.get(base_type_num, BASE_TYPE_BYTE) if (field_size % base_type.size) != 0: warnings.warn( "Invalid field size %d for field '%s' of type '%s' (expected a multiple of %d); falling back to byte encoding." % ( field_size, field.name, base_type.name, base_type.size) ) base_type = BASE_TYPE_BYTE # If the field has components that are accumulators # start recording their accumulation at 0 if field and field.components: for component in field.components: if component.accumulate: accumulators = self._accumulators.setdefault(global_mesg_num, {}) accumulators[component.def_num] = 0 field_defs.append(FieldDefinition( field=field, def_num=field_def_num, base_type=base_type, size=field_size, )) dev_field_defs = [] if header.is_developer_data: num_dev_fields = self._read_struct('B', endian=endian) for n in range(num_dev_fields): field_def_num, field_size, dev_data_index = self._read_struct('3B', endian=endian) field = self.get_dev_type(dev_data_index, field_def_num) dev_field_defs.append(DevFieldDefinition( field=field, dev_data_index=dev_data_index, def_num=field_def_num, size=field_size )) def_mesg = DefinitionMessage( header=header, endian=endian, mesg_type=mesg_type, mesg_num=global_mesg_num, field_defs=field_defs, dev_field_defs=dev_field_defs, ) self._local_mesgs[header.local_mesg_num] = def_mesg return def_mesg
def _parse_definition_message(self, header): # Read reserved byte and architecture byte to resolve endian endian = '>' if self._read_struct('xB') else '<' # Read rest of header with endian awareness global_mesg_num, num_fields = self._read_struct('HB', endian=endian) mesg_type = MESSAGE_TYPES.get(global_mesg_num) field_defs = [] for n in range(num_fields): field_def_num, field_size, base_type_num = self._read_struct( '3B', endian=endian) # Try to get field from message type (None if unknown) field = mesg_type.fields.get(field_def_num) if mesg_type else None base_type = BASE_TYPES.get(base_type_num, BASE_TYPE_BYTE) if (field_size % base_type.size) != 0: # NOTE: we could fall back to byte encoding if there's any # examples in the wild. For now, just throw an exception raise FitParseError( "Invalid field size %d for type '%s' (expected a multiple of %d)" % (field_size, base_type.name, base_type.size)) # If the field has components that are accumulators # start recording their accumulation at 0 if field is not None and hasattr(field, 'components'): if field.components is not None: for component in field.components: if component.accumulate: accumulators = self._accumulators.setdefault( global_mesg_num, {}) accumulators[component.def_num] = 0 field_defs.append( FieldDefinition( field=field, def_num=field_def_num, base_type=base_type, size=field_size, )) def_mesg = DefinitionMessage( header=header, endian=endian, mesg_type=mesg_type, mesg_num=global_mesg_num, field_defs=field_defs, ) self._local_mesgs[header.local_mesg_num] = def_mesg return def_mesg