public bool Supports(MesgDefinition mesgDef) { if (mesgDef == null) { return(false); } if (GlobalMesgNum != mesgDef.GlobalMesgNum) { return(false); } if (LocalMesgNum != mesgDef.LocalMesgNum) { 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); } } return(true); }
public void Write(MesgDefinition mesgDefinition) { if (open == false) { throw new FitException("Encode:Write - Encode not opened yet, must call Encode:Open()"); } mesgDefinition.Write(fitDest); lastMesgDef[mesgDefinition.LocalMesgNum] = mesgDefinition; }
public MesgDefinition(MesgDefinition mesgDef) { LocalMesgNum = mesgDef.LocalMesgNum; GlobalMesgNum = mesgDef.GlobalMesgNum; architecture = mesgDef.IsBigEndian ? Fit.BigEndian : Fit.LittleEndian; NumFields = mesgDef.NumFields; foreach (FieldDefinition fieldDef in mesgDef.fieldDefs) { fieldDefs.Add(new FieldDefinition(fieldDef)); } }
public void OnMesgDefinition(MesgDefinition newMesgDefinition) { Write(newMesgDefinition); }
public MesgDefinitionEventArgs(MesgDefinition newDefn) { mesgDef = new MesgDefinition(newDefn); }
public void DecodeNextMessage(Stream fitStream) { var br = new BinaryReader(fitStream); byte nextByte = br.ReadByte(); // Is it a compressed timestamp mesg? if ((nextByte & Fit.CompressedHeaderMask) == Fit.CompressedHeaderMask) { var mesgBuffer = new MemoryStream(); int timeOffset = nextByte & Fit.CompressedTimeMask; timestamp += (uint)((timeOffset - lastTimeOffset) & Fit.CompressedTimeMask); lastTimeOffset = timeOffset; var timestampField = new Field(Profile.mesgs[Profile.RecordIndex].GetField("Timestamp")); timestampField.SetValue(timestamp); var localMesgNum = (byte)((nextByte & Fit.CompressedLocalMesgNumMask) >> 5); mesgBuffer.WriteByte(localMesgNum); if (localMesgDefs[localMesgNum] == null) { throw new FitException( "Decode:DecodeNextMessage - FIT decode error: Missing message definition for local message number " + localMesgNum + "."); } int fieldsSize = localMesgDefs[localMesgNum].GetMesgSize() - 1; try { mesgBuffer.Write(br.ReadBytes(fieldsSize), 0, fieldsSize); } catch (IOException e) { throw new FitException( "Decode:DecodeNextMessage - Compressed Data Message unexpected end of file. Wanted " + fieldsSize + " bytes at stream position " + fitStream.Position, e); } var newMesg = new Mesg(mesgBuffer, localMesgDefs[localMesgNum]); newMesg.InsertField(0, timestampField); if (MesgEvent != null) { MesgEvent(this, new MesgEventArgs(newMesg)); } } // Is it a mesg def? else if ((nextByte & Fit.HeaderTypeMask) == Fit.MesgDefinitionMask) { var 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); try { mesgDefBuffer.Write(br.ReadBytes(numfields*3), 0, numfields*3); } catch (IOException e) { throw new FitException( "Decode:DecodeNextMessage - Defn Message unexpected end of file. Wanted " + (numfields*3) + " bytes at stream position " + fitStream.Position, e); } var newMesgDef = new MesgDefinition(mesgDefBuffer); localMesgDefs[newMesgDef.LocalMesgNum] = newMesgDef; if (MesgDefinitionEvent != null) { MesgDefinitionEvent(this, new MesgDefinitionEventArgs(newMesgDef)); } } // Is it a data mesg? else if ((nextByte & Fit.HeaderTypeMask) == Fit.MesgHeaderMask) { var mesgBuffer = new MemoryStream(); var localMesgNum = (byte) (nextByte & Fit.LocalMesgNumMask); mesgBuffer.WriteByte(localMesgNum); if (localMesgDefs[localMesgNum] == null) { throw new FitException( "Decode:DecodeNextMessage - FIT decode error: Missing message definition for local message number " + localMesgNum + "."); } int fieldsSize = localMesgDefs[localMesgNum].GetMesgSize() - 1; try { mesgBuffer.Write(br.ReadBytes(fieldsSize), 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); } var newMesg = new Mesg(mesgBuffer, localMesgDefs[localMesgNum]); // If the new message contains a timestamp field, record the value to use as // a reference for compressed timestamp headers Field timestampField = newMesg.GetField("Timestamp"); if (timestampField != null) { timestamp = (uint) timestampField.GetValue(); lastTimeOffset = (int) timestamp & Fit.CompressedTimeMask; } // Now that the entire message is decoded we can evaluate subfields and expand any components newMesg.ExpandComponents(); if (MesgEvent != null) { MesgEvent(this, new MesgEventArgs(newMesg)); } } else { throw new FitException("Decode:Read - FIT decode error: Unexpected Record Header Byte 0x" + nextByte.ToString("X")); } }
public Mesg(Stream fitStream, MesgDefinition defnMesg) : this(defnMesg.GlobalMesgNum) { Read(fitStream, defnMesg); }
public void Write(Stream outStream, MesgDefinition mesgDef) { if (mesgDef == null) { mesgDef = new MesgDefinition(this); } EndianBinaryWriter bw = new EndianBinaryWriter(outStream, mesgDef.IsBigEndian); bw.Write(LocalNum); foreach (FieldDefinition fieldDef in mesgDef.GetFields()) { Field field = GetField(fieldDef.Num); if (field == null) { field = Profile.GetField(this.Num, fieldDef.Num); fields.Add(field); } // The field could be blank, correctly formed or partially filled while (field.GetSize() < fieldDef.Size) { field.AddValue(Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].invalidValue); } for (int i = 0; i < field.GetNumValues(); i++) { object value = field.GetRawValue(i); if (value == null) { value = Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].invalidValue; } switch (fieldDef.Type & Fit.BaseTypeNumMask) { case Fit.Enum: case Fit.Byte: case Fit.UInt8: case Fit.UInt8z: bw.Write((byte)value); break; case Fit.SInt8: bw.Write((sbyte)value); break; case Fit.SInt16: bw.Write((short)value); break; case Fit.UInt16: case Fit.UInt16z: bw.Write((ushort)value); break; case Fit.SInt32: bw.Write((int)value); break; case Fit.UInt32: case Fit.UInt32z: bw.Write((uint)value); break; case Fit.Float32: bw.Write((float)value); break; case Fit.Float64: bw.Write((double)value); break; case Fit.String: bw.Write((byte[])value); // Write the null terminator bw.Write((byte)0x00); break; default: break; } } } }
public void Read(Stream inStream, MesgDefinition defnMesg) { inStream.Position = 1; EndianBinaryReader mesgReader = new EndianBinaryReader(inStream, defnMesg.IsBigEndian); LocalNum = defnMesg.LocalMesgNum; foreach (FieldDefinition fieldDef in defnMesg.GetFields()) { // 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.GetMesg(this.Num).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.Type = fieldDef.Type; } SetField(field); } object value; // strings may be an array and are of variable length if ((field.Type & Fit.BaseTypeNumMask) == Fit.String) { List <byte> utf8Bytes = new List <byte>(); byte b = new byte(); for (int i = 0; i < fieldDef.Size; i++) { b = mesgReader.ReadByte(); if (b == 0x00) { field.AddValue(utf8Bytes.ToArray()); utf8Bytes.Clear(); } else { utf8Bytes.Add(b); } } if (utf8Bytes.Count != 0) { field.AddValue(utf8Bytes.ToArray()); utf8Bytes.Clear(); } } else { int numElements = (int)fieldDef.Size / Fit.BaseType[field.Type & Fit.BaseTypeNumMask].size; for (int i = 0; i < numElements; i++) { switch (field.Type & Fit.BaseTypeNumMask) { case Fit.Enum: case Fit.Byte: case Fit.UInt8: case Fit.UInt8z: value = mesgReader.ReadByte(); break; case Fit.SInt8: value = mesgReader.ReadSByte(); break; case Fit.SInt16: value = mesgReader.ReadInt16(); break; case Fit.UInt16: case Fit.UInt16z: value = mesgReader.ReadUInt16(); break; case Fit.SInt32: value = mesgReader.ReadInt32(); break; case Fit.UInt32: case Fit.UInt32z: value = mesgReader.ReadUInt32(); break; case Fit.Float32: value = mesgReader.ReadSingle(); break; case Fit.Float64: value = mesgReader.ReadDouble(); break; default: value = mesgReader.ReadBytes(fieldDef.Size); break; } field.SetRawValue(i, value); } } } }