Ejemplo n.º 1
0
        /// <summary>
        /// Validate if a MessageDefinition is compatible with a protocol version
        /// </summary>
        /// <param name="defn">Definition to validate</param>
        /// <returns>true if definition is compatible. false otherwise</returns>
        public bool ValidateMessageDefn(MessageDefinition defn)
        {
            if (m_validator == null)
            {
                return(true);
            }

            return(m_validator.ValidateMessageDefn(defn));
        }
Ejemplo n.º 2
0
        public bool Supports(MessageDefinition mesgDef)
        {
            if (mesgDef == null)
            {
                return(false);
            }

            if (GlobalMessageNum != mesgDef.GlobalMessageNum)
            {
                return(false);
            }

            if (LocalMessageNum != mesgDef.LocalMessageNum)
            {
                return(false);
            }

            foreach (FieldDefinition fieldDef in mesgDef.GetFields())
            {
                FieldDefinition supportedFieldDef = GetField(fieldDef.Num);

                if (supportedFieldDef == null)
                {
                    return(false);
                }

                if (fieldDef.Size > supportedFieldDef.Size)
                {
                    return(false);
                }
            }

            foreach (DeveloperFieldDefinition fieldDef in mesgDef.DeveloperFieldDefinitions)
            {
                var supportedFieldDef =
                    GetDeveloperFieldDefinition(fieldDef.FieldNum, fieldDef.DeveloperDataIndex);

                if (supportedFieldDef == null)
                {
                    return(false);
                }

                if (fieldDef.Size > supportedFieldDef.Size)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 3
0
        public MessageDefinition(MessageDefinition mesgDef)
        {
            LocalMessageNum  = mesgDef.LocalMessageNum;
            GlobalMessageNum = mesgDef.GlobalMessageNum;
            architecture     = mesgDef.IsBigEndian ? Fit.BigEndian : Fit.LittleEndian;
            NumFields        = mesgDef.NumFields;

            foreach (FieldDefinition fieldDef in mesgDef.fieldDefs)
            {
                fieldDefs.Add(new FieldDefinition(fieldDef));
            }

            m_devFieldDefs.AddRange(mesgDef.m_devFieldDefs);
        }
Ejemplo n.º 4
0
        public void Write(MessageDefinition mesgDefinition)
        {
            if (open == false)
            {
                throw new FitException("Encode:Write - Encode not opened yet, must call Encode:Open()");
            }

            if (!validator.ValidateMessageDefn(mesgDefinition))
            {
                throw new FitException("Encode:Write - mesgDefinition contains incompatible protocol Features");
            }

            mesgDefinition.Write(fitDest);
            lastMessageDef[mesgDefinition.LocalMessageNum] = mesgDefinition;
        }
Ejemplo n.º 5
0
        public void Write(Stream outStream, MessageDefinition mesgDef)
        {
            if (mesgDef == null)
            {
                mesgDef = new MessageDefinition(this);
            }

            EndianBinaryWriter bw = new EndianBinaryWriter(outStream, mesgDef.IsBigEndian);

            bw.Write(LocalNum);

            foreach (FieldDefinition fieldDef in mesgDef.GetFields())
            {
                Field field = GetField(fieldDef.Num);
                if (null == field)
                {
                    field = Profile.GetField(this.MessageNumber, fieldDef.Num);
                    if (null != field)
                    {
                        FieldsList.Add(field);
                    }
                    else
                    {
                        field = new Field(fieldDef.Num, fieldDef.Type);
                    }
                }

                WriteField(field, fieldDef.Size, bw);
            }

            foreach (DeveloperFieldDefinition fieldDef in mesgDef.DeveloperFieldDefinitions)
            {
                DeveloperField field = GetDeveloperField(fieldDef.FieldNum, fieldDef.DeveloperDataIndex);

                if (field == null)
                {
                    field = new DeveloperField(fieldDef);
                    SetDeveloperField(field);
                }

                WriteField(field, fieldDef.Size, bw);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Validate if a MessageDefinition is compatible with a protocol version
        /// </summary>
        /// <param name="defn">Definition to validate</param>
        /// <returns>true if definition is compatible. false otherwise</returns>
        public bool ValidateMessageDefn(MessageDefinition defn)
        {
            if (defn.DeveloperFieldDefinitions.Any())
            {
                return(false);
            }

            foreach (var fld in defn.GetFields())
            {
                int typeNum = fld.Type & Fit.BaseTypeNumMask;

                if (typeNum > Fit.Byte)
                {
                    return(false);
                }
            }

            return(true);
        }
Ejemplo n.º 7
0
        public void Read(Stream inStream, MessageDefinition defnMessage)
        {
            inStream.Position = 1;
            EndianBinaryReader mesgReader = new EndianBinaryReader(inStream, defnMessage.IsBigEndian);

            LocalNum = defnMessage.LocalMessageNum;

            foreach (FieldDefinition fieldDef in defnMessage.GetFields())
            {
                bool read = true;

                // It's possible the field type found in the field definition may
                // not agree with the type defined in the profile.  The profile
                // type will be preferred for decode.
                Field field = GetField(fieldDef.Num);
                if (field == null)
                {
                    // We normally won't have fields attached to our skeleton message,
                    // as we add values we need to add the fields too based on the mesg,field
                    // combo in the profile.  Must derive from the profile so the scale etc
                    // is correct
                    field = new Field(Profile.GetMessage(this.MessageNumber).GetField(fieldDef.Num));
                    if (field.Num == Fit.FieldNumInvalid)
                    {
                        // If there was no info in the profile the FieldNum will get set to invalid
                        // so preserve the unknown fields info while we know it
                        field.Num = fieldDef.Num;
                        field.SetType(fieldDef.Type);
                    }
                    SetField(field);
                }

                if (field.Type != fieldDef.Type)
                {
                    int fieldSize = Fit.BaseType[field.Type & Fit.BaseTypeNumMask].size;
                    int defSize   = Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].size;

                    if (defSize < fieldSize)
                    {
                        field.SetType(fieldDef.Type);
                    }
                    else if (defSize != fieldSize)
                    {
                        // Demotion is hard. Don't read the field if the
                        // sizes are different. Use the profile type if the
                        // signedness of the field has changed.
                        read = false;
                    }
                }

                if (read)
                {
                    ReadFieldValue(field, fieldDef.Size, mesgReader);
                }
                else
                {
                    // Skip the bytes for the field if we aren't going to bother reading them
                    mesgReader.ReadBytes(fieldDef.Size);
                }
            }

            foreach (DeveloperFieldDefinition fldDef in defnMessage.DeveloperFieldDefinitions)
            {
                DeveloperField fld = GetDeveloperField(fldDef.FieldNum, fldDef.DeveloperDataIndex);
                if (ReferenceEquals(fld, null))
                {
                    fld = new DeveloperField(fldDef);
                    SetDeveloperField(fld);
                }

                ReadFieldValue(fld, fldDef.Size, mesgReader);
            }
        }
Ejemplo n.º 8
0
 public Message(Stream fitStream, MessageDefinition defnMessage)
     : this(defnMessage.GlobalMessageNum)
 {
     Read(fitStream, defnMessage);
 }
Ejemplo n.º 9
0
        public void DecodeNextMessage(Stream fitStream)
        {
            BinaryReader br       = new BinaryReader(fitStream);
            byte         nextByte = br.ReadByte();

            // Is it a compressed timestamp mesg?
            if ((nextByte & Fit.CompressedHeaderMask) == Fit.CompressedHeaderMask)
            {
                MemoryStream mesgBuffer = new MemoryStream();

                int timeOffset = nextByte & Fit.CompressedTimeMask;
                timestamp     += (uint)((timeOffset - lastTimeOffset) & Fit.CompressedTimeMask);
                lastTimeOffset = timeOffset;
                Field timestampField = new Field(Profile.GetMessage(MessageNum.Record).GetField("Timestamp"));
                timestampField.SetValue(timestamp);

                byte localMessageNum = (byte)((nextByte & Fit.CompressedLocalMessageNumMask) >> 5);
                mesgBuffer.WriteByte(localMessageNum);
                if (localMessageDefs[localMessageNum] == null)
                {
                    throw new FitException("Decode:DecodeNextMessage - FIT decode error: Missing message definition for local message number " + localMessageNum + " at stream position " + fitStream.Position);
                }
                int fieldsSize = localMessageDefs[localMessageNum].GetMessageSize() - 1;
                try
                {
                    byte[] read = br.ReadBytes(fieldsSize);
                    if (read.Length < fieldsSize)
                    {
                        throw new Exception("Field size mismatch, expected: " + fieldsSize + "received: " + read.Length);
                    }
                    mesgBuffer.Write(read, 0, fieldsSize);
                }
                catch (Exception e)
                {
                    throw new FitException("Decode:DecodeNextMessage - Compressed Data Message unexpected end of file.  Wanted " + fieldsSize + " bytes at stream position " + fitStream.Position, e);
                }

                Message newMessage = new Message(mesgBuffer, localMessageDefs[localMessageNum]);
                newMessage.InsertField(0, timestampField);
                RaiseMessageEvent(newMessage);
            }
            // Is it a mesg def?
            else if ((nextByte & Fit.MessageDefinitionMask) == Fit.MessageDefinitionMask)
            {
                MemoryStream mesgDefBuffer = new MemoryStream();

                // Figure out number of fields (length) of our defn and build buffer
                mesgDefBuffer.WriteByte(nextByte);
                mesgDefBuffer.Write(br.ReadBytes(4), 0, 4);
                byte numFields = br.ReadByte();
                mesgDefBuffer.WriteByte(numFields);
                int numBytes = numFields * 3; //3 Bytes per field
                try
                {
                    byte[] read = br.ReadBytes(numBytes);
                    if (read.Length < numBytes)
                    {
                        throw new Exception("Message Definition size mismatch, expected: " + numBytes + "received: " + read.Length);
                    }
                    mesgDefBuffer.Write(read, 0, numBytes);

                    if ((nextByte & Fit.DevDataMask) == Fit.DevDataMask)
                    {
                        // Definition Contains Dev Data
                        byte numDevFields = br.ReadByte();
                        mesgDefBuffer.WriteByte(numDevFields);

                        numBytes = numDevFields * 3;
                        read     = br.ReadBytes(numBytes);
                        if (read.Length < numBytes)
                        {
                            throw new Exception("Message Definition size mismatch, expected: " + numBytes + "received: " + read.Length);
                        }

                        // Read Dev Data
                        mesgDefBuffer.Write(read, 0, numBytes);
                    }
                }
                catch (Exception e)
                {
                    throw new FitException("Decode:DecodeNextMessage - Defn Message unexpected end of file.  Wanted " + numBytes + " bytes at stream position " + fitStream.Position, e);
                }

                MessageDefinition newMessageDef = new MessageDefinition(mesgDefBuffer, m_lookup);
                localMessageDefs[newMessageDef.LocalMessageNum] = newMessageDef;
                if (MessageDefinitionEvent != null)
                {
                    MessageDefinitionEvent(this, new MessageDefinitionEventArgs(newMessageDef));
                }
            }
            // Is it a data mesg?
            else if ((nextByte & Fit.MessageDefinitionMask) == Fit.MessageHeaderMask)
            {
                MemoryStream mesgBuffer = new MemoryStream();

                byte localMessageNum = (byte)(nextByte & Fit.LocalMessageNumMask);
                mesgBuffer.WriteByte(localMessageNum);
                if (localMessageDefs[localMessageNum] == null)
                {
                    throw new FitException("Decode:DecodeNextMessage - FIT decode error: Missing message definition for local message number " + localMessageNum + " at stream position " + fitStream.Position);
                }
                int fieldsSize = localMessageDefs[localMessageNum].GetMessageSize() - 1;
                try
                {
                    byte[] read = br.ReadBytes(fieldsSize);
                    if (read.Length < fieldsSize)
                    {
                        throw new Exception("Field size mismatch, expected: " + fieldsSize + "received: " + read.Length);
                    }
                    mesgBuffer.Write(read, 0, fieldsSize);
                }
                catch (Exception e)
                {
                    throw new FitException("Decode:DecodeNextMessage - Data Message unexpected end of file.  Wanted " + fieldsSize + " bytes at stream position " + fitStream.Position, e);
                }

                Message newMessage = new Message(mesgBuffer, localMessageDefs[localMessageNum]);

                // If the new message contains a timestamp field, record the value to use as
                // a reference for compressed timestamp headers
                Field timestampField = newMessage.GetField("Timestamp");
                if (timestampField != null)
                {
                    object tsValue = timestampField.GetValue();
                    if (tsValue != null)
                    {
                        timestamp      = (uint)tsValue;
                        lastTimeOffset = (int)timestamp & Fit.CompressedTimeMask;
                    }
                }

                foreach (Field field in newMessage.FieldsList)
                {
                    if (field.IsAccumulated)
                    {
                        int i;
                        for (i = 0; i < field.GetNumValues(); i++)
                        {
                            long value = Convert.ToInt64(field.GetRawValue(i));

                            foreach (Field fieldIn in newMessage.FieldsList)
                            {
                                foreach (FieldComponent fc in fieldIn.components)
                                {
                                    if ((fc.fieldNum == field.Num) && (fc.accumulate))
                                    {
                                        value = (long)((((value / field.Scale) - field.Offset) + fc.offset) * fc.scale);
                                    }
                                }
                            }
                            accumulator.Set(newMessage.MessageNumber, field.Num, value);
                        }
                    }
                }

                // Now that the entire message is decoded we can evaluate subfields and expand any components
                newMessage.ExpandComponents(accumulator);

                RaiseMessageEvent(newMessage);
            }
            else
            {
                throw new FitException("Decode:Read - FIT decode error: Unexpected Object Header Byte 0x" + nextByte.ToString("X") + " at stream position: " + fitStream.Position);
            }
        }
Ejemplo n.º 10
0
 public MessageDefinitionEventArgs(MessageDefinition newDefn)
 {
     messageDefinition = new MessageDefinition(newDefn);
 }
Ejemplo n.º 11
0
 public void OnMessageDefinition(MessageDefinition newMessageDefinition)
 {
     Write(newMessageDefinition);
 }