forked from upstream-mirrors/OpenTracks
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae4d2da262 |
+3
-3
@@ -6,7 +6,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:9.0.1'
|
||||
classpath 'com.android.tools.build:gradle:9.0.0'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,8 +47,8 @@ android {
|
||||
|
||||
defaultConfig {
|
||||
applicationId 'de.dennisguse.opentracks'
|
||||
versionCode 6603
|
||||
versionName "v4.26.0"
|
||||
versionCode 6564
|
||||
versionName "v4.25.2"
|
||||
|
||||
buildConfigField "String", "VERSION_NAME_FULL", "\"${getVersionName()}\""
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
v4.26.0: OpenTracks
|
||||
|
||||
Changes:
|
||||
- GPS is optional: configurable in the settings
|
||||
- BLE sensor address/name is only shown after successful connection
|
||||
|
||||
Bugfix:
|
||||
- Altitude is now shown again in EGM2008 (introduced in v4.25.0)
|
||||
- Altitude and speed were shown as 0.0 briefly when data was stored
|
||||
|
||||
Developer:
|
||||
- Refactored sensor subsystem
|
||||
+3
-3
@@ -89,12 +89,12 @@ import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
public class ExportImportTest {
|
||||
|
||||
@Rule
|
||||
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS);
|
||||
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(50, TimeUnit.SECONDS); //TODO 5s
|
||||
|
||||
@Rule
|
||||
public GrantPermissionRule mGrantPermissionRule = TestUtil.createGrantPermissionRule();
|
||||
|
||||
//For csv_export_only() as the timezone is hardcoded in the expectation.
|
||||
//For csv_export_only() as we the timezone is hardcoded in the expectation.
|
||||
@Rule
|
||||
public TimezoneRule timezoneRule = new TimezoneRule(TimeZone.getTimeZone("Europe/Berlin"));
|
||||
|
||||
@@ -747,7 +747,7 @@ public class ExportImportTest {
|
||||
sensorManager.getAltitudeChangeHandler().setAggregator(aggregatorBarometer);
|
||||
}
|
||||
|
||||
public static void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) {
|
||||
private void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) {
|
||||
Location location = new Location("mock");
|
||||
location.setLatitude(latitude);
|
||||
location.setLongitude(longitude);
|
||||
|
||||
@@ -26,7 +26,6 @@ public class TrackPointAssert {
|
||||
|
||||
Assert.assertEquals("has altitude", expected.position().hasAltitude(), actual.position().hasAltitude());
|
||||
if (expected.position().hasAltitude()) {
|
||||
Assert.assertEquals("altitude", expected.position().altitude().getClass(), actual.position().altitude().getClass());
|
||||
Assert.assertEquals("altitude", expected.position().altitude().toM(), actual.position().altitude().toM(), delta);
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ public class TrackRecordingServiceStateMachineTest {
|
||||
// then
|
||||
assertEquals(TrackRecordingService.STATUS_DEFAULT, service.getRecordingStatusObservable().getValue());
|
||||
assertEquals(RecordingData.NOT_RECORDING, service.getRecordingDataObservable().getValue());
|
||||
assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue());
|
||||
// assertEquals(GpsStatusValue.GPS_NONE, service.getGpsStatusObservable().getValue()); TODO BUG: GPS can only be stopped if a service is recording.
|
||||
}
|
||||
|
||||
@MediumTest
|
||||
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
package de.dennisguse.opentracks.services;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static de.dennisguse.opentracks.services.TrackRecordingService.RECORDING_DATA_UPDATE_INTERVAL;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.core.location.LocationManagerCompat;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.rule.GrantPermissionRule;
|
||||
import androidx.test.rule.ServiceTestRule;
|
||||
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import de.dennisguse.opentracks.TestUtil;
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.importer.ExportImportTest;
|
||||
import de.dennisguse.opentracks.io.file.importer.TrackPointAssert;
|
||||
import de.dennisguse.opentracks.sensors.driver.GpsInternal;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TrackRecordingServiceUITest {
|
||||
|
||||
@Rule
|
||||
public final ServiceTestRule mServiceRule = ServiceTestRule.withTimeout(5, TimeUnit.SECONDS);
|
||||
|
||||
@Rule
|
||||
public GrantPermissionRule mGrantPermissionRule = TestUtil.createGrantPermissionRule();
|
||||
|
||||
private static final Context context = ApplicationProvider.getApplicationContext();
|
||||
|
||||
@BeforeClass
|
||||
public static void preSetUp() {
|
||||
// Prepare looper for Android's message queue
|
||||
if (Looper.myLooper() == null) Looper.prepare();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getDataForUI_gps() throws TimeoutException, InterruptedException {
|
||||
TrackRecordingService service = ((TrackRecordingService.Binder) mServiceRule.bindService(new Intent(context, TrackRecordingService.class)))
|
||||
.getService();
|
||||
RecordingData recordingData;
|
||||
|
||||
// given
|
||||
TrackPointCreator trackPointCreator = service.getTrackPointCreator();
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:02:02Z");
|
||||
|
||||
// when
|
||||
service.startNewTrack();
|
||||
//We do not want the real GPS to interfere.
|
||||
GpsInternal gpsInternal = (GpsInternal)trackPointCreator.getSensorManager().getGpsHandler().driver;
|
||||
LocationManagerCompat.removeUpdates(gpsInternal.locationManager, gpsInternal.locationListenerCompat);
|
||||
Thread.sleep(RECORDING_DATA_UPDATE_INTERVAL.toMillis());
|
||||
|
||||
// then
|
||||
assertEquals(new TrackPoint(
|
||||
null,
|
||||
TrackPoint.Type.TRACKPOINT,
|
||||
Position.of( Instant.parse("2020-02-02T02:02:02Z")),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
),
|
||||
service.getRecordingDataObservable().getValue().latestTrackPoint());
|
||||
|
||||
|
||||
// when
|
||||
// In this step, the data is saved (and Aggregator.resetAggregated called), but data should still be shown in the UI.
|
||||
trackPointCreator.setClock("2020-02-02T02:02:03Z");
|
||||
ExportImportTest.sendLocation(trackPointCreator, "2020-02-02T02:02:03Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 1f);
|
||||
|
||||
// then
|
||||
Thread.sleep(RECORDING_DATA_UPDATE_INTERVAL.toMillis());
|
||||
recordingData = service.getRecordingDataObservable().getValue();
|
||||
new TrackPointAssert().assertEquals(new TrackPoint(
|
||||
null,
|
||||
TrackPoint.Type.TRACKPOINT,
|
||||
new Position(
|
||||
Instant.parse("2020-02-02T02:02:03Z"),
|
||||
3.1234567, 14.0014567, null,
|
||||
Altitude.EGM2008.of(1013.05), null,
|
||||
null,
|
||||
Speed.of(15)),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(1, 1)
|
||||
),
|
||||
recordingData.latestTrackPoint());
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
|
||||
|
||||
private static final int DATABASE_VERSION = 42;
|
||||
private static final int DATABASE_VERSION = 43;
|
||||
|
||||
private final Context context;
|
||||
|
||||
@@ -86,6 +86,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 40 -> upgradeFrom39to40(db);
|
||||
case 41 -> upgradeFrom40to41(db);
|
||||
case 42 -> upgradeFrom41to42(db);
|
||||
case 43 -> upgradeFrom42to43(db);
|
||||
default -> throw new RuntimeException("Not implemented: upgrade to " + toVersion);
|
||||
}
|
||||
}
|
||||
@@ -115,6 +116,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 39 -> downgradeFrom40to39(db);
|
||||
case 40 -> downgradeFrom41to40(db);
|
||||
case 41 -> downgradeFrom42to41(db);
|
||||
case 42 -> downgradeFrom43to42(db);
|
||||
default -> throw new RuntimeException("Not implemented: downgrade to " + toVersion);
|
||||
}
|
||||
}
|
||||
@@ -794,4 +796,18 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
private void upgradeFrom42to43(SQLiteDatabase db) {
|
||||
db.beginTransaction();
|
||||
|
||||
db.execSQL("UPDATE trackpoints SET heartrate = null WHERE heartrate = 0.0");
|
||||
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
private void downgradeFrom43to42(SQLiteDatabase db) {
|
||||
// Downgrade not possible: invalid data replaced with null.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,10 @@ public record HeartRate(float value) {
|
||||
@Nullable
|
||||
public static HeartRate ofOrNull(Float value) {
|
||||
if (value == null) return null;
|
||||
return new HeartRate(value);
|
||||
HeartRate rate = of(value);
|
||||
if (rate.isValid()) return rate;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public float getBPM() {
|
||||
|
||||
@@ -8,7 +8,7 @@ import androidx.annotation.Nullable;
|
||||
import java.time.Instant;
|
||||
|
||||
public record Position(
|
||||
@Nullable Instant time, //TODO It may be a good idea to move time out of Position
|
||||
@Nullable Instant time,
|
||||
@Nullable Double latitude,
|
||||
@Nullable Double longitude,
|
||||
@Nullable Distance horizontalAccuracy,
|
||||
@@ -17,6 +17,10 @@ public record Position(
|
||||
@Nullable Float bearing,
|
||||
@Nullable Speed speed
|
||||
) {
|
||||
@Deprecated
|
||||
public static Position empty() {
|
||||
return of(null);
|
||||
}
|
||||
|
||||
public static Position of(@NonNull Instant time) {
|
||||
return new Position(
|
||||
|
||||
@@ -119,6 +119,19 @@ public record TrackPoint(
|
||||
);
|
||||
}
|
||||
|
||||
public TrackPoint removeHeartRate() {
|
||||
return new TrackPoint(
|
||||
id,
|
||||
type,
|
||||
position,
|
||||
sensorDistance,
|
||||
null,
|
||||
cadence,
|
||||
power,
|
||||
altitudeGainLoss
|
||||
);
|
||||
}
|
||||
|
||||
public TrackPoint with(Position newPosition) {
|
||||
return new TrackPoint(
|
||||
id,
|
||||
|
||||
@@ -167,11 +167,8 @@ public class ExportActivity extends AbstractActivity {
|
||||
new Thread(() -> {
|
||||
directoryFiles = ExportUtils.getAllFiles(ExportActivity.this, documentFile.getUri());
|
||||
runOnUiThread(() -> {
|
||||
if (createExportTasks(allInOneFile)) {
|
||||
nextExport(null);
|
||||
} else {
|
||||
onExportEnded();
|
||||
}
|
||||
createExportTasks(allInOneFile);
|
||||
nextExport(null);
|
||||
});
|
||||
}).start();
|
||||
} else {
|
||||
@@ -220,12 +217,8 @@ public class ExportActivity extends AbstractActivity {
|
||||
exportTasks.clear();
|
||||
}
|
||||
|
||||
private boolean createExportTasks(boolean allInOneFile) {
|
||||
private void createExportTasks(boolean allInOneFile) {
|
||||
List<Track> tracks = contentProviderUtils.getTracks();
|
||||
if (tracks.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
exportTasks = new ArrayList<>();
|
||||
if (allInOneFile) {
|
||||
String filename = "OpenTracks-Backup";
|
||||
@@ -234,7 +227,6 @@ public class ExportActivity extends AbstractActivity {
|
||||
exportTasks.addAll(tracks.stream().map(it -> new ExportTask(null, trackFileFormat, List.of(it.id()))).toList());
|
||||
}
|
||||
trackExportTotalCount = exportTasks.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -399,7 +391,7 @@ public class ExportActivity extends AbstractActivity {
|
||||
|
||||
/**
|
||||
* Try to resolve the conflict if user gave the info needed.
|
||||
* Otherwise, shows the buttons and views needed to gives the user the possibility of take a decision.
|
||||
* Otherwise shows the buttons and views needed to gives the user the possibility of take a decision.
|
||||
*
|
||||
* @return true if it could resolve the conflict or false otherwise.
|
||||
*/
|
||||
|
||||
@@ -356,7 +356,7 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
HeartRate parsedHeartRate = null;
|
||||
if (heartrate != null) {
|
||||
try {
|
||||
parsedHeartRate = HeartRate.of(Float.parseFloat(heartrate));
|
||||
parsedHeartRate = HeartRate.ofOrNull(Float.parseFloat(heartrate));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse heart rate: %s", heartrate)), e);
|
||||
}
|
||||
|
||||
@@ -190,6 +190,15 @@ public class TrackImporter {
|
||||
}
|
||||
trackPoints.set(i, newCurrent);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (int i = 0; i < trackPoints.size(); i++) {
|
||||
TrackPoint current = trackPoints.get(i);
|
||||
if (!current.heartRate().isValid()) {
|
||||
current = current.removeHeartRate();
|
||||
trackPoints.set(i, current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingCadence;
|
||||
@@ -125,7 +126,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
gpsHandler.resetAggregated();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public GpsHandler getGpsHandler() {
|
||||
return gpsHandler;
|
||||
}
|
||||
@@ -185,6 +185,17 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
return handler;
|
||||
}
|
||||
|
||||
private SensorData<HeartRate> getHeartRate(Instant now) {
|
||||
SensorData<HeartRate> value = heartRateHandler.getSensorData(now);
|
||||
if (value != null) {
|
||||
|
||||
//TODO Move this check into HeartRateHandler
|
||||
if (value.data().isValid()) return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SensorData<Cadence> getCadence(Instant now) {
|
||||
{
|
||||
SensorData<Cadence> value = cyclingCadenceHandler.getSensorData(now);
|
||||
@@ -239,19 +250,16 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
}
|
||||
|
||||
public SensorDataSet getSensorDataSet(Instant now) {
|
||||
//We always need a Position with now
|
||||
SensorData<Position> gpsSensorData = gpsHandler.getSensorData(now);
|
||||
if (gpsSensorData != null && gpsSensorData.data() != null) {
|
||||
gpsSensorData = new SensorData<>(gpsSensorData.data().with(now), gpsSensorData.sensorNameOrAddress());
|
||||
} else {
|
||||
gpsSensorData = new SensorData<>(Position.of(now), "");
|
||||
}
|
||||
|
||||
var a = temperatureHandler.getSensorData(now);
|
||||
var b = altitudeChangeHandler.getSensorData(now);
|
||||
|
||||
return new SensorDataSet(
|
||||
gpsSensorData,
|
||||
gpsSensorData != null ? gpsSensorData : new SensorData<>(Position.of(now), ""), //We always need a Position(now)
|
||||
getSpeed(now),
|
||||
getDistance(now),
|
||||
heartRateHandler.getSensorData(now),
|
||||
getHeartRate(now),
|
||||
temperatureHandler.getSensorData(now),
|
||||
getCadence(now),
|
||||
cyclingPowerHandler.getSensorData(now),
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package de.dennisguse.opentracks.sensors.driver;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -13,6 +14,8 @@ import de.dennisguse.opentracks.sensors.ServiceMeasurementUUID;
|
||||
|
||||
public class HeartRateBluetooth implements BluetoothDriver.BluetoothParser<HeartRate> {
|
||||
|
||||
private static final String TAG = BluetoothHandlerManagerHeartRate.class.getSimpleName();
|
||||
|
||||
public static final ServiceMeasurementUUID HEARTRATE = new ServiceMeasurementUUID(
|
||||
new UUID(0x180D00001000L, 0x800000805f9b34fbL),
|
||||
new UUID(0x2A3700001000L, 0x800000805f9b34fbL)
|
||||
@@ -35,7 +38,16 @@ public class HeartRateBluetooth implements BluetoothDriver.BluetoothParser<Heart
|
||||
|
||||
@Override
|
||||
public HeartRate parsePayload(@NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, BluetoothGattCharacteristic characteristic) {
|
||||
return parseHeartRate(characteristic);
|
||||
HeartRate heartRate = parseHeartRate(characteristic);
|
||||
|
||||
if (heartRate == null) return null;
|
||||
|
||||
if (heartRate.value() == 0.0) {
|
||||
Log.d(TAG, "Invalid heartrate received. Ignoring.");
|
||||
return null;
|
||||
}
|
||||
|
||||
return heartRate;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
|
||||
@@ -34,7 +34,7 @@ public abstract class Aggregator<InputType, OutputType> {
|
||||
previous = next;
|
||||
}
|
||||
|
||||
protected abstract void computeValue(@NonNull Raw<InputType> current);
|
||||
protected abstract void computeValue(Raw<InputType> current);
|
||||
|
||||
/**
|
||||
* @return did we process data from a sensor.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Altitude;
|
||||
import de.dennisguse.opentracks.data.models.AltitudeGainLoss;
|
||||
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
|
||||
import de.dennisguse.opentracks.sensors.PressureSensorUtils;
|
||||
@@ -15,7 +14,7 @@ public class AggregatorBarometer extends Aggregator<AtmosphericPressure, Altitud
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void computeValue(@NonNull Raw<AtmosphericPressure> current) {
|
||||
protected void computeValue(Raw<AtmosphericPressure> current) {
|
||||
if (previous == null) {
|
||||
lastAcceptedSensorValue = current.value();
|
||||
output = new AltitudeGainLoss(0f, 0f);
|
||||
@@ -41,4 +40,6 @@ public class AggregatorBarometer extends Aggregator<AtmosphericPressure, Altitud
|
||||
public void resetAggregated() {
|
||||
output = null;
|
||||
}
|
||||
|
||||
public record Data(Altitude gain, Altitude loss) {}
|
||||
}
|
||||
|
||||
+1
-3
@@ -2,8 +2,6 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
@@ -19,7 +17,7 @@ public class AggregatorCyclingCadence extends Aggregator<CyclingCadenceBluetooth
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void computeValue(@NonNull Raw<CyclingCadenceBluetooth.CrankData> current) {
|
||||
protected void computeValue(Raw<CyclingCadenceBluetooth.CrankData> current) {
|
||||
if (previous == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-3
@@ -2,8 +2,6 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
@@ -22,7 +20,7 @@ public class AggregatorCyclingDistanceSpeed extends Aggregator<CyclingDistanceSp
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void computeValue(@NonNull Raw<CyclingDistanceSpeedBluetooth.WheelData> current) {
|
||||
protected void computeValue(Raw<CyclingDistanceSpeedBluetooth.WheelData> current) {
|
||||
if (previous == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-3
@@ -1,7 +1,5 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.sensors.driver.CyclingPowerBluetooth;
|
||||
|
||||
@@ -12,7 +10,7 @@ public class AggregatorCyclingPower extends Aggregator<CyclingPowerBluetooth.Dat
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeValue(@NonNull Raw<CyclingPowerBluetooth.Data> current) {
|
||||
public void computeValue(Raw<CyclingPowerBluetooth.Data> current) {
|
||||
this.output = current.value().power();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import android.location.Location;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
|
||||
public class AggregatorGPS extends Aggregator<Location, Position> {
|
||||
@@ -13,7 +15,7 @@ public class AggregatorGPS extends Aggregator<Location, Position> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void computeValue(@NonNull Raw<Location> current) {
|
||||
protected void computeValue(Raw<Location> current) {
|
||||
output = Position.of(current.value(), current.time());
|
||||
}
|
||||
|
||||
@@ -22,7 +24,17 @@ public class AggregatorGPS extends Aggregator<Location, Position> {
|
||||
/*
|
||||
* GPS data is not an aggregated value, but for now we want to ensure to only save the data once.
|
||||
* The data is too large to save it more often than needed (i.e., duplicated values).
|
||||
* TODO: this behavior can be changed if TrackRecordingManager.insertTrackPoint() would strip GPS data if it was already saved. This would simplify TrackPointCreator.createCurrentTrackPoint()
|
||||
*/
|
||||
resetOutdated();
|
||||
output = null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Position getAggregatedValue(Instant now) {
|
||||
Position value = super.getAggregatedValue(now);
|
||||
if (value == null) value = Position.empty();
|
||||
|
||||
return value.with(now);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
|
||||
public class AggregatorHeartRate extends Aggregator<HeartRate, HeartRate> {
|
||||
@@ -11,9 +9,7 @@ public class AggregatorHeartRate extends Aggregator<HeartRate, HeartRate> {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void computeValue(@NonNull Raw<HeartRate> current) {
|
||||
if (current.value().isValid()) {
|
||||
this.output = current.value();
|
||||
}
|
||||
protected void computeValue(Raw<HeartRate> current) {
|
||||
this.output = current.value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public final class AggregatorRunning extends Aggregator<RunningSpeedAndCadenceBl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeValue(@NonNull Raw<RunningSpeedAndCadenceBluetooth.Data> current) {
|
||||
public void computeValue(Raw<RunningSpeedAndCadenceBluetooth.Data> current) {
|
||||
if (previous == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
+1
-3
@@ -1,7 +1,5 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
@@ -12,7 +10,7 @@ public class AggregatorTemperature extends Aggregator<Temperature, Temperature>
|
||||
super(sensorAddress, sensorName);
|
||||
}
|
||||
|
||||
protected void computeValue(@NonNull Raw<Temperature> current) {
|
||||
protected void computeValue(Raw<Temperature> current) {
|
||||
this.output = current.value();
|
||||
}
|
||||
|
||||
|
||||
@@ -10,10 +10,6 @@ import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
*/
|
||||
public record RecordingData(
|
||||
Track track,
|
||||
/*
|
||||
* The current view on the SensorData.
|
||||
* May contain data from previous measurements that are not present in SensorDataSet.
|
||||
*/
|
||||
TrackPoint latestTrackPoint,
|
||||
SensorDataSet sensorDataSet,
|
||||
Statistics currentSegment) {
|
||||
|
||||
@@ -131,10 +131,10 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
|
||||
|
||||
RecordingData getDataForUI() {
|
||||
Pair<TrackPoint, SensorDataSet> current = trackPointCreator.createCurrentTrackPoint(lastTrackPointUIWithSpeed, lastTrackPointUIWithAltitude, lastStoredTrackPointWithLocation);
|
||||
TrackPoint trackPoint = current.first;
|
||||
TrackStatisticsUpdater tmpTrackStatisticsUpdater = new TrackStatisticsUpdater(trackStatisticsUpdater, trackPoint);
|
||||
|
||||
TrackPoint TrackPointWithEGM2008 = ALTITUDE_CORRECTION_MANAGER.correctAltitude(context, trackPoint);
|
||||
TrackStatisticsUpdater tmpTrackStatisticsUpdater = new TrackStatisticsUpdater(trackStatisticsUpdater, current.first);
|
||||
|
||||
ALTITUDE_CORRECTION_MANAGER.correctAltitude(context, current.first);
|
||||
|
||||
Track track = contentProviderUtils.getTrack(trackId); //Get copy TODO: Avoid re-loading data from DB
|
||||
if (track == null) {
|
||||
@@ -145,7 +145,7 @@ public class TrackRecordingManager implements SharedPreferences.OnSharedPreferen
|
||||
TrackBuilder trackBuilder = new TrackBuilder(track);
|
||||
trackBuilder.setStatistics(tmpTrackStatisticsUpdater.getTrackStatistics());
|
||||
|
||||
return new RecordingData(trackBuilder.getTrack(), TrackPointWithEGM2008, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
|
||||
return new RecordingData(trackBuilder.getTrack(), current.first, current.second, tmpTrackStatisticsUpdater.getCurrentSegment());
|
||||
}
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
|
||||
@@ -48,8 +48,7 @@ public class TrackRecordingService extends Service implements TrackPointCreator.
|
||||
|
||||
private static final String TAG = TrackRecordingService.class.getSimpleName();
|
||||
|
||||
@VisibleForTesting
|
||||
public static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
||||
private static final Duration RECORDING_DATA_UPDATE_INTERVAL = Duration.ofSeconds(1);
|
||||
|
||||
public static final RecordingStatus STATUS_DEFAULT = RecordingStatus.notRecording();
|
||||
public static final GpsStatusValue STATUS_GPS_DEFAULT = GpsStatusValue.GPS_NONE;
|
||||
|
||||
@@ -102,10 +102,10 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
|
||||
}
|
||||
|
||||
if (lastTrackPointUISpeed != null)
|
||||
position = position.with(lastTrackPointUISpeed.position().speed());
|
||||
position.with(lastTrackPointUISpeed.position().speed());
|
||||
|
||||
if (lastTrackPointUIAltitude != null)
|
||||
position = position.with(lastTrackPointUIAltitude.position().altitude());
|
||||
position.with(lastTrackPointUIAltitude.position().altitude());
|
||||
|
||||
TrackPoint currentTrackPoint = new TrackPoint(
|
||||
null,
|
||||
|
||||
+1
-2
@@ -5,7 +5,6 @@ import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -23,7 +22,7 @@ public class RecordingLayoutIO {
|
||||
public static List<RecordingLayout> fromCsv(@NonNull String csv, @NonNull Resources resources) {
|
||||
return CsvLayoutUtils.getCsvLines(csv).stream()
|
||||
.map(line -> RecordingLayoutIO.fromCsvLine(line, resources))
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
.toList();
|
||||
}
|
||||
|
||||
public static RecordingLayout fromCsvLine(@NonNull String csvLine, @NonNull Resources resources) {
|
||||
|
||||
Reference in New Issue
Block a user