diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java index d3c49a5d2..253d03885 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/AbstractChartFragment.java @@ -411,7 +411,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { protected DefaultChartsData refresh(GBDevice gbDevice, List samples) { // Calendar cal = GregorianCalendar.getInstance(); // cal.clear(); - int tsOffset = 0; + TimestampTranslation tsTranslation = new TimestampTranslation(); // Date date; // String dateStringFrom = ""; // String dateStringTo = ""; @@ -435,13 +435,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { for (int i = 0; i < numEntries; i++) { ActivitySample sample = samples.get(i); int type = sample.getKind(); - int ts; - if (i == 0) { - tsOffset = sample.getTimestamp(); - ts = 0; - } else { - ts = sample.getTimestamp() - tsOffset; - } + int ts = tsTranslation.shorten(sample.getTimestamp()); // System.out.println(ts); // ts = i; @@ -541,7 +535,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { combinedData = new CombinedData(); } - IAxisValueFormatter xValueFormatter = new SampleXLabelFormatter(tsOffset); + IAxisValueFormatter xValueFormatter = new SampleXLabelFormatter(tsTranslation); return new DefaultChartsData(combinedData, xValueFormatter); } @@ -750,13 +744,13 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { } protected static class SampleXLabelFormatter implements IAxisValueFormatter { - private final int tsOffset; + private final TimestampTranslation tsTranslation; SimpleDateFormat annotationDateFormat = new SimpleDateFormat("HH:mm"); // SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yyyy HH:mm"); Calendar cal = GregorianCalendar.getInstance(); - public SampleXLabelFormatter(int tsOffset) { - this.tsOffset = tsOffset; + public SampleXLabelFormatter(TimestampTranslation tsTranslation) { + this.tsTranslation = tsTranslation; } // TODO: this does not work. Cannot use precomputed labels @@ -764,7 +758,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { public String getFormattedValue(float value, AxisBase axis) { cal.clear(); int ts = (int) value; - cal.setTimeInMillis((ts + tsOffset) * 1000L); + cal.setTimeInMillis(tsTranslation.toOriginalValue(ts) * 1000L); Date date = cal.getTime(); String dateString = annotationDateFormat.format(date); return dateString; @@ -797,4 +791,31 @@ public abstract class AbstractChartFragment extends AbstractGBFragment { return 0; } } + + /** + * Awkward class that helps in translating long timestamp + * values to float (sic!) values. It basically rebases all + * timestamps to a base (the very first) timestamp value. + * + * It does this so that the large timestamp values can be used + * floating point values, where the mantissa is just 24 bits. + */ + protected static class TimestampTranslation { + private int tsOffset = -1; + + public int shorten(int timestamp) { + if (tsOffset == -1) { + tsOffset = timestamp; + return 0; + } + return timestamp - tsOffset; + } + + public int toOriginalValue(int timestamp) { + if (tsOffset == -1) { + return timestamp; + } + return timestamp + tsOffset; + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java index d56bf81f8..12b1d152d 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/charts/LiveActivityFragment.java @@ -69,13 +69,13 @@ public class LiveActivityFragment extends AbstractChartFragment { private List heartRateValues; private LineDataSet mHeartRateSet; private int mHeartRate; - private long tsOffset = -1; + private TimestampTranslation tsTranslation; private class Steps { private int initialSteps; private int steps; - private long lastTimestamp; + private int lastTimestamp; private int currentStepsPerMinute; private int maxStepsPerMinute; private int lastStepsPerMinute; @@ -97,7 +97,7 @@ public class LiveActivityFragment extends AbstractChartFragment { return maxStepsPerMinute; } - public void updateCurrentSteps(int newSteps, long timestamp) { + public void updateCurrentSteps(int newSteps, int timestamp) { try { if (steps == 0) { steps = newSteps; @@ -111,7 +111,7 @@ public class LiveActivityFragment extends AbstractChartFragment { if (newSteps >= steps) { int stepsDelta = newSteps - steps; - long timeDelta = timestamp - lastTimestamp; + int timeDelta = timestamp - lastTimestamp; currentStepsPerMinute = calculateStepsPerMinute(stepsDelta, timeDelta); if (currentStepsPerMinute > maxStepsPerMinute) { maxStepsPerMinute = currentStepsPerMinute; @@ -128,16 +128,16 @@ public class LiveActivityFragment extends AbstractChartFragment { } } - private int calculateStepsPerMinute(int stepsDelta, long millis) { + private int calculateStepsPerMinute(int stepsDelta, int seconds) { if (stepsDelta == 0) { return 0; // not walking or not enough data per mills? } - if (millis <= 0) { - throw new IllegalArgumentException("delta in millis is <= 0 -- time change?"); + if (seconds <= 0) { + throw new IllegalArgumentException("delta in seconds is <= 0 -- time change?"); } - long oneMinute = 60 * 1000; - float factor = oneMinute / millis; + int oneMinute = 60 * 1000; + float factor = oneMinute / seconds; int result = (int) (stepsDelta * factor); if (result > MAX_STEPS_PER_MINUTE) { // ignore, return previous value instead @@ -154,15 +154,13 @@ public class LiveActivityFragment extends AbstractChartFragment { switch (action) { case DeviceService.ACTION_REALTIME_STEPS: { int steps = intent.getIntExtra(DeviceService.EXTRA_REALTIME_STEPS, 0); - long timestamp = intent.getLongExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis()); - timestamp = adjust(timestamp); + int timestamp = translateTimestampFrom(intent); addEntries(steps, timestamp); break; } case DeviceService.ACTION_HEARTRATE_MEASUREMENT: { int heartRate = intent.getIntExtra(DeviceService.EXTRA_HEART_RATE_VALUE, 0); - long timestamp = intent.getLongExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis()); - timestamp = adjust(timestamp); + int timestamp = translateTimestampFrom(intent); if (isValidHeartRateValue(heartRate)) { setCurrentHeartRate(heartRate, timestamp); } @@ -172,15 +170,16 @@ public class LiveActivityFragment extends AbstractChartFragment { } }; - private long adjust(long timestamp) { - if (tsOffset == -1) { - tsOffset = timestamp; - return 0; - } - return timestamp - tsOffset; + private int translateTimestampFrom(Intent intent) { + return translateTimestamp(intent.getLongExtra(DeviceService.EXTRA_TIMESTAMP, System.currentTimeMillis())); } - private void setCurrentHeartRate(int heartRate, long timestamp) { + private int translateTimestamp(long tsMillis) { + int timestamp = (int) (tsMillis / 1000); // translate to seconds + return tsTranslation.shorten(timestamp); // and shorten + } + + private void setCurrentHeartRate(int heartRate, int timestamp) { addHistoryDataSet(true); mHeartRate = heartRate; } @@ -191,7 +190,7 @@ public class LiveActivityFragment extends AbstractChartFragment { return result; } - private void addEntries(int steps, long timestamp) { + private void addEntries(int steps, int timestamp) { mSteps.updateCurrentSteps(steps, timestamp); if (++maxStepsResetCounter > RESET_COUNT) { maxStepsResetCounter = 0; @@ -203,7 +202,7 @@ public class LiveActivityFragment extends AbstractChartFragment { // addEntries(); } - private void addEntries(long timestamp) { + private void addEntries(int timestamp) { mTotalStepsChart.setSingleEntryYValue(mSteps.getTotalSteps()); YAxis stepsPerMinuteCurrentYAxis = mStepsPerMinuteCurrentChart.getAxisLeft(); int maxStepsPerMinute = mSteps.getMaxStepsPerMinute(); @@ -255,6 +254,7 @@ public class LiveActivityFragment extends AbstractChartFragment { filterLocal.addAction(DeviceService.ACTION_REALTIME_STEPS); filterLocal.addAction(DeviceService.ACTION_HEARTRATE_MEASUREMENT); heartRateValues = new ArrayList<>(); + tsTranslation = new TimestampTranslation(); View rootView = inflater.inflate(R.layout.fragment_live_activity, container, false); @@ -315,7 +315,7 @@ public class LiveActivityFragment extends AbstractChartFragment { * Called in the UI thread. */ private void pulse() { - addEntries(adjust(System.currentTimeMillis())); + addEntries(translateTimestamp(System.currentTimeMillis())); LineData historyData = (LineData) mStepsPerMinuteHistoryChart.getData(); if (historyData == null) { @@ -333,7 +333,7 @@ public class LiveActivityFragment extends AbstractChartFragment { GBApplication.deviceService().onEnableRealtimeHeartRateMeasurement(true); } - private long getPulseIntervalMillis() { + private int getPulseIntervalMillis() { return 1000; }