Ejemplo n.º 1
0
 def __populate_schema_cache(self, schema_sig, field_name, type, count):
     """Cache schema on the assumption that the set of schemas is much smaller than the number of times they are used."""
     schema = data.Schema(
         field_name,
         collections.OrderedDict([(field_name, [type, count, '%d'])]))
     self.__schema_cache[schema_sig] = schema
     return schema
Ejemplo n.º 2
0
class RecordHeader(data.Data):
    """Object that represents a FIT file record header."""

    rh_schema = data.Schema(
        'rh', collections.OrderedDict([('record_header', ['UINT8', 1, '%x'])]))
    message_type_string = ['data', 'definition']

    def __init__(self, file):
        """Return a RecordHeader instance created by reading the record geader data from a FIT file."""
        super(RecordHeader, self).__init__(file, self.rh_schema)
        self.message_class = MessageClass(self.message_type())

    def __compressed_timestamp(self):
        return (self.record_header & 0x80) == 0x80

    def message_type(self):
        return (self.record_header & 0x40) == 0x40

    def developer_data(self):
        return (self.record_header & 0x60) == 0x60

    def local_message(self):
        return (self.record_header & 0x0f)

    def __str__(self):
        """Return a string representation of a RecordHeader instance."""
        return ("RecordHeader: Local %s message %d (Compressed %d)" %
                (self.message_class.name, self.local_message(),
                 self.__compressed_timestamp()))

    def __repr__(self):
        """Return a string representation of a RecordHeader instance."""
        return self.__str__()
Ejemplo n.º 3
0
class FileHeader(data.Data):
    """Class that represents a FIT file header."""

    fh_primary_schema = data.Schema(
        'fh_primary',
        collections.OrderedDict(
            [
                ('header_size', ['UINT8', 1, '%d']),
                ('protocol_version', ['UINT8', 1, '%x']),
                ('profile_version', ['UINT16', 1, '%d']),
                ('data_size', ['UINT32', 1, '%d']),
                ('data_type', ['CHAR', 4, '%c'])
            ]
        )
    )
    fh_optional_schema = data.Schema(
        'fh_optional',
        collections.OrderedDict([('crc', ['UINT16', 1, '%x'])])
    )
    profile_version_str = {100 : 'activity', 1602 : 'device'}

    min_file_header_size = 12
    opt_file_header_size = 14
    min_protocol_version = 0x10
    file_data_type = [46, 70, 73, 84]
#    file_data_type = ['.', 'F', 'I', 'T']

    def __init__(self, file):
        """Return a FileHeader instance created by reading data from a Fit file."""
        super(FileHeader, self).__init__(file, FileHeader.fh_primary_schema, [(FileHeader.fh_optional_schema, self.__decode_secondary)])
        self.__check()

    def __decode_secondary(self):
        return (self.header_size >= FileHeader.opt_file_header_size)

    def __check(self):
        if self.header_size < FileHeader.min_file_header_size:
            raise exceptions.FitFileBadHeaderSize("%d < %d" % (self.header_size, FileHeader.min_file_header_size))
        if self.protocol_version < FileHeader.min_protocol_version:
            raise exceptions.FitFileBadProtocolVersion("%d < %d" % (self.protocol_version, FileHeader.min_protocol_version))
        if self.data_type != FileHeader.file_data_type:
            raise exceptions.FitFileDataType("%r < %r" % (self.data_type, FileHeader.file_data_type))

    def __str__(self):
        """Return a string representation of a FileHeader instance."""
        return ("%s(header size %d prot ver %x prof ver %d)" %
                (self.__class__.__name__, self.header_size, self.protocol_version, self.profile_version))
Ejemplo n.º 4
0
 def __init__(self, file, definition_message, dev_field_definition,
              measurement_system):
     self.dev_field_definition = dev_field_definition
     self.measurement_system = measurement_system
     self.field = dev_field_definition.field()
     type = dev_field_definition.type_string()
     count = dev_field_definition.type_count()
     schema = data.Schema(
         self.field.name,
         collections.OrderedDict([(self.field.name, [type, count, '%d'])]))
     super(DevDataField, self).__init__(file, schema, None,
                                        definition_message.endian)
Ejemplo n.º 5
0
class FieldDefinition(data.Data, base_type.BaseType):
    """Object that defines the structure of a FIT file message field."""

    fd_schema = data.Schema(
        'fd',
        collections.OrderedDict([('field_definition_number',
                                  ['UINT8', 1, '%x']),
                                 ('size', ['UINT8', 1, '%x']),
                                 ('base_type', ['UINT8', 1, '%x'])]))

    def __init__(self, file):
        """
        Return a FieldDefinition instance created by reading data from a FIT file.

        Paramters:
            file (File):  a FIT File instance.
        """
        super(FieldDefinition, self).__init__(file, FieldDefinition.fd_schema)

    def base_type(self):
        """Return the base type for the field."""
        return self._base_type(self.base_type)

    def type_endian(self):
        """Return the endian value for the field."""
        return self._type_endian(self.base_type)

    def type_name(self):
        """Return the type name for the field."""
        return self._type_name(self.base_type)

    def invalid(self):
        """Return the invalid value for the field."""
        return self._invalid(self.base_type)

    def type_string(self):
        """Return the type string for the field."""
        return self._type_string(self.base_type)

    def type_count(self):
        """Return the number of values for the field."""
        type_size = data.Schema.type_to_size(self.type_string())
        return (self.size / type_size)

    def __str__(self):
        """Return a string representation for the FieldDefinition instance."""
        return ("FieldDefinition: type %d: %d of %s" %
                (self.field_definition_number, self.type_count(),
                 self.type_string()))
Ejemplo n.º 6
0
class DeveloperFieldDefinition(data.Data, base_type.BaseType):
    """Developer filed definitions decoded from a FIT file."""

    dfd_schema = data.Schema(
        'dfd_schema',
        collections.OrderedDict(
            [
                ('field_number', ['UINT8', 1, '%x']),
                ('size', ['UINT8', 1, '%x']),
                ('developer_data_index', ['UINT8', 1, '%x'])
            ]
        )
    )

    def __init__(self, dev_field_dict, file):
        """
        Return a DeveloperFieldDefinition instance created by reading data from a FIT file.

        Paramters:
            dev_field_dict (dict): a dictionary of developer defined fields.
            file (File):  a FIT File instance.
        """
        super(DeveloperFieldDefinition, self).__init__(file, DeveloperFieldDefinition.dfd_schema)
        self.dev_field = dev_field_dict.get(self.field_number)
        if self.dev_field is None:
            raise exceptions.FitUndefDevMessageType('Dev field %d undefined in %r' % (self.field_number, dev_field_dict))
        self.field_name = self.dev_field['field_name'].value
        self.native_message_num = self.dev_field['native_message_num'].value
        self.native_field_num = self.dev_field['native_field_num'].value
        self.units = self.dev_field['units'].value
        self.offset = self.dev_field['offset'].value
        self.scale = self.dev_field['scale'].value

    def __base_type_value(self):
        return self.dev_field['fit_base_type_id'].orig

    def field(self):
        """Return a DevField instance representing the field for this DeveloperFieldDefinition instance."""
        # if self.native_message_num is not None and self.native_field_num is not None:
        #     message_data = DefinitionMessageData.get_message(self.native_message_num)
        #     field_dict = message_data[1]
        #     return field_dict[self.native_field_num]
        return fields.DevField('dev_' + self.field_name, self.units, self.scale, self.offset)

    def base_type(self):
        """Return the base type for the field."""
        return self._base_type(self.__base_type_value())

    def type_endian(self):
        """Return the endian value for the field."""
        return self._type_endian(self.__base_type_value())

    def type_name(self):
        """Return the type name for the field."""
        return self._type_name(self.__base_type_value())

    def invalid(self):
        """Return the invalid value for the field."""
        return self._invalid(self.__base_type_value())

    def type_string(self):
        """Return the type string for the field."""
        return self._type_string(self.__base_type_value())

    def type_count(self):
        """Return the number of values for the field."""
        type_size = data.Schema.type_to_size(self.type_string())
        return (self.size / type_size)

    def __str__(self):
        """Return a string representation for the DeveloperFieldDefinition instance."""
        return ("%s: type %d: %d %d of %s" % (self.__class__.__name__, self.field_number, self.developer_data_index, self.type_count(), self.type_string()))
Ejemplo n.º 7
0
class DefinitionMessage(data.Data):
    """FIT file definition message."""

    dm_primary_schema = data.Schema(
        'dm_primary',
        collections.OrderedDict([('reserved', ['UINT8', 1, '%x']),
                                 ('architecture', ['UINT8', 1, '%x'])]))
    dm_secondary_schema = data.Schema(
        'dm_secondary',
        collections.OrderedDict([('global_message_number', ['UINT16', 1,
                                                            '%x']),
                                 ('fields', ['UINT8', 1, '%x'])]))
    dm_dev_schema = data.Schema(
        'dm_dev', collections.OrderedDict([('dev_fields', ['UINT8', 1,
                                                           '%x'])]))

    def __init__(self, record_header, dev_field_dict, file):
        """
        Return a DefinitionMessage instance created by reading data from a FIT file.

        Paramters:
            record_header (RecordHeader): the record header associated with this definition message.
            dev_field_dict (dict): a dictionary of developer defoined fields in the FIT file.
            file (File): the FIT file instance to read the definition message data from.
        """
        super(DefinitionMessage, self).__init__(
            file, DefinitionMessage.dm_primary_schema,
            [(DefinitionMessage.dm_secondary_schema, self.__decode_secondary)])

        self.message_type = MessageType.get_type(self.global_message_number)
        self.message_data = DefinitionMessageData.get_message_definition(
            self.message_type)

        self.field_definitions = []
        for index in xrange(self.fields):
            field_definition = FieldDefinition(file)
            self.file_size += field_definition.file_size
            self.field_definitions.append(field_definition)

        self.has_dev_fields = record_header.developer_data()
        self.dev_field_definitions = []
        if self.has_dev_fields:
            self._decode(DefinitionMessage.dm_dev_schema)
            for index in xrange(self.dev_fields):
                dev_field_definition = DeveloperFieldDefinition(
                    dev_field_dict, file)
                self.file_size += dev_field_definition.file_size
                self.dev_field_definitions.append(dev_field_definition)

    def __decode_secondary(self):
        self.endian = data.Architecture(self.architecture)
        return True

    def field(self, field_number):
        """Return an instance of the proper Field subclass for the given field definition."""
        return DefinitionMessageData.reserved_field_indexes.get(
            field_number,
            self.message_data.get(field_number,
                                  fields.UnknownField(field_number)))

    def __str__(self):
        """Return a string representation of a DefinitionMessage instance."""
        return ("DefinitionMessage: %r %d %s fields" %
                (self.message_type, self.fields, self.endian.name))