/// <summary> /// Checks if the reference fields in a given message indicate the subfield (alternate) /// definition should be used /// </summary> /// <param name="mesg">message of interest</param> /// <returns>true if the subfield is active</returns> internal bool CanMessageSupport(Message mesg) { Field field = mesg.GetField(refFieldNum); if (field != null) { object value = field.GetValue(0, Fit.SubfieldIndexMainField); // Float refvalues are not supported if (Convert.ToInt64(value) == Convert.ToInt64(refFieldValue)) { return(true); } } return(false); }
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); } }