diff --git a/src/androidTest/java/de/dennisguse/opentracks/content/sensor/SensorDataCyclingTest.java b/src/androidTest/java/de/dennisguse/opentracks/content/sensor/SensorDataCyclingTest.java index bb8cfae24..63ba862e8 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/content/sensor/SensorDataCyclingTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/content/sensor/SensorDataCyclingTest.java @@ -104,8 +104,8 @@ public class SensorDataCyclingTest { current.compute(previous, Distance.ofMM(2150)); // then - assertEquals(2.15, current.getValue().distance.toM(), 0.01); - assertEquals(1.20, current.getValue().speed.toMPS(), 0.01); + assertEquals(2.15, current.getValue().getDistance().toM(), 0.01); + assertEquals(1.20, current.getValue().getSpeed().toMPS(), 0.01); } @Test @@ -118,8 +118,8 @@ public class SensorDataCyclingTest { current.compute(previous, Distance.ofMM(2000)); // then - assertEquals(2, current.getValue().distance.toM(), 0.01); - assertEquals(2, current.getValue().speed.toMPS(), 0.01); + assertEquals(2, current.getValue().getDistance().toM(), 0.01); + assertEquals(2, current.getValue().getSpeed().toMPS(), 0.01); } @Test diff --git a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java index 8e6d79faa..d92d81872 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/io/file/importer/ExportImportTest.java @@ -3,9 +3,11 @@ package de.dennisguse.opentracks.io.file.importer; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.location.Location; import android.net.Uri; import android.os.Looper; +import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; import androidx.test.core.app.ApplicationProvider; import androidx.test.ext.junit.runners.AndroidJUnit4; @@ -19,6 +21,7 @@ import org.junit.BeforeClass; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mockito; import java.io.File; import java.io.IOException; @@ -34,7 +37,6 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Collectors; import de.dennisguse.opentracks.R; -import de.dennisguse.opentracks.content.data.Altitude; import de.dennisguse.opentracks.content.data.Distance; import de.dennisguse.opentracks.content.data.Marker; import de.dennisguse.opentracks.content.data.Speed; @@ -42,10 +44,16 @@ import de.dennisguse.opentracks.content.data.TestDataUtil; import de.dennisguse.opentracks.content.data.Track; import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.content.provider.ContentProviderUtils; +import de.dennisguse.opentracks.content.sensor.SensorDataCycling; +import de.dennisguse.opentracks.content.sensor.SensorDataCyclingPower; +import de.dennisguse.opentracks.content.sensor.SensorDataHeartRate; +import de.dennisguse.opentracks.content.sensor.SensorDataSet; import de.dennisguse.opentracks.io.file.TrackFileFormat; import de.dennisguse.opentracks.io.file.exporter.TrackExporter; import de.dennisguse.opentracks.services.TrackRecordingService; import de.dennisguse.opentracks.services.handlers.HandlerServer; +import de.dennisguse.opentracks.services.sensors.AltitudeSumManager; +import de.dennisguse.opentracks.services.sensors.BluetoothRemoteSensorManager; import de.dennisguse.opentracks.stats.TrackStatistics; import static org.junit.Assert.assertEquals; @@ -81,7 +89,6 @@ public class ExportImportTest { private File tmpFile; private Uri tmpFileUri; - private Track track; private List markers = new ArrayList<>(); private List trackPoints = new ArrayList<>(); @@ -119,26 +126,30 @@ public class ExportImportTest { Distance sensorDistance = hasSensorDistance ? Distance.of(5) : null; - service.newTrackPoint(createTrackPoint(Instant.parse("2020-02-02T02:02:03Z"), 3, 14, 10, 15, 10, 1, 66, 3, 50, sensorDistance), Distance.of(0)); + sendLocation(handlerServer, Instant.parse("2020-02-02T02:02:03Z"), 3, 14, 10, 15, 10, 1, 66, 3, 50, sensorDistance); service.insertMarker("Marker 1", "Marker 1 category", "Marker 1 desc", null); - service.newTrackPoint(createTrackPoint(Instant.parse("2020-02-02T02:02:04Z"), 3, 14.001, 10, 15, 10, 0, 66, 3, 50, sensorDistance), Distance.of(0)); - service.newTrackPoint(createTrackPoint(Instant.parse("2020-02-02T02:02:05Z"), 3, 14.002, 10, 15, 10, 0, 66, 3, 50, sensorDistance), Distance.of(0)); + sendLocation(handlerServer, Instant.parse("2020-02-02T02:02:04Z"), 3, 14.001, 10, 15, 10, 0, 66, 3, 50, sensorDistance); + sendLocation(handlerServer, Instant.parse("2020-02-02T02:02:05Z"), 3, 14.002, 10, 15, 10, 0, 66, 3, 50, sensorDistance); service.insertMarker("Marker 2", "Marker 2 category", "Marker 2 desc", null); handlerServer.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:06Z"), ZoneId.of("CET"))); + handlerServer.setRemoteSensorManager(new BluetoothRemoteSensorManager(context)); service.pauseCurrentTrack(); handlerServer.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:20Z"), ZoneId.of("CET"))); service.resumeCurrentTrack(); - service.newTrackPoint(createTrackPoint(Instant.parse("2020-02-02T02:02:21Z"), 3, 14.003, 10, 15, 10, 0, 66, 3, 50, sensorDistance), Distance.of(0)); - service.newTrackPoint(createTrackPoint(Instant.parse("2020-02-02T02:02:22Z"), 3, 16, 10, 15, 10, 0, 66, 3, 50, sensorDistance), Distance.of(0)); - service.newTrackPoint(createTrackPoint(Instant.parse("2020-02-02T02:02:23Z"), 3, 16.001, 10, 15, 10, 0, 66, 3, 50, sensorDistance), Distance.of(0)); + handlerServer.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:21Z"), ZoneId.of("CET"))); + sendLocation(handlerServer, Instant.parse("2020-02-02T02:02:21Z"), 3, 14.003, 10, 15, 10, 0, 66, 3, 50, sensorDistance); + + sendLocation(handlerServer, Instant.parse("2020-02-02T02:02:22Z"), 3, 16, 10, 15, 10, 0, 66, 3, 50, sensorDistance); + sendLocation(handlerServer, Instant.parse("2020-02-02T02:02:23Z"), 3, 16.001, 10, 15, 10, 0, 66, 3, 50, sensorDistance); handlerServer.setClock(Clock.fixed(Instant.parse("2020-02-02T02:02:24Z"), ZoneId.of("CET"))); + handlerServer.setRemoteSensorManager(new BluetoothRemoteSensorManager(context)); service.endCurrentTrack(); - track = contentProviderUtils.getTrack(trackId); + Track track = contentProviderUtils.getTrack(trackId); track.setIcon(TRACK_ICON); track.setCategory(TRACK_CATEGORY); track.setDescription(TRACK_DESCRIPTION); @@ -369,16 +380,49 @@ public class ExportImportTest { } } - private static TrackPoint createTrackPoint(Instant time, double latitude, double longitude, float accuracy, float speed, float altitude, float altitudeGain, float heartRate, float cyclingCadence, float power, Distance distance) { - TrackPoint tp = new TrackPoint(latitude, longitude, Altitude.WGS84.of(altitude), time); - tp.setHorizontalAccuracy(Distance.of(accuracy)); - tp.setSpeed(Speed.of(speed)); - tp.setHeartRate_bpm(heartRate); - tp.setCyclingCadence_rpm(cyclingCadence); - tp.setPower(power); - tp.setAltitudeGain(altitudeGain); - tp.setAltitudeLoss(altitudeGain); //TODO - tp.setSensorDistance(distance); - return tp; + private void sendLocation(HandlerServer handlerServer, Instant time, double latitude, double longitude, float accuracy, float speed, float altitude, float altitudeGain, float heartRate, float cyclingCadence, float power, Distance distance) { + Location location = new Location("mock"); + location.setLatitude(latitude); + location.setLongitude(longitude); + location.setAccuracy(accuracy); + location.setSpeed(speed); + location.setAltitude(altitude); + + handlerServer.setAltitudeSumManager(new AltitudeSumManager() { + @Override + public void fill(@NonNull TrackPoint trackPoint) { + trackPoint.setAltitudeGain(altitudeGain); + trackPoint.setAltitudeLoss(altitudeGain); + } + }); + + handlerServer.setRemoteSensorManager(new BluetoothRemoteSensorManager(context) { + @Override + public SensorDataSet fill(@NonNull TrackPoint trackPoint) { + SensorDataSet sensorDataSet = new SensorDataSet(); + sensorDataSet.set(new SensorDataCyclingPower("power", "power", power)); + sensorDataSet.set(new SensorDataHeartRate("heartRate", "heartRate", heartRate)); + + SensorDataCycling.Cadence cadence = Mockito.mock(SensorDataCycling.Cadence.class); + Mockito.when(cadence.hasValue()).thenReturn(true); + 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); + + sensorDataSet.fillTrackPoint(trackPoint); + return sensorDataSet; + } + }); + + handlerServer.setClock(Clock.fixed(time, ZoneId.of("CET"))); + handlerServer.getLocationHandler().onLocationChanged(location); } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/content/data/TrackPoint.java b/src/main/java/de/dennisguse/opentracks/content/data/TrackPoint.java index 8eb6175c0..520a86806 100644 --- a/src/main/java/de/dennisguse/opentracks/content/data/TrackPoint.java +++ b/src/main/java/de/dennisguse/opentracks/content/data/TrackPoint.java @@ -203,6 +203,9 @@ public class TrackPoint { if (hasAltitude()) { location.setAltitude(altitude.toM()); } + if (hasSpeed()) { + location.setSpeed((float) speed.toMPS()); + } return location; } diff --git a/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataCycling.java b/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataCycling.java index c085d81fa..534bee338 100644 --- a/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataCycling.java +++ b/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataCycling.java @@ -169,9 +169,9 @@ public final class SensorDataCycling { } public static class Data { - public final Distance distance; - public final Distance distanceOverall; - public final Speed speed; + private final Distance distance; + private final Distance distanceOverall; + private final Speed speed; private Data(Distance distance, Distance distanceOverall, Speed speed) { this.distance = distance; @@ -179,12 +179,24 @@ public final class SensorDataCycling { this.speed = speed; } + public Distance getDistance() { + return distance; + } + + public Distance getDistanceOverall() { + return distanceOverall; + } + + public Speed getSpeed() { + return speed; + } + @Override public String toString() { return "Data{" + - "distance_m=" + distance + - ", distance_overall_m=" + distanceOverall + - ", speed_mps=" + speed + + "distance=" + getDistance() + + ", distance_overall=" + getDistanceOverall() + + ", speed=" + getSpeed() + '}'; } } diff --git a/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataSet.java b/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataSet.java index 4ac2461d1..22eb527f1 100644 --- a/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataSet.java +++ b/src/main/java/de/dennisguse/opentracks/content/sensor/SensorDataSet.java @@ -65,8 +65,8 @@ public final class SensorDataSet { } if (cyclingDistanceSpeed != null && cyclingDistanceSpeed.hasValue()) { - trackPoint.setSensorDistance(cyclingDistanceSpeed.getValue().distanceOverall); - trackPoint.setSpeed(cyclingDistanceSpeed.getValue().speed); + trackPoint.setSensorDistance(cyclingDistanceSpeed.getValue().getDistanceOverall()); + trackPoint.setSpeed(cyclingDistanceSpeed.getValue().getSpeed()); } if (cyclingPower != null && cyclingPower.hasValue()) { diff --git a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java index 65dc774ac..e67281f54 100644 --- a/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java +++ b/src/main/java/de/dennisguse/opentracks/fragments/StatisticsRecordingFragment.java @@ -258,7 +258,7 @@ public class StatisticsRecordingFragment extends Fragment { if (sensorDataSet != null && sensorDataSet.getCyclingDistanceSpeed() != null) { SensorDataCycling.DistanceSpeed data = sensorDataSet.getCyclingDistanceSpeed(); if (data.hasValue() && data.isRecent()) { - speed = data.getValue().speed; + speed = data.getValue().getSpeed(); } } diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java b/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java index 769d8679f..db36fcffc 100644 --- a/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/HandlerServer.java @@ -177,6 +177,11 @@ public class HandlerServer { this.clock = clock; } + @VisibleForTesting + public LocationHandler getLocationHandler() { + return locationHandler; + } + void sendGpsStatus(GpsStatusValue gpsStatusValue) { service.newGpsStatus(gpsStatusValue); } diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java b/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java index 1154ba99d..808999189 100644 --- a/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/LocationHandler.java @@ -9,6 +9,7 @@ import android.os.Bundle; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.VisibleForTesting; import java.time.Duration; @@ -18,7 +19,8 @@ import de.dennisguse.opentracks.content.data.TrackPoint; import de.dennisguse.opentracks.util.LocationUtils; import de.dennisguse.opentracks.util.PreferencesUtils; -class LocationHandler implements LocationListener, GpsStatus.GpsStatusListener { +@VisibleForTesting(otherwise = 3) +public class LocationHandler implements LocationListener, GpsStatus.GpsStatusListener { private final String TAG = LocationHandler.class.getSimpleName();