Garmin: Improve developer field decoding

This commit is contained in:
José Rebelo
2026-01-15 22:11:45 +01:00
committed by José Rebelo
parent effb054aaf
commit 813be065c3
4 changed files with 59 additions and 8 deletions
@@ -13,6 +13,8 @@ public class DevFieldDefinition {
private final int developerDataIndex;
private BaseType baseType;
private String name;
private int nativeMesgNum = -1;
private int nativeFieldNum = -1;
public DevFieldDefinition(int fieldDefinitionNumber, int size, int developerDataIndex, String name) {
this.fieldDefinitionNumber = fieldDefinitionNumber;
@@ -59,6 +61,22 @@ public class DevFieldDefinition {
this.name = name;
}
public int getNativeMesgNum() {
return nativeMesgNum;
}
public void setNativeMesgNum(final int nativeMesgNum) {
this.nativeMesgNum = nativeMesgNum;
}
public int getNativeFieldNum() {
return nativeFieldNum;
}
public void setNativeFieldNum(final int nativeFieldNum) {
this.nativeFieldNum = nativeFieldNum;
}
@Override
public boolean equals(Object o) {
if (o == null || getClass() != o.getClass()) return false;
@@ -137,13 +137,39 @@ public class RecordData {
}
}
public Object getFieldByNumber(int number) {
for (FieldData fieldData :
fieldDataList) {
/**
* Returns the field that matches the given **native** number, taking into account dev fields. If a dev field exists that
* has the same native number as a native field, it has precedence.
*/
public Object getFieldByNumber(final int number) {
// Developer fields are all added after regular fields in the constructor
final int regularFieldCount = recordDefinition.getFieldDefinitions() != null ?
recordDefinition.getFieldDefinitions().size() : 0;
// First, check whether we have a developer field that maps to the native field. If it exists, it has priority
final List<DevFieldDefinition> devFieldDefinitions = recordDefinition.getDevFieldDefinitions();
if (devFieldDefinitions != null) {
for (int i = 0; i < devFieldDefinitions.size(); i++) {
final DevFieldDefinition devField = devFieldDefinitions.get(i);
if (devField.getNativeMesgNum() == globalFITMessage.getNumber() && devField.getNativeFieldNum() == number) {
// Get the corresponding FieldData for this developer field
final int fieldDataIndex = regularFieldCount + i;
if (fieldDataIndex < fieldDataList.size()) {
return fieldDataList.get(fieldDataIndex).decode();
}
}
}
}
// Next, check whether there is any native field that matches the number
for (int i = 0; i < regularFieldCount; i++) {
final FieldData fieldData = fieldDataList.get(i);
if (fieldData.getNumber() == number) {
return fieldData.decode();
}
}
return null;
}
@@ -118,6 +118,16 @@ public class RecordDefinition {
BaseType baseType = BaseType.fromIdentifier((int) recordData.getFieldByName("fit_base_type_id"));
devFieldDef.setBaseType(baseType);
devFieldDef.setName((String) recordData.getFieldByName("field_name"));
final Object nativeMesgNum = recordData.getFieldByName("native_mesg_num");
final Object nativeFieldNum = recordData.getFieldByName("native_field_num");
if (nativeMesgNum instanceof Integer integer) {
devFieldDef.setNativeMesgNum(integer);
}
if (nativeFieldNum instanceof Integer integer) {
devFieldDef.setNativeFieldNum(integer);
}
}
} catch (Exception e) {
//ignore
@@ -512,6 +512,8 @@ public class GarminSupportTest extends TestBase {
FitFile fitFile = FitFile.parseIncoming(fileContents);
Assert.assertEquals(expectedOutput, fitFile.toString());
// Field 0 is not overwritten by the developer field
Assert.assertNull(fitFile.getRecords().get(3).getFieldByNumber(0));
getAllFitFieldValues(fitFile);
}
@@ -615,11 +617,6 @@ public class GarminSupportTest extends TestBase {
} catch (Exception e) {
String recordName = record.getClass().getSimpleName();
String message = methodName + " failed for " + recordName;
if ("FitRecord".equals(recordName) && "getLatitude".equals(methodName)) {
// TODO GarminSupportTest.TestFitFileDevelopersField -> FitRecord / getLatitude
// FIXME java.lang.ClassCastException: class java.lang.Integer cannot be cast to class java.lang.Double
continue;
}
throw new AssertionError(message, e);
}
}