def generate_messages(mesg_num, local_mesg_num, field_defs, endian='<', data=None): mesgs = [] base_type_list = [] # definition message, local message num s = pack('<B', 0x40 | local_mesg_num) # reserved byte and endian s += pack('<xB', int(endian == '>')) # global message num, num fields s += pack('%sHB' % endian, mesg_num, len(field_defs)) for def_num, base_type in field_defs: base_type = [bt for bt in BASE_TYPES.values() if bt.name == base_type][0] base_type_list.append(base_type) s += pack('<3B', def_num, base_type.size, base_type.identifier) mesgs.append(s) if data: for mesg_data in data: s = pack('B', local_mesg_num) for value, base_type in zip(mesg_data, base_type_list): s += pack("%s%s" % (endian, base_type.fmt), value) mesgs.append(s) return b''.join(mesgs)
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 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 = 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