read method
Implementation
void read(Uint8List data, {DecodeMode mode = DecodeMode.normal}) {
EndianBinaryReader reader = EndianBinaryReader(data);
if (mode == DecodeMode.normal || mode == DecodeMode.invalidHeader) {
Header header = Header();
try {
header.read(reader);
} catch (e) {
if (mode == DecodeMode.normal) rethrow;
}
if (mode == DecodeMode.normal) {
// CRC Check
int calculatedCrc = Crc.calc16(data, data.length - 2);
int fileCrc = data[data.length - 2] | (data[data.length - 1] << 8);
if (calculatedCrc != fileCrc) {
throw FitException('FIT decode error: File CRC mismatch');
}
}
}
while (reader.position < reader.length - 2) {
int headerByte = reader.readByte();
if ((headerByte & Fit.mesgDefinitionMask) == Fit.mesgDefinitionMask) {
// Message Definition
reader.position--; // Back up to read full definition
MesgDefinition mesgDef = MesgDefinition();
mesgDef.read(reader, lookup: _lookup);
_localMesgDefinitions[mesgDef.localMesgNum] = mesgDef;
onMesgDefinition?.call(mesgDef);
} else if ((headerByte & Fit.compressedHeaderMask) ==
Fit.compressedHeaderMask) {
// Compressed Timestamp Header
int timeOffset = headerByte & Fit.compressedTimeMask;
_timestamp += (timeOffset - _lastTimeOffset) & Fit.compressedTimeMask;
_lastTimeOffset = timeOffset;
int localMesgNum = (headerByte & Fit.compressedLocalMesgNumMask) >> 5;
MesgDefinition? def = _localMesgDefinitions[localMesgNum];
if (def != null) {
Mesg newMesg = Mesg.fromDefinition(def);
newMesg.read(reader, def);
// Add Timestamp Field
Mesg recordMesg = Profile.getMesg(MesgNum.record);
Field? timestampProfileField = recordMesg.getFieldByName('timestamp');
if (timestampProfileField != null) {
Field timestampField = Field.fromOther(timestampProfileField);
timestampField.setValue(_timestamp);
newMesg.insertField(0, timestampField);
}
newMesg.expandComponents(_accumulator);
_handleMetaData(newMesg);
onMesg?.call(newMesg);
}
} else {
// Data Message
int localMesgNum = headerByte & Fit.localMesgNumMask;
MesgDefinition? def = _localMesgDefinitions[localMesgNum];
if (def != null) {
Mesg newMesg = Mesg.fromDefinition(def);
newMesg.read(reader, def);
Field? timestampField = newMesg.getFieldByName('timestamp');
if (timestampField != null) {
Object? val = timestampField.value;
if (val is int) {
_timestamp = val;
_lastTimeOffset = _timestamp & Fit.compressedTimeMask;
}
}
// Accumulate fields
for (var field in newMesg.fields) {
if (field.isAccumulated) {
for (int i = 0; i < field.getNumValues(); i++) {
var val = field.values[i];
if (val is! num) continue;
int value = val.toInt();
for (var fieldIn in newMesg.fields) {
for (var fc in fieldIn.components) {
if (fc.fieldNum == field.num && fc.accumulate) {
value = ((((value / field.scale) - field.offset) +
fc.offset) *
fc.scale)
.round();
}
}
}
_accumulator.set(newMesg.num, field.num, value);
}
}
}
newMesg.expandComponents(_accumulator);
_handleMetaData(newMesg);
onMesg?.call(newMesg);
} else {
// Should not happen if FIT is valid
break;
}
}
}
}