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")); } }