diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java index f73d5bd70..77c250c51 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminSupport.java @@ -147,8 +147,8 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni RecordData today = new RecordData(GlobalDefinitionsEnum.TODAY_WEATHER_CONDITIONS.getRecordDefinition()); today.setFieldByName("weather_report", 0); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast - today.setFieldByName("timestamp", GarminTimeUtils.unixTimeToGarminTimestamp(weather.timestamp)); - today.setFieldByName("observed_at_time", GarminTimeUtils.unixTimeToGarminTimestamp(weather.timestamp)); + today.setFieldByName("timestamp", weather.timestamp); + today.setFieldByName("observed_at_time", weather.timestamp); today.setFieldByName("temperature", weather.currentTemp - 273.15); today.setFieldByName("low_temperature", weather.todayMinTemp - 273.15); today.setFieldByName("high_temperature", weather.todayMaxTemp - 273.15); @@ -168,7 +168,7 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni WeatherSpec.Hourly hourly = weather.hourly.get(hour); RecordData weatherHourlyForecast = new RecordData(GlobalDefinitionsEnum.HOURLY_WEATHER_FORECAST.getRecordDefinition()); weatherHourlyForecast.setFieldByName("weather_report", 1); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast - weatherHourlyForecast.setFieldByName("timestamp", GarminTimeUtils.unixTimeToGarminTimestamp(hourly.timestamp)); + weatherHourlyForecast.setFieldByName("timestamp", hourly.timestamp); weatherHourlyForecast.setFieldByName("temperature", hourly.temp - 273.15); weatherHourlyForecast.setFieldByName("condition", FitWeatherConditions.openWeatherCodeToFitWeatherStatus(hourly.conditionCode)); weatherHourlyForecast.setFieldByName("wind_direction", hourly.windDirection); @@ -184,7 +184,7 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni // RecordData todayDailyForecast = new RecordData(GlobalDefinitionsEnum.DAILY_WEATHER_FORECAST.getRecordDefinition()); todayDailyForecast.setFieldByName("weather_report", 2); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast - todayDailyForecast.setFieldByName("timestamp", GarminTimeUtils.unixTimeToGarminTimestamp(weather.timestamp)); + todayDailyForecast.setFieldByName("timestamp", weather.timestamp); todayDailyForecast.setFieldByName("low_temperature", weather.todayMinTemp - 273.15); todayDailyForecast.setFieldByName("high_temperature", weather.todayMaxTemp - 273.15); todayDailyForecast.setFieldByName("condition", FitWeatherConditions.openWeatherCodeToFitWeatherStatus(weather.currentConditionCode)); @@ -199,7 +199,7 @@ public class GarminSupport extends AbstractBTLEDeviceSupport implements ICommuni int ts = weather.timestamp + (day + 1) * 24 * 60 * 60; //TODO: is this needed? RecordData weatherDailyForecast = new RecordData(GlobalDefinitionsEnum.DAILY_WEATHER_FORECAST.getRecordDefinition()); weatherDailyForecast.setFieldByName("weather_report", 2); // 0 = current, 1 = hourly_forecast, 2 = daily_forecast - weatherDailyForecast.setFieldByName("timestamp", GarminTimeUtils.unixTimeToGarminTimestamp(weather.timestamp)); + weatherDailyForecast.setFieldByName("timestamp", weather.timestamp); weatherDailyForecast.setFieldByName("low_temperature", daily.minTemp - 273.15); weatherDailyForecast.setFieldByName("high_temperature", daily.maxTemp - 273.15); weatherDailyForecast.setFieldByName("condition", FitWeatherConditions.openWeatherCodeToFitWeatherStatus(daily.conditionCode)); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminTimeUtils.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminTimeUtils.java index bc08437cd..1cdef52aa 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminTimeUtils.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/GarminTimeUtils.java @@ -5,7 +5,7 @@ import org.threeten.bp.ZoneId; public class GarminTimeUtils { - private static final int GARMIN_TIME_EPOCH = 631065600; + public static final int GARMIN_TIME_EPOCH = 631065600; public static int unixTimeToGarminTimestamp(int unixTime) { return unixTime - GARMIN_TIME_EPOCH; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldDefinition.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldDefinition.java index 6c64238a6..0ff9593c2 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldDefinition.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldDefinition.java @@ -1,16 +1,18 @@ package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit; +import java.nio.ByteBuffer; + import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.baseTypes.BaseType; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.MessageReader; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.messages.MessageWriter; -public class FieldDefinition { +public class FieldDefinition implements FieldInterface { private final int localNumber; private final int size; - private final BaseType baseType; + protected final BaseType baseType; private final String name; - private final int scale; - private final int offset; + protected final int scale; + protected final int offset; public FieldDefinition(int localNumber, int size, BaseType baseType, String name, int scale, int offset) { this.localNumber = localNumber; @@ -70,4 +72,18 @@ public class FieldDefinition { writer.writeByte(baseType.getIdentifier()); } + @Override + public Object decode(ByteBuffer byteBuffer) { + return baseType.decode(byteBuffer, scale, offset); + } + + @Override + public void encode(ByteBuffer byteBuffer, Object o) { + baseType.encode(byteBuffer, o, scale, offset); + } + + @Override + public void invalidate(ByteBuffer byteBuffer) { + baseType.invalidate(byteBuffer); + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldInterface.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldInterface.java new file mode 100644 index 000000000..a3135284b --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/FieldInterface.java @@ -0,0 +1,12 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit; + +import java.nio.ByteBuffer; + +public interface FieldInterface { + Object decode(ByteBuffer byteBuffer); + + void encode(ByteBuffer byteBuffer, Object o); + + void invalidate(ByteBuffer byteBuffer); + +} diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalDefinitionsEnum.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalDefinitionsEnum.java index 2fb9c0f32..de490266f 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalDefinitionsEnum.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/GlobalDefinitionsEnum.java @@ -6,6 +6,7 @@ import java.nio.ByteOrder; import java.util.Arrays; import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.baseTypes.BaseType; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions.FieldDefinitionTimestamp; public enum GlobalDefinitionsEnum { TODAY_WEATHER_CONDITIONS(MesgType.TODAY_WEATHER_CONDITIONS, new RecordDefinition( @@ -13,8 +14,8 @@ public enum GlobalDefinitionsEnum { ByteOrder.BIG_ENDIAN, MesgType.TODAY_WEATHER_CONDITIONS, Arrays.asList(new FieldDefinition(0, 1, BaseType.ENUM, "weather_report"), - new FieldDefinition(253, 4, BaseType.UINT32, "timestamp"), - new FieldDefinition(9, 4, BaseType.UINT32, "observed_at_time"), + new FieldDefinitionTimestamp(253, 4, BaseType.UINT32, "timestamp"), + new FieldDefinitionTimestamp(9, 4, BaseType.UINT32, "observed_at_time"), new FieldDefinition(1, 1, BaseType.SINT8, "temperature"), new FieldDefinition(14, 1, BaseType.SINT8, "low_temperature"), new FieldDefinition(13, 1, BaseType.SINT8, "high_temperature"), @@ -33,7 +34,7 @@ public enum GlobalDefinitionsEnum { ByteOrder.BIG_ENDIAN, MesgType.HOURLY_WEATHER_FORECAST, Arrays.asList(new FieldDefinition(0, 1, BaseType.ENUM, "weather_report"), - new FieldDefinition(253, 4, BaseType.UINT32, "timestamp"), + new FieldDefinitionTimestamp(253, 4, BaseType.UINT32, "timestamp"), new FieldDefinition(1, 1, BaseType.SINT8, "temperature"), new FieldDefinition(2, 1, BaseType.ENUM, "condition"), new FieldDefinition(3, 2, BaseType.UINT16, "wind_direction"), @@ -49,7 +50,7 @@ public enum GlobalDefinitionsEnum { ByteOrder.BIG_ENDIAN, MesgType.DAILY_WEATHER_FORECAST, Arrays.asList(new FieldDefinition(0, 1, BaseType.ENUM, "weather_report"), - new FieldDefinition(253, 4, BaseType.UINT32, "timestamp"), + new FieldDefinitionTimestamp(253, 4, BaseType.UINT32, "timestamp"), new FieldDefinition(14, 1, BaseType.SINT8, "low_temperature"), new FieldDefinition(13, 1, BaseType.SINT8, "high_temperature"), new FieldDefinition(2, 1, BaseType.ENUM, "condition"), diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/RecordData.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/RecordData.java index d1aa0f2c6..68d92b650 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/RecordData.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/RecordData.java @@ -29,7 +29,7 @@ public class RecordData { for (FieldDefinition fieldDef : recordDefinition.getFieldDefinitions()) { - fieldDataList.add(new FieldData(fieldDef.getBaseType(), totalSize, fieldDef.getSize(), fieldDef.getName(), fieldDef.getLocalNumber(), fieldDef.getScale(), fieldDef.getOffset())); + fieldDataList.add(new FieldData(fieldDef, totalSize)); totalSize += fieldDef.getSize(); } @@ -90,10 +90,10 @@ public class RecordData { StringBuilder oBuilder = new StringBuilder(); for (FieldData fieldData : fieldDataList) { - if (fieldData.getName() != null) { + if (fieldData.getName() != null && !fieldData.getName().equals("")) { oBuilder.append(fieldData.getName()); } else { - oBuilder.append(fieldData.getNumber()); + oBuilder.append("unknown_" + fieldData.getNumber()); } oBuilder.append(": "); oBuilder.append(fieldData.decode()); @@ -104,45 +104,46 @@ public class RecordData { } - private class FieldData { - private final BaseType baseType; + public FieldData getFieldByNumber(int number) { + for (FieldData fieldData : + fieldDataList) { + if (number == fieldData.getNumber()) { + return fieldData; + } + } + return null; + } + + + public class FieldData { + private FieldDefinition fieldDefinition; private final int position; private final int size; - private final String name; - private final int scale; - private final int offset; - private final int number; - public FieldData(BaseType baseType, int position, int size, String name, int number, int scale, int offset) { - this.baseType = baseType; + + public FieldData(FieldDefinition fieldDefinition, int position) { + this.fieldDefinition = fieldDefinition; this.position = position; - this.size = size; - this.name = name; - this.number = number; - this.scale = scale; - this.offset = offset; + this.size = fieldDefinition.getSize(); } - public BaseType getBaseType() { - return baseType; - } public String getName() { - return name; + return fieldDefinition.getName(); } public int getNumber() { - return number; + return fieldDefinition.getLocalNumber(); } public void invalidate() { goToPosition(); - if (STRING.equals(getBaseType())) { + if (STRING.equals(fieldDefinition.getBaseType())) { for (int i = 0; i < size; i++) { valueHolder.put((byte) 0); } return; } - baseType.invalidate(valueHolder); + fieldDefinition.invalidate(valueHolder); } private void goToPosition() { @@ -159,18 +160,18 @@ public class RecordData { throw new IllegalArgumentException("Array of values not supported yet"); //TODO: handle arrays Object o = objects[0]; goToPosition(); - if (STRING.equals(getBaseType())) { + if (STRING.equals(fieldDefinition.getBaseType())) { final byte[] bytes = ((String) o).getBytes(StandardCharsets.UTF_8); valueHolder.put(Arrays.copyOf(bytes, Math.min(this.size - 1, bytes.length))); valueHolder.put((byte) 0); return; } - getBaseType().encode(valueHolder, o, scale, offset); + fieldDefinition.encode(valueHolder, o); } public Object decode() { goToPosition(); - if (STRING.equals(getBaseType())) { + if (STRING.equals(fieldDefinition.getBaseType())) { final byte[] bytes = new byte[size]; valueHolder.get(bytes); final int zero = ArrayUtils.indexOf((byte) 0, bytes); @@ -180,7 +181,8 @@ public class RecordData { return new String(bytes, 0, zero, StandardCharsets.UTF_8); } //TODO: handle arrays - return getBaseType().decode(valueHolder, scale, offset); + return fieldDefinition.decode(valueHolder); + } } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionTimestamp.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionTimestamp.java new file mode 100644 index 000000000..fed1ba665 --- /dev/null +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/garmin/fit/fieldDefinitions/FieldDefinitionTimestamp.java @@ -0,0 +1,26 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.fieldDefinitions; + +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.FieldDefinition; +import nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.fit.baseTypes.BaseType; + +import static nodomain.freeyourgadget.gadgetbridge.service.devices.garmin.GarminTimeUtils.GARMIN_TIME_EPOCH; + +public class FieldDefinitionTimestamp extends FieldDefinition { + public FieldDefinitionTimestamp(int localNumber, int size, BaseType baseType, String name) { + super(localNumber, size, baseType, name, 1, GARMIN_TIME_EPOCH); + } + +// @Override +// public Object decode(ByteBuffer byteBuffer) { +// return new Timestamp((long) baseType.decode(byteBuffer, scale, offset) * 1000L); +// } +// +// @Override +// public void encode(ByteBuffer byteBuffer, Object o) { +// if(o instanceof Timestamp) { +// baseType.encode(byteBuffer, (int) (((Timestamp) o).getTime() / 1000L), scale, offset); +// return; +// } +// baseType.encode(byteBuffer, o, scale, offset); +// } +}