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); }
/// <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 ValidateMesgDefn(MesgDefinition defn) { if (m_validator == null) { return(true); } return(m_validator.ValidateMesgDefn(defn)); }
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 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 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); } } 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); }
public void Write(MesgDefinition mesgDefinition) { if (open == false) { throw new FitException("Encode:Write - Encode not opened yet, must call Encode:Open()"); } if (!validator.ValidateMesgDefn(mesgDefinition)) { throw new FitException("Encode:Write - mesgDefinition contains incompatible protocol Features"); } mesgDefinition.Write(fitDest); lastMesgDef[mesgDefinition.LocalMesgNum] = mesgDefinition; }
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.SetType(fieldDef.Type); } SetField(field); } ReadFieldValue(field, fieldDef.Size, mesgReader); } foreach (DeveloperFieldDefinition fldDef in defnMesg.DeveloperFieldDefinitions) { DeveloperField fld = GetDeveloperField(fldDef.FieldNum, fldDef.DeveloperDataIndex); if (ReferenceEquals(fld, null)) { fld = new DeveloperField(fldDef); SetDeveloperField(fld); } ReadFieldValue(fld, fldDef.Size, mesgReader); } }
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 (null == field) { field = Profile.GetField(this.Num, fieldDef.Num); if (null != field) { FieldsList.Add(field); } else { //Field does not exist in profile, continue to next field continue; } } 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); } }
/// <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 ValidateMesgDefn(MesgDefinition 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); }
public Mesg(Stream fitStream, MesgDefinition defnMesg) : this(defnMesg.GlobalMesgNum) { Read(fitStream, defnMesg); }
public void OnMesgDefinition(MesgDefinition newMesgDefinition) { Write(newMesgDefinition); }
public MesgDefinitionEventArgs(MesgDefinition newDefn) { mesgDef = new MesgDefinition(newDefn); }
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.GetMesg(MesgNum.Record).GetField("Timestamp")); timestampField.SetValue(timestamp); byte 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 + " at stream position " + fitStream.Position); } int fieldsSize = localMesgDefs[localMesgNum].GetMesgSize() - 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); } Mesg newMesg = new Mesg(mesgBuffer, localMesgDefs[localMesgNum]); newMesg.InsertField(0, timestampField); RaiseMesgEvent(newMesg); } // Is it a mesg def? else if ((nextByte & Fit.MesgDefinitionMask) == Fit.MesgDefinitionMask) { 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); } MesgDefinition newMesgDef = new MesgDefinition(mesgDefBuffer, m_lookup); localMesgDefs[newMesgDef.LocalMesgNum] = newMesgDef; if (MesgDefinitionEvent != null) { MesgDefinitionEvent(this, new MesgDefinitionEventArgs(newMesgDef)); } } // Is it a data mesg? else if ((nextByte & Fit.MesgDefinitionMask) == Fit.MesgHeaderMask) { MemoryStream mesgBuffer = new MemoryStream(); byte 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 + " at stream position " + fitStream.Position); } int fieldsSize = localMesgDefs[localMesgNum].GetMesgSize() - 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); } Mesg 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) { object tsValue = timestampField.GetValue(); if (tsValue != null) { timestamp = (uint)tsValue; lastTimeOffset = (int)timestamp & Fit.CompressedTimeMask; } } foreach (Field field in newMesg.FieldsList) { if (field.IsAccumulated) { int i; for (i = 0; i < field.GetNumValues(); i++) { long value = Convert.ToInt64(field.GetRawValue(i)); foreach (Field fieldIn in newMesg.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(newMesg.Num, field.Num, value); } } } // Now that the entire message is decoded we can evaluate subfields and expand any components newMesg.ExpandComponents(accumulator); RaiseMesgEvent(newMesg); } else { throw new FitException("Decode:Read - FIT decode error: Unexpected Record Header Byte 0x" + nextByte.ToString("X") + " at stream position: " + fitStream.Position); } }
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); } } } }
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 void OnMesgDefinition(MesgDefinition newMesgDefinition) { Write(newMesgDefinition); }
public Mesg(Stream fitStream, MesgDefinition defnMesg) : this(defnMesg.GlobalMesgNum) { Read(fitStream, defnMesg); }
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.mesgs[Profile.RecordIndex].GetField("Timestamp")); timestampField.SetValue(timestamp); byte 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); } Mesg 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) { 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); 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); } MesgDefinition 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) { MemoryStream mesgBuffer = new MemoryStream(); byte 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 (IOException e) { throw new FitException("Decode:DecodeNextMessage - Data Message unexpected end of file. Wanted " + fieldsSize + " bytes at stream position " + fitStream.Position, e); } Mesg 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; } 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 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 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.mesgs[Profile.RecordIndex].GetField("Timestamp")); timestampField.SetValue(timestamp); byte 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); } Mesg 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) { 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); 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); } MesgDefinition 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) { MemoryStream mesgBuffer = new MemoryStream(); byte 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); } Mesg 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 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(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 (null == field) { field = Profile.GetField(this.Num, fieldDef.Num); if (null != field) { fields.Add(field); } else { //Field does not exist in profile, continue to next field continue; } } // The field could be blank, correctly formed or partially filled while (field.GetSize() < fieldDef.Size) { if ((field.GetNumValues() == 1) && ((fieldDef.Type & Fit.BaseTypeNumMask) == Fit.String)) { //Has to be a string. try { byte[] value = (byte[])field.GetValue(); List <byte> temp = new List <byte>(value); while (temp.Count < fieldDef.Size) { temp.Add(Convert.ToByte(Fit.BaseType[fieldDef.Type & Fit.BaseTypeNumMask].invalidValue)); } field.SetValue(temp.ToArray()); } catch (Exception) { throw new FitException("Exception occurred while resizing field to match definition."); } } else { 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++) { bool invalid = true; switch (field.Type & Fit.BaseTypeNumMask) { case Fit.Enum: case Fit.Byte: case Fit.UInt8: case Fit.UInt8z: value = mesgReader.ReadByte(); if ((byte)value != (byte)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue) { invalid = false; } break; case Fit.SInt8: value = mesgReader.ReadSByte(); if ((sbyte)value != (sbyte)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue) { invalid = false; } break; case Fit.SInt16: value = mesgReader.ReadInt16(); if ((short)value != (short)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue) { invalid = false; } break; case Fit.UInt16: case Fit.UInt16z: value = mesgReader.ReadUInt16(); if ((ushort)value != (ushort)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue) { invalid = false; } break; case Fit.SInt32: value = mesgReader.ReadInt32(); if ((int)value != (int)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue) { invalid = false; } break; case Fit.UInt32: case Fit.UInt32z: value = mesgReader.ReadUInt32(); if ((uint)value != (uint)Fit.BaseType[field.Type & Fit.BaseTypeNumMask].invalidValue) { invalid = false; } break; case Fit.Float32: value = mesgReader.ReadSingle(); // TODO! Unless we find a different way to store floats, we dont have a good way to compare if (!float.IsNaN((float)value)) { invalid = false; } break; case Fit.Float64: value = mesgReader.ReadDouble(); // TODO! Unless we find a different way to store floats, we dont have a good way to compare if (!double.IsNaN((double)value)) { invalid = false; } break; default: value = mesgReader.ReadBytes(fieldDef.Size); break; } if (!invalid || numElements > 1) { field.SetRawValue(i, value); } } } } }
public MesgDefinitionEventArgs(MesgDefinition newDefn) { mesgDef = new MesgDefinition(newDefn); }
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 // preserve the 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); } } if ((field.values.Count > 0) && (field.components.Count > 0)) { int offset = 0; foreach (FieldComponent component in field.components) { if (component.fieldNum != Fit.FieldNumInvalid) { Field componentField = new Field(Profile.GetMesg(this.Num).GetField(component.fieldNum)); long?bitsValue = field.GetBitsValue(offset, component.bits, componentField.Type); if (bitsValue == null) { break; } if (component.accumulate == true) { bitsValue = component.Accumulate(bitsValue.Value); } // Remove containing field scale and offset float fbitsValue = Convert.ToSingle(bitsValue); fbitsValue = ((float)fbitsValue / component.scale) - component.offset; if (this.HasField(componentField.Num) == true) { this.GetField(componentField.Num).SetValue(this.GetField(componentField.Num).values.Count, fbitsValue); } else { componentField.SetValue(fbitsValue); this.SetField(componentField); } } offset += component.bits; } } } }
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()) { 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.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.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 defnMesg.DeveloperFieldDefinitions) { DeveloperField fld = GetDeveloperField(fldDef.FieldNum, fldDef.DeveloperDataIndex); if (ReferenceEquals(fld, null)) { fld = new DeveloperField(fldDef); SetDeveloperField(fld); } ReadFieldValue(fld, fldDef.Size, mesgReader); } }