SENSORPOINT and TRACKPOINT require a distance to be stored.

TrackRecording and TrackStatisticsUpdater.

Part of #500
Fixes #1074.
This commit is contained in:
Dennis Guse
2022-01-02 14:50:57 +01:00
parent c4b8082efc
commit 1163f74b98
10 changed files with 200 additions and 149 deletions
@@ -38,7 +38,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.stream.Collectors;
import de.dennisguse.opentracks.R;
import de.dennisguse.opentracks.content.data.Distance;
@@ -129,21 +128,21 @@ public class ExportImportTest {
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:02Z"), ZoneId.of("CET")));
trackId = service.startNewTrack();
service.stopUpdateRecordingData();
Distance sensorDistance = Distance.of(10); // recording distance interval
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:03Z"), 3, 14, 10, 15, 10, 1);
service.insertMarker("Marker 1", "Marker 1 category", "Marker 1 desc", null);
// A sensor-only TrackPoint
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:04Z"), ZoneId.of("CET")));
mockAltitudeChange(trackPointCreator, 1);
sendSensor(trackPointCreator, Instant.parse("2020-02-02T02:02:04Z"));
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:05Z"), 3, 14.002, 10, 15, 10, 0);
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:05Z"), ZoneId.of("CET")));
mockBLESensorData(trackPointCreator, 5f, Distance.of(2), 66f, 3f, 50f); // Distance will be added to next TrackPoint
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:05Z"), 3, 14.001, 10, 15, 10, 0);
service.insertMarker("Marker 2", "Marker 2 category", "Marker 2 desc", null);
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:06Z"), ZoneId.of("CET")));
@@ -152,16 +151,11 @@ public class ExportImportTest {
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:20Z"), ZoneId.of("CET")));
service.resumeCurrentTrack();
service.stopUpdateRecordingData();
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:21Z"), ZoneId.of("CET")));
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:21Z"), 3, 14.003, 10, 15, 10, 0);
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:21Z"), 3, 14.002, 10, 15, 10, 0);
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:22Z"), 3, 16, 10, 15, 10, 0);
mockBLESensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f);
sendLocation(trackPointCreator, Instant.parse("2020-02-02T02:02:23Z"), 3, 16.001, 10, 15, 10, 0);
trackPointCreator.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:24Z"), ZoneId.of("CET")));
@@ -213,7 +207,8 @@ public class ExportImportTest {
// 2. trackpoints
TrackPointAssert a = new TrackPointAssert()
.noAccuracy();
a.assertEquals(trackPoints, TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId));
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
a.assertEquals(trackPoints, actual);
// 3. trackstatistics
TrackStatistics importedTrackStatistics = importedTrack.getTrackStatistics();
@@ -226,24 +221,24 @@ public class ExportImportTest {
TrackStatistics originalTrackStatistics = track.getTrackStatistics();
assertEquals(originalTrackStatistics.getTotalTime(), importedTrackStatistics.getTotalTime());
assertEquals(Duration.ofSeconds(8), importedTrackStatistics.getTotalTime());
assertEquals(Duration.ofSeconds(7), importedTrackStatistics.getTotalTime());
assertEquals(originalTrackStatistics.getMovingTime(), importedTrackStatistics.getMovingTime());
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getMovingTime());
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getMovingTime());
// Distance
assertEquals(originalTrackStatistics.getTotalDistance(), importedTrackStatistics.getTotalDistance());
assertEquals(Distance.of(60), importedTrackStatistics.getTotalDistance());
assertEquals(123.16, importedTrackStatistics.getTotalDistance().toM(), 0.01);
// Speed
assertEquals(originalTrackStatistics.getMaxSpeed(), importedTrackStatistics.getMaxSpeed());
assertEquals(Speed.of(15), importedTrackStatistics.getMaxSpeed());
assertEquals(41.05, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(originalTrackStatistics.getAverageSpeed(), importedTrackStatistics.getAverageSpeed());
assertEquals(Speed.of(7.5), importedTrackStatistics.getAverageSpeed());
assertEquals(17.59, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(originalTrackStatistics.getAverageMovingSpeed(), importedTrackStatistics.getAverageMovingSpeed());
assertEquals(Speed.of(15), importedTrackStatistics.getAverageMovingSpeed());
assertEquals(41.05, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
// Altitude
assertEquals(originalTrackStatistics.getMinAltitude(), importedTrackStatistics.getMinAltitude(), 0.01);
@@ -322,17 +317,52 @@ public class ExportImportTest {
// 2. trackpoints
// The GPX exporter does not support exporting TrackPoints without lat/lng.
// Therefore, the track segmentation is changes.
List<TrackPoint> trackPointsWithCoordinates = trackPoints.stream().filter(it -> TrackPoint.Type.SEGMENT_START_AUTOMATIC.equals(it.getType()) || TrackPoint.Type.TRACKPOINT.equals(it.getType())).collect(Collectors.toList());
trackPointsWithCoordinates.get(0).setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
trackPointsWithCoordinates.get(1).setSensorDistance(Distance.of(20));
trackPointsWithCoordinates.get(1).setAltitudeGain(1f);
trackPointsWithCoordinates.get(1).setAltitudeLoss(1f);
trackPointsWithCoordinates.get(2).setType(TrackPoint.Type.SEGMENT_START_AUTOMATIC);
TrackPointAssert a = new TrackPointAssert()
.setDelta(0.05)
.noAccuracy(); // speed is not fully
a.assertEquals(trackPointsWithCoordinates, TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId));
List<TrackPoint> actual = TestDataUtil.getTrackPoints(contentProviderUtils, importTrackId);
a.assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, Instant.parse("2020-02-02T02:02:03Z"))
.setLatitude(3)
.setLongitude(14)
.setAltitude(10)
.setSpeed(Speed.of(15))
.setAltitudeLoss(1f)
.setAltitudeGain(1f),
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.parse("2020-02-02T02:02:05Z"))
.setLatitude(3)
.setLongitude(14.001)
.setAltitude(10)
.setSpeed(Speed.of(5))
.setAltitudeLoss(1f)
.setAltitudeGain(1f)
.setSensorDistance(Distance.of(12))
.setHeartRate_bpm(66f)
.setPower(50f)
.setCadence_rpm(3f),
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, Instant.parse("2020-02-02T02:02:21Z"))
.setLatitude(3)
.setLongitude(14.002)
.setAltitude(10)
.setAltitudeLoss(0f)
.setAltitudeGain(0f)
.setSpeed(Speed.of(15)),
new TrackPoint(TrackPoint.Type.SEGMENT_START_AUTOMATIC, Instant.parse("2020-02-02T02:02:22Z"))
.setLatitude(3)
.setLongitude(16)
.setAltitude(10)
.setAltitudeLoss(0f)
.setAltitudeGain(0f)
.setSpeed(Speed.of(15)),
new TrackPoint(TrackPoint.Type.TRACKPOINT, Instant.parse("2020-02-02T02:02:23Z"))
.setLatitude(3)
.setLongitude(16.001)
.setAltitude(10)
.setAltitudeLoss(0f)
.setAltitudeGain(0f)
.setSpeed(Speed.of(15))
), actual);
// 3. trackstatistics
TrackStatistics trackStatistics = track.getTrackStatistics();
@@ -343,16 +373,16 @@ public class ExportImportTest {
assertEquals(Instant.parse("2020-02-02T02:02:03Z"), importedTrackStatistics.getStartTime());
assertEquals(Instant.parse("2020-02-02T02:02:23Z"), importedTrackStatistics.getStopTime());
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getTotalTime());
assertEquals(Duration.ofSeconds(4), importedTrackStatistics.getMovingTime());
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getTotalTime());
assertEquals(Duration.ofSeconds(3), importedTrackStatistics.getMovingTime());
// Distance
assertEquals(Distance.of(60), importedTrackStatistics.getTotalDistance());
assertEquals(123.16, importedTrackStatistics.getTotalDistance().toM(), 0.01);
// Speed
assertEquals(Speed.of(15), importedTrackStatistics.getMaxSpeed());
assertEquals(Speed.of(15), importedTrackStatistics.getAverageSpeed());
assertEquals(Speed.of(15), importedTrackStatistics.getAverageMovingSpeed());
assertEquals(41.05, importedTrackStatistics.getMaxSpeed().toMPS(), 0.01);
assertEquals(41.05, importedTrackStatistics.getAverageSpeed().toMPS(), 0.01);
assertEquals(41.05, importedTrackStatistics.getAverageMovingSpeed().toMPS(), 0.01);
// Altitude
assertEquals(10, importedTrackStatistics.getMinAltitude(), 0.01);
@@ -424,19 +454,21 @@ public class ExportImportTest {
Mockito.when(cadence.getValue()).thenReturn(cyclingCadence);
sensorDataSet.set(cadence);
SensorDataCycling.DistanceSpeed.Data distanceSpeedData = Mockito.mock(SensorDataCycling.DistanceSpeed.Data.class);
Mockito.when(distanceSpeedData.getDistanceOverall()).thenReturn(distance);
Mockito.when(distanceSpeedData.getSpeed()).thenReturn(Speed.of(speed));
SensorDataCycling.DistanceSpeed distanceSpeed = Mockito.mock(SensorDataCycling.DistanceSpeed.class);
Mockito.when(distanceSpeed.hasValue()).thenReturn(true);
Mockito.when(distanceSpeed.getValue()).thenReturn(distanceSpeedData);
sensorDataSet.set(distanceSpeed);
if (distance != null && speed != null) {
SensorDataCycling.DistanceSpeed.Data distanceSpeedData = Mockito.mock(SensorDataCycling.DistanceSpeed.Data.class);
Mockito.when(distanceSpeedData.getDistanceOverall()).thenReturn(distance);
Mockito.when(distanceSpeedData.getSpeed()).thenReturn(Speed.of(speed));
SensorDataCycling.DistanceSpeed distanceSpeed = Mockito.mock(SensorDataCycling.DistanceSpeed.class);
Mockito.when(distanceSpeed.hasValue()).thenReturn(true);
Mockito.when(distanceSpeed.getValue()).thenReturn(distanceSpeedData);
sensorDataSet.set(distanceSpeed);
}
sensorDataSet.fillTrackPoint(trackPoint);
return sensorDataSet;
}
});
trackPointCreator.onChange(null);
}
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
@@ -445,11 +477,6 @@ public class ExportImportTest {
altitudeSumManager.setAltitudeLoss_m(altitudeGain);
}
private void sendSensor(TrackPointCreator trackPointCreator, Instant time) {
trackPointCreator.setClock(Clock.fixed(time, ZoneId.of("CET")));
trackPointCreator.onNewTrackPointWithoutGPS();
}
private void sendLocation(TrackPointCreator trackPointCreator, Instant time, double latitude, double longitude, float accuracy, float speed, float altitude, float altitudeGain) {
Location location = new Location("mock");
location.setLatitude(latitude);
@@ -62,6 +62,7 @@ import de.dennisguse.opentracks.content.provider.ContentProviderUtils;
import de.dennisguse.opentracks.io.file.importer.TrackPointAssert;
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
import de.dennisguse.opentracks.services.sensors.AltitudeSumManager;
import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager;
import de.dennisguse.opentracks.settings.PreferencesUtils;
import de.dennisguse.opentracks.stats.TrackStatistics;
@@ -465,8 +466,10 @@ public class TrackRecordingServiceTest {
// Reset service (if some previous test failed)
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
.getService();
service.endCurrentTrack();
service.getTrackPointCreator().setRemoteSensorManager(new BluetoothRemoteSensorManager(context, service.getTrackPointCreator()));
service.getTrackPointCreator().setClock(Clock.systemUTC());
service.endCurrentTrack();
service.sharedPreferenceChangeListener.onSharedPreferenceChanged(null, null);
}
}
@@ -382,7 +382,6 @@ public class TrackRecordingServiceTestLocation {
), trackPoints);
}
@Deprecated // Will be superseded when fixing #500
@MediumTest
@Test
public void testOnLocationChangedAsync_idle_withSensorDistance() {
@@ -407,23 +406,25 @@ public class TrackRecordingServiceTestLocation {
// when
altitudeSumManager.addAltitudeGain_m(6f);
altitudeSumManager.addAltitudeLoss_m(6f);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(0)));
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(2)));
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(0))); //Should be ignored
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(2))); //TODO Should be ignored; distance will be added to TrackPoint
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 1, 15);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(12)));
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 2, 15);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(13)));
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 3, 15);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(13))); //Should be ignored
altitudeSumManager.addAltitudeGain_m(6f);
altitudeSumManager.addAltitudeLoss_m(6f);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(14)));
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 15);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(14))); //Should be ignored
TrackRecordingServiceTest.newTrackPoint(service, 45.0, 35.0, 4, 15); //Should be ignored
altitudeSumManager.addAltitudeGain_m(6f);
altitudeSumManager.addAltitudeLoss_m(6f);
remoteSensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(16)));
altitudeSumManager.addAltitudeGain_m(7f);
altitudeSumManager.addAltitudeLoss_m(7f);
service.endCurrentTrack();
// then
@@ -434,34 +435,31 @@ public class TrackRecordingServiceTestLocation {
.ignoreTime();
a.assertEquals(List.of(
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, null),
new TrackPoint(TrackPoint.Type.SENSORPOINT, null) // TODO Should be ignored; is stored as it assumed to be first in current segment.
.setAltitudeGain(6f)
.setAltitudeLoss(6f)
.setSpeed(Speed.of(5))
.setSensorDistance(Distance.of(2)),
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
.setLatitude(45)
.setLongitude(35)
.setHorizontalAccuracy(Distance.of(1))
.setSpeed(Speed.of(5))
.setAltitudeGain(6f)
.setAltitudeLoss(6f)
.setSensorDistance(Distance.of(2)),
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
.setLatitude(45)
.setLongitude(35)
.setHorizontalAccuracy(Distance.of(2))
.setSensorDistance(Distance.of(0)),
new TrackPoint(TrackPoint.Type.SENSORPOINT, null)
.setSpeed(Speed.of(5))
.setSensorDistance(Distance.of(10)),
new TrackPoint(TrackPoint.Type.TRACKPOINT, null)
.setLatitude(45)
.setLongitude(35)
.setHorizontalAccuracy(Distance.of(4))
new TrackPoint(TrackPoint.Type.SENSORPOINT, null)
.setSpeed(Speed.of(5))
.setAltitudeGain(6f)
.setAltitudeLoss(6f)
.setSensorDistance(Distance.of(2)),
.setAltitudeGain(12f)
.setAltitudeLoss(12f)
.setSensorDistance(Distance.of(4)),
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, null)
.setSensorDistance(Distance.of(11))
.setSpeed(Speed.of(5))
.setAltitudeGain(6f)
.setAltitudeLoss(6f)
.setSensorDistance(Distance.of(2))
.setAltitudeGain(7f)
.setAltitudeLoss(7f)
.setSensorDistance(Distance.of(0))
), trackPoints);
}