Documentation
¶
Overview ¶
Package proto defines the abstraction for Fit Protocol.
Fit Protocol is the core of a Fit file and it's the fundamental building block for decoding and encoding fit files.
Index ¶
- Constants
- Variables
- func LocalMesgNum(header byte) byte
- func Validate(version byte) error
- func VersionMajor(version byte) byte
- func VersionMinor(version byte) byte
- type Component
- type DeveloperField
- type DeveloperFieldDefinition
- type Field
- type FieldBase
- type FieldDefinition
- type FileHeader
- type Fit
- type Message
- func (m Message) Clone() Message
- func (m *Message) FieldByNum(num byte) *Field
- func (m *Message) FieldValueByNum(num byte) any
- func (m *Message) MarshalBinary() ([]byte, error)
- func (m *Message) RemoveFieldByNum(num byte)
- func (m Message) WithDeveloperFields(developerFields ...DeveloperField) Message
- func (m Message) WithFieldValues(fieldNumValues map[byte]any) Message
- func (m Message) WithFields(fields ...Field) Message
- func (m *Message) WriteTo(w io.Writer) (n int64, err error)
- type MessageDefinition
- type SubField
- type SubFieldMap
- type Validator
- type Version
Constants ¶
const ( MesgDefinitionMask = 0b01000000 // Mask for determining if the message type is a message definition. MesgNormalHeaderMask = 0b00000000 // Mask for determining if the message type is a normal message data . MesgCompressedHeaderMask = 0b10000000 // Mask for determining if the message type is a compressed timestamp message data. LocalMesgNumMask = 0b00001111 // Mask for mapping normal message data to the message definition. CompressedLocalMesgNumMask = 0b01100000 // Mask for mapping compressed timestamp message data to the message definition. Used with CompressedBitShift. CompressedTimeMask = 0b00011111 // Mask for measuring time offset value from header. Compressed timestamp is using 5 least significant bits (lsb) of header DevDataMask = 0b00100000 // Mask for determining if a message contains developer fields. CompressedBitShift = 5 // Used for right shifting the 5 least significant bits (lsb) of compressed ti DefaultFileHeaderSize byte = 14 // The preferred size is 14 DataTypeFIT string = ".FIT" // FIT is a constant string ".FIT" FieldNumTimestamp = 253 // Field Num for timestamp across all defined messages in the profile. )
const ( MajorVersionShift = 4 MajorVersionMask = 0x0F << MajorVersionShift MinorVersionMask = 0x0F V1 Version = 1 << MajorVersionShift // V1 is Version 1.0 V2 Version = 2 << MajorVersionShift // V2 is Version 2.0 Vmax = V2 // Vmax is an alias for the current latest version. )
const MaxBytesPerMessage = 1 + (255 * 255) + (255 * 255) + 1
m.Header + ((max cap of m.Fields) * (n value)) + ((max cap of m.DeveloperFields) * (n value)) + cap
Variables ¶
var ErrProtocolVersionNotSupported = errors.New("protocol version not supported")
var ErrProtocolViolation = errors.New("protocol violation")
Functions ¶
func LocalMesgNum ¶
LocalMesgNum extracts LocalMesgNum from message header.
func VersionMajor ¶
VersionMajor returns major value of given version
func VersionMinor ¶
VersionMinor returns minor value of given version
Types ¶
type Component ¶
type Component struct { FieldNum byte Scale float64 Offset float64 Accumulate bool Bits byte // bit value max 32 }
Component is a way of compressing one or more fields into a bit field expressed in a single containing field. The component can be expanded as a main Field in a Message or to update the value of the destination main Field.
type DeveloperField ¶
type DeveloperField struct { Num byte DeveloperDataIndex byte Size byte NativeMesgNum typedef.MesgNum NativeFieldNum byte Name string Type basetype.BaseType Units string Value any }
Developer Field is a way to add custom data fields to existing messages. Developer Data Fields can be added to any message at runtime by providing a self-describing field definition. Developer Data Fields are also used by the Connect IQ FIT Contributor library, allowing Connect IQ apps and data fields to include custom data in FIT Activity files during the recording of activities. [Added since protocol version 2.0]
NOTE: If Developer Field contains a valid NativeMesgNum and NativeFieldNum, the value should be treated as native value (scale, offset, etc shall apply).
func (DeveloperField) Clone ¶
func (f DeveloperField) Clone() DeveloperField
Clone clones DeveloperField
type DeveloperFieldDefinition ¶
type DeveloperFieldDefinition struct { Num byte // Map to the `field_definition_number` of a `field_description` Message. Size byte // Size (in bytes) of the specified FIT message’s field DeveloperDataIndex byte // Maps to the `developer_data_index“ of a `developer_data_id` Message }
FieldDefinition is the definition of the upcoming developer field within the message's structure.
type Field ¶
type Field struct { // PERF: Embedding the struct as a pointer to avoid runtime duffcopy when creating a field since FieldBase should not be altered. *FieldBase // The decoded value, composed by decoder, will always in a form of a primitive-type (or a slice of primitive types): // - int8, uint8, int16, uint16, int32, uint32, int64, uint64, float32, float64 and string. // - []int8, []uint8, []int16, []uint16, []int32, []uint32, []int64, []uint64, []float32, []float64 and []string. // // When the field is manually composed, you may use type-defined value as long as it refer to any of primitive-types // (e.g. typedef.FileActivity). However, please note that marshaling type-defined value requires reflection. // // NOTE: You can not use distinct types such as int and uint. Value any // A flag to detect whether this field is generated through component expansion. IsExpandedField bool }
Field represents the full representation of a field, as specified in the Global Fit Profile.
func (*Field) SubFieldSubtitution ¶
SubFieldSubstitution returns any sub-field that can substitute the properties interpretation of the parent Field (Dynamic Field).
type FieldBase ¶
type FieldBase struct { Name string // Defined in the Global FIT profile for the specified FIT message, otherwise its a manufaturer specific name (defined by manufacturer). Num byte // Defined in the Global FIT profile for the specified FIT message, otherwise its a manufaturer specific number (defined by manufacturer). (255 == invalid) Type profile.ProfileType // Type is defined type that serves as an abstraction layer above base types (primitive-types), e.g. DateTime is a time representation in uint32. Array bool // Flag whether the value of this field is an array Scale float64 // A scale or offset specified in the FIT profile for binary fields (sint/uint etc.) only. the binary quantity is divided by the scale factor and then the offset is subtracted. (default: 1) Offset float64 // A scale or offset specified in the FIT profile for binary fields (sint/uint etc.) only. the binary quantity is divided by the scale factor and then the offset is subtracted. (default: 0) Units string // Units of the value, such as m (meter), m/s (meter per second), s (second), etc. Accumulate bool // Flag to indicate if the value of the field is accumulable. Components []Component // List of components SubFields []SubField // List of sub-fields }
FieldBase acts as a fundamental representation of a field as defined in the Global Fit Profile. The value of this representation should not be altered, except in the case of an unknown field.
type FieldDefinition ¶
type FieldDefinition struct { Num byte // The field definition number Size byte // The size of the upcoming value BaseType basetype.BaseType // The type of the upcoming value to be represented }
FieldDefinition is the definition of the upcoming field within the message's structure.
type FileHeader ¶
type FileHeader struct { Size byte // Header size either 12 (legacy) or 14. ProtocolVersion byte // The Fit Protocol version which is being used to encode the Fit file. ProfileVersion uint16 // The Fit Profile Version (associated with data defined in Global Fit Profile). DataSize uint32 // The size of the messages in bytes (this field will be automatically updated by the encoder) DataType string // ".FIT" (a string constant) CRC uint16 // Cyclic Redundancy Check 16-bit value to ensure the integrity if the header. (this field will be automatically updated by the encoder) }
FileHeader is a Fit's FileHeader with either 12 bytes size without CRC or a 14 bytes size with CRC, while 14 bytes size is the preferred size.
func (*FileHeader) MarshalBinary ¶
func (h *FileHeader) MarshalBinary() ([]byte, error)
type Fit ¶
type Fit struct { FileHeader FileHeader // File Header contains either 12 or 14 bytes Messages []Message // Messages. CRC uint16 // Cyclic Redundancy Check 16-bit value to ensure the integrity of the messages. }
Fit represents a structure for Fit Files.
func (*Fit) WithMessages ¶
WithMessages set Messages and return the pointer to the Fit.
type Message ¶
type Message struct { Header byte // Message Header serves to distinguish whether the message is a Normal Data or a Compressed Timestamp Data. Unlike MessageDefinition, Message's Header should not contain Developer Data Flag. Num typedef.MesgNum // Global Message Number defined in Global Fit Profile, except number within range 0xFF00 - 0xFFFE are manufacturer specific number. Reserved byte // Currently undetermined; the default value is 0. Architecture byte // Architecture type / Endianness. Must be the same Fields []Field // List of Field DeveloperFields []DeveloperField // List of DeveloperField }
Message is a FIT protocol message containing the data defined in the Message Definition
func (*Message) FieldByNum ¶
FieldByNum returns a pointer to the Field in a Message, if not found return nil.
func (*Message) FieldValueByNum ¶ added in v0.1.0
FieldValueByNum returns the value of the Field in a Messsage, if not found return nil.
func (*Message) MarshalBinary ¶
func (*Message) RemoveFieldByNum ¶
RemoveFieldByNum removes Field in a Message by num.
func (Message) WithDeveloperFields ¶
func (m Message) WithDeveloperFields(developerFields ...DeveloperField) Message
WithFields copies the provided fields into the message's fields.
func (Message) WithFieldValues ¶
WithFieldValues assigns the values of the targeted fields with the given map, where map[byte]any represents the field numbers and their respective values.
func (Message) WithFields ¶
WithFields copies the provided fields into the message's fields.
type MessageDefinition ¶
type MessageDefinition struct { Header byte // The message definition header with mask 0b01000000. Reserved byte // Currently undetermined; the default value is 0. Architecture byte // The Byte Order to be used to decode the values of both this message definition and the upcoming message. (0: Little-Endian, 1: Big-Endian) MesgNum typedef.MesgNum // Global Message Number defined by factory (retrieved from Profile.xslx). (endianness of this 2 Byte value is defined in the Architecture byte) FieldDefinitions []FieldDefinition // List of the field definition DeveloperFieldDefinitions []DeveloperFieldDefinition // List of the developer field definition (only if Developer Data Flag is set in Header) }
MessageDefinition is the definition of the upcoming data messages.
func CreateMessageDefinition ¶
func CreateMessageDefinition(mesg *Message) (mesgDef MessageDefinition)
CreateMessageDefinition creates new MessageDefinition base on given Message.
func (MessageDefinition) Clone ¶
func (m MessageDefinition) Clone() MessageDefinition
Clone clones MessageDefinition
func (*MessageDefinition) MarshalBinary ¶
func (m *MessageDefinition) MarshalBinary() ([]byte, error)
type SubField ¶
type SubField struct { Name string Type profile.ProfileType Scale float64 Offset float64 Units string Maps []SubFieldMap Components []Component }
SubField is a dynamic interpretation of the main Field in a Message when the SubFieldMap mapping match. See SubFieldMap's docs.
type SubFieldMap ¶
SubFieldMap is the mapping between SubField and and the corresponding main Field in a Message. When any Field in a Message has Field.Num == RefFieldNum and Field.Value == RefFieldValue, then the SubField containing this mapping can be interpreted as the main Field's properties (name, scale, type etc.)
type Validator ¶
type Validator struct {
// contains filtered or unexported fields
}
Validator is protocol validator
func NewValidator ¶
NewValidator creates protocol validator base on given version.
func (*Validator) ValidateMessageDefinition ¶
func (p *Validator) ValidateMessageDefinition(mesgDef *MessageDefinition) error
ValidateMessageDefinition validates whether the message definition contains unsupported data for the targeted version.