mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-09 03:37:03 +01:00
Garmin: fix basetype handling and truncation
Numeric BaseTypes now return fractional part if a scale is set, the return type for numeric values is unboxed from Number class so that existing comparisons and checks keep working, but values are not truncated at nearest integer value. The codegen class has been updated and some of the messages are re-generated with the new code, with the exception of Hrv* messages, since updating those needs updating the related sample types. Test cases expected values have been adjusted to keep into account the fractional part of some fields. Garmin: Fix HRV value and summary types
This commit is contained in:
parent
51a0745b06
commit
fd1e81ff66
@ -206,12 +206,24 @@ public class FitImporter {
|
||||
LOG.trace("HRV summary at {}: {}", ts, record);
|
||||
final GarminHrvSummarySample sample = new GarminHrvSummarySample();
|
||||
sample.setTimestamp(ts * 1000L);
|
||||
sample.setWeeklyAverage(hrvSummary.getWeeklyAverage());
|
||||
sample.setLastNightAverage(hrvSummary.getLastNightAverage());
|
||||
sample.setLastNight5MinHigh(hrvSummary.getLastNight5MinHigh());
|
||||
sample.setBaselineLowUpper(hrvSummary.getBaselineLowUpper());
|
||||
sample.setBaselineBalancedLower(hrvSummary.getBaselineBalancedLower());
|
||||
sample.setBaselineBalancedUpper(hrvSummary.getBaselineBalancedUpper());
|
||||
if (hrvSummary.getWeeklyAverage() != null) {
|
||||
sample.setWeeklyAverage(Math.round(hrvSummary.getWeeklyAverage()));
|
||||
}
|
||||
if (hrvSummary.getLastNightAverage() != null) {
|
||||
sample.setLastNightAverage(Math.round(hrvSummary.getLastNightAverage()));
|
||||
}
|
||||
if (hrvSummary.getLastNight5MinHigh() != null) {
|
||||
sample.setLastNight5MinHigh(Math.round(hrvSummary.getLastNight5MinHigh()));
|
||||
}
|
||||
if (hrvSummary.getBaselineLowUpper() != null) {
|
||||
sample.setBaselineLowUpper(Math.round(hrvSummary.getBaselineLowUpper()));
|
||||
}
|
||||
if (hrvSummary.getBaselineBalancedLower() != null) {
|
||||
sample.setBaselineBalancedLower(Math.round(hrvSummary.getBaselineBalancedLower()));
|
||||
}
|
||||
if (hrvSummary.getBaselineBalancedUpper() != null) {
|
||||
sample.setBaselineBalancedUpper(Math.round(hrvSummary.getBaselineBalancedUpper()));
|
||||
}
|
||||
final FieldDefinitionHrvStatus.HrvStatus status = hrvSummary.getStatus();
|
||||
if (status != null) {
|
||||
sample.setStatusNum(status.getId());
|
||||
@ -226,7 +238,7 @@ public class FitImporter {
|
||||
LOG.trace("HRV value at {}: {}", ts, hrvValue.getValue());
|
||||
final GarminHrvValueSample sample = new GarminHrvValueSample();
|
||||
sample.setTimestamp(ts * 1000L);
|
||||
sample.setValue(hrvValue.getValue());
|
||||
sample.setValue(Math.round(hrvValue.getValue()));
|
||||
hrvValueSamples.add(sample);
|
||||
} else {
|
||||
LOG.trace("Unknown record: {}", record);
|
||||
|
@ -49,7 +49,45 @@ public enum BaseType {
|
||||
}
|
||||
|
||||
public Object decode(ByteBuffer byteBuffer, double scale, int offset) {
|
||||
return baseTypeInterface.decode(byteBuffer, scale, offset);
|
||||
Object raw = baseTypeInterface.decode(byteBuffer, scale, offset);
|
||||
if (raw == null)
|
||||
return null;
|
||||
|
||||
//the following returns STRING basetype but also all specialized FieldDefinition classes
|
||||
if (!Number.class.isAssignableFrom(raw.getClass()))
|
||||
return raw;
|
||||
|
||||
switch (this) {
|
||||
case ENUM:
|
||||
case SINT8:
|
||||
case UINT8:
|
||||
case SINT16:
|
||||
case UINT16:
|
||||
case UINT8Z:
|
||||
case UINT16Z:
|
||||
case BASE_TYPE_BYTE:
|
||||
if (scale != 1) {
|
||||
return ((Number) raw).floatValue();
|
||||
} else {
|
||||
return ((Number) raw).intValue();
|
||||
}
|
||||
case SINT32:
|
||||
case UINT32:
|
||||
case UINT32Z:
|
||||
case SINT64:
|
||||
case UINT64:
|
||||
case UINT64Z:
|
||||
if (scale != 1) {
|
||||
return ((Number) raw).doubleValue();
|
||||
} else {
|
||||
return ((Number) raw).longValue();
|
||||
}
|
||||
case FLOAT32:
|
||||
return ((Number) raw).floatValue();
|
||||
case FLOAT64:
|
||||
return ((Number) raw).doubleValue();
|
||||
}
|
||||
return raw;
|
||||
}
|
||||
|
||||
public void encode(ByteBuffer byteBuffer, Object o, double scale, int offset) {
|
||||
|
@ -34,7 +34,7 @@ public class BaseTypeByte implements BaseTypeInterface {
|
||||
return null;
|
||||
if (b == invalid)
|
||||
return null;
|
||||
return (int) (Math.round(b / scale) - offset);
|
||||
return (b / scale) - offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -26,7 +26,7 @@ public class BaseTypeFloat implements BaseTypeInterface {
|
||||
}
|
||||
if (Float.isNaN(f) || f == invalid)
|
||||
return null;
|
||||
return (float) (f / scale) - offset;
|
||||
return (f / scale) - offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,7 +32,7 @@ public class BaseTypeInt implements BaseTypeInterface {
|
||||
return null;
|
||||
if (i == invalid)
|
||||
return null;
|
||||
return (Math.round(i / scale) - offset);
|
||||
return (i / scale) - offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -32,7 +32,7 @@ public class BaseTypeShort implements BaseTypeInterface {
|
||||
return null;
|
||||
if (s == invalid)
|
||||
return null;
|
||||
return (int) Math.round(s / scale) - offset;
|
||||
return (s / scale) - offset;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -268,14 +268,22 @@ public class FitCodeGen {
|
||||
case UINT8Z:
|
||||
case UINT16Z:
|
||||
case BASE_TYPE_BYTE:
|
||||
return Integer.class;
|
||||
if (primitive.getScale() != 1) {
|
||||
return Float.class;
|
||||
} else {
|
||||
return Integer.class;
|
||||
}
|
||||
case SINT32:
|
||||
case UINT32:
|
||||
case UINT32Z:
|
||||
case SINT64:
|
||||
case UINT64:
|
||||
case UINT64Z:
|
||||
return Long.class;
|
||||
if (primitive.getScale() != 1) {
|
||||
return Double.class;
|
||||
} else {
|
||||
return Long.class;
|
||||
}
|
||||
case STRING:
|
||||
return String.class;
|
||||
case FLOAT32:
|
||||
|
@ -22,33 +22,33 @@ public class FitHrvSummary extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getWeeklyAverage() {
|
||||
return (Integer) getFieldByNumber(0);
|
||||
public Float getWeeklyAverage() {
|
||||
return (Float) getFieldByNumber(0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getLastNightAverage() {
|
||||
return (Integer) getFieldByNumber(1);
|
||||
public Float getLastNightAverage() {
|
||||
return (Float) getFieldByNumber(1);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getLastNight5MinHigh() {
|
||||
return (Integer) getFieldByNumber(2);
|
||||
public Float getLastNight5MinHigh() {
|
||||
return (Float) getFieldByNumber(2);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getBaselineLowUpper() {
|
||||
return (Integer) getFieldByNumber(3);
|
||||
public Float getBaselineLowUpper() {
|
||||
return (Float) getFieldByNumber(3);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getBaselineBalancedLower() {
|
||||
return (Integer) getFieldByNumber(4);
|
||||
public Float getBaselineBalancedLower() {
|
||||
return (Float) getFieldByNumber(4);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getBaselineBalancedUpper() {
|
||||
return (Integer) getFieldByNumber(5);
|
||||
public Float getBaselineBalancedUpper() {
|
||||
return (Float) getFieldByNumber(5);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -21,8 +21,8 @@ public class FitHrvValue extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getValue() {
|
||||
return (Integer) getFieldByNumber(0);
|
||||
public Float getValue() {
|
||||
return (Float) getFieldByNumber(0);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -41,18 +41,18 @@ public class FitLap extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getTotalElapsedTime() {
|
||||
return (Long) getFieldByNumber(7);
|
||||
public Double getTotalElapsedTime() {
|
||||
return (Double) getFieldByNumber(7);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getTotalTimerTime() {
|
||||
return (Long) getFieldByNumber(8);
|
||||
public Double getTotalTimerTime() {
|
||||
return (Double) getFieldByNumber(8);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getTotalDistance() {
|
||||
return (Long) getFieldByNumber(9);
|
||||
public Double getTotalDistance() {
|
||||
return (Double) getFieldByNumber(9);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -36,8 +36,8 @@ public class FitRecord extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getAltitude() {
|
||||
return (Integer) getFieldByNumber(2);
|
||||
public Float getAltitude() {
|
||||
return (Float) getFieldByNumber(2);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -46,13 +46,13 @@ public class FitRecord extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getDistance() {
|
||||
return (Long) getFieldByNumber(5);
|
||||
public Double getDistance() {
|
||||
return (Double) getFieldByNumber(5);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getSpeed() {
|
||||
return (Integer) getFieldByNumber(6);
|
||||
public Float getSpeed() {
|
||||
return (Float) getFieldByNumber(6);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@ -61,8 +61,8 @@ public class FitRecord extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getEnhancedAltitude() {
|
||||
return (Long) getFieldByNumber(78);
|
||||
public Double getEnhancedAltitude() {
|
||||
return (Double) getFieldByNumber(78);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -36,13 +36,13 @@ public class FitSession extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getStartLatitude() {
|
||||
return (Long) getFieldByNumber(3);
|
||||
public Double getStartLatitude() {
|
||||
return (Double) getFieldByNumber(3);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Long getStartLongitude() {
|
||||
return (Long) getFieldByNumber(4);
|
||||
public Double getStartLongitude() {
|
||||
return (Double) getFieldByNumber(4);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -43,8 +43,8 @@ public class FitUserProfile extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getWeight() {
|
||||
return (Integer) getFieldByNumber(4);
|
||||
public Float getWeight() {
|
||||
return (Float) getFieldByNumber(4);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -45,8 +45,8 @@ public class FitWeather extends RecordData {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Integer getWindSpeed() {
|
||||
return (Integer) getFieldByNumber(4);
|
||||
public Float getWindSpeed() {
|
||||
return (Float) getFieldByNumber(4);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
@ -336,7 +336,7 @@ public class GarminSupportTest extends TestBase {
|
||||
"FitFileId{serial_number=3889965805, manufacturer=1, product=1561, type=SETTINGS}, " +
|
||||
"FitFileCreator{software_version=340}, " +
|
||||
"FitDeviceSettings{utc_offset=0, time_offset=0, active_time_zone=0, unknown_3(ENUM/1)=0, time_mode=0, time_zone_offset=0, unknown_10(ENUM/1)=3, unknown_11(ENUM/1)=0, backlight_mode=2, unknown_13(UINT8/1)=0, unknown_14(UINT8/1)=0, unknown_15(UINT8/1)=50, unknown_21(ENUM/1)=1, unknown_22(ENUM/1)=0, unknown_26(ENUM/1)=254, unknown_27(ENUM/1)=0, unknown_29(ENUM/1)=0, unknown_52(ENUM/1)=0, unknown_53(ENUM/1)=1}, " +
|
||||
"FitUserProfile{friendly_name=edge510, weight=78, gender=1, age=41, height=183, language=english, elev_setting=metric, weight_setting=metric, resting_heart_rate=60, default_max_biking_heart_rate=185, default_max_heart_rate=185, hr_setting=1, speed_setting=metric, dist_setting=metric, power_setting=1, activity_class=168, position_setting=2, temperature_setting=metric}, " +
|
||||
"FitUserProfile{friendly_name=edge510, weight=78.0, gender=1, age=41, height=183, language=english, elev_setting=metric, weight_setting=metric, resting_heart_rate=60, default_max_biking_heart_rate=185, default_max_heart_rate=185, hr_setting=1, speed_setting=metric, dist_setting=metric, power_setting=1, activity_class=168, position_setting=2, temperature_setting=metric}, " +
|
||||
"RecordData{UNK_4, unknown_254(UINT16/2)=0, unknown_1(UINT16Z/2)=50008, unknown_0(UINT8/1)=1, unknown_3(UINT8Z/1)=1}, " +
|
||||
"RecordData{UNK_6, unknown_0(STRING/4)=EVO, unknown_3(UINT32/4)=45719172, unknown_39(UINT8Z/4)=[39,53,,], unknown_41(UINT8Z/12)=[23,21,19,18,17,16,15,14,13,12,11,], unknown_254(UINT16/2)=0, unknown_7(UINT16Z/2)=47617, unknown_8(UINT16/2)=2096, unknown_9(UINT16/2)=0, unknown_10(UINT16/2)=80, unknown_11(UINT16/2)=500, unknown_12(UINT8/1)=1, unknown_13(UINT8/1)=1, unknown_14(UINT8/1)=0, unknown_15(UINT8/1)=0, unknown_16(UINT8/1)=0, unknown_17(UINT8/1)=0, unknown_18(UINT8/1)=1, unknown_19(UINT8/1)=254, unknown_20(UINT8/1)=1, unknown_24(UINT8Z/1)=5, unknown_35(UINT8/3)=[0,50,], unknown_36(ENUM/1)=4, unknown_38(UINT8Z/1)=2, unknown_40(UINT8Z/1)=11, unknown_44(ENUM/1)=0}, " +
|
||||
"RecordData{UNK_6, unknown_0(STRING/5)=P2SL, unknown_3(UINT32/4)=0, unknown_39(UINT8Z/4)=[39,53,,], unknown_41(UINT8Z/12)=[23,21,19,18,17,16,15,14,13,12,11,], unknown_254(UINT16/2)=1, unknown_7(UINT16Z/2)=28209, unknown_8(UINT16/2)=2096, unknown_9(UINT16/2)=0, unknown_10(UINT16/2)=90, unknown_11(UINT16/2)=500, unknown_12(UINT8/1)=1, unknown_13(UINT8/1)=1, unknown_14(UINT8/1)=0, unknown_15(UINT8/1)=0, unknown_16(UINT8/1)=0, unknown_17(UINT8/1)=0, unknown_18(UINT8/1)=1, unknown_19(UINT8/1)=254, unknown_20(UINT8/1)=1, unknown_24(UINT8Z/1)=5, unknown_35(UINT8/3)=[0,118,190], unknown_36(ENUM/1)=4, unknown_38(UINT8Z/1)=2, unknown_40(UINT8Z/1)=11, unknown_44(ENUM/1)=0}, " +
|
||||
@ -364,9 +364,9 @@ public class GarminSupportTest extends TestBase {
|
||||
"FitFileId{manufacturer=15, type=ACTIVITY, product=9001, serial_number=1701}, " +
|
||||
"FitDeveloperData{application_id=[1,1,2,3,5,8,13,21,34,55,89,144,233,121,98,219], developer_data_index=0}, " +
|
||||
"FitFieldDescription{developer_data_index=0, field_definition_number=0, fit_base_type_id=1, field_name=doughnuts_earned, units=doughnuts}, " +
|
||||
"FitRecord{heart_rate=140, unknown_4(UINT8/1)=88, distance=510, speed=47, doughnuts_earned=1}, " +
|
||||
"FitRecord{heart_rate=143, unknown_4(UINT8/1)=90, distance=2080, speed=36, doughnuts_earned=2}, " +
|
||||
"FitRecord{heart_rate=144, unknown_4(UINT8/1)=92, distance=3710, speed=35, doughnuts_earned=3}" +
|
||||
"FitRecord{heart_rate=140, unknown_4(UINT8/1)=88, distance=510.0, speed=47.488, doughnuts_earned=1}, " +
|
||||
"FitRecord{heart_rate=143, unknown_4(UINT8/1)=90, distance=2080.0, speed=36.416, doughnuts_earned=2}, " +
|
||||
"FitRecord{heart_rate=144, unknown_4(UINT8/1)=92, distance=3710.0, speed=35.344, doughnuts_earned=3}" +
|
||||
"]";
|
||||
|
||||
FitFile fitFile = FitFile.parseIncoming(fileContents);
|
||||
|
Loading…
Reference in New Issue
Block a user