Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Monotonic clock#1966 #2036

Merged
merged 2 commits into from
Dec 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ public void setUp() throws TimeoutException {
contentProviderUtils.insertMarker(new Marker("Marker 2", "Marker 2 desc", "Marker 2 category", null, trackId, service.getLastStoredTrackPointWithLocation(), ""));

trackPointCreator.setClock("2020-02-02T02:02:18Z");
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet();
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(trackPointCreator);
service.endCurrentTrack();

trackPointCreator.setClock("2020-02-02T02:03:20Z");
Expand All @@ -172,7 +172,7 @@ public void setUp() throws TimeoutException {

sendLocation(trackPointCreator, "2020-02-02T02:03:50Z", 3, 16.001, 10, 27, 15, 10, 0f);

trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet();
trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(trackPointCreator);
trackPointCreator.setClock("2020-02-02T02:04:00Z");
service.endCurrentTrack();

Expand Down Expand Up @@ -550,22 +550,22 @@ private void mockSensorData(TrackPointCreator trackPointCreator, Float speed, Di

AggregatorCyclingPower cyclingPower = Mockito.mock(AggregatorCyclingPower.class);
Mockito.when(cyclingPower.hasValue()).thenReturn(true);
Mockito.when(cyclingPower.getValue()).thenReturn(Power.of(power));
Mockito.when(cyclingPower.getValue(Mockito.any())).thenReturn(Power.of(power));
sensorDataSet.add(cyclingPower);

AggregatorHeartRate agheartRate = Mockito.mock(AggregatorHeartRate.class);
Mockito.when(agheartRate.getValue()).thenReturn(HeartRate.of(heartRate));
sensorDataSet.add(agheartRate);
AggregatorHeartRate avgHeartRate = Mockito.mock(AggregatorHeartRate.class);
Mockito.when(avgHeartRate.getValue(Mockito.any())).thenReturn(HeartRate.of(heartRate));
sensorDataSet.add(avgHeartRate);

AggregatorCyclingCadence cyclingCadence = Mockito.mock(AggregatorCyclingCadence.class);
Mockito.when(cyclingCadence.hasValue()).thenReturn(true);
Mockito.when(cyclingCadence.getValue()).thenReturn(Cadence.of(cadence));
Mockito.when(cyclingCadence.getValue(Mockito.any())).thenReturn(Cadence.of(cadence));
sensorDataSet.add(cyclingCadence);

if (distance != null && speed != null) {
AggregatorCyclingDistanceSpeed distanceSpeed = Mockito.mock(AggregatorCyclingDistanceSpeed.class);
Mockito.when(distanceSpeed.hasValue()).thenReturn(true);
Mockito.when(distanceSpeed.getValue()).thenReturn(new AggregatorCyclingDistanceSpeed.Data(null, distance, Speed.of(speed)));
Mockito.when(distanceSpeed.getValue(Mockito.any())).thenReturn(new AggregatorCyclingDistanceSpeed.Data(null, distance, Speed.of(speed)));
sensorDataSet.add(distanceSpeed);
} else {
sensorDataSet.add(new AggregatorCyclingDistanceSpeed("", ""));
Expand All @@ -582,7 +582,7 @@ private void mockAltitudeChange(TrackPointCreator trackPointCreator, Float altit
if (altitudeGain != null) {
AggregatorBarometer barometer = Mockito.mock(AggregatorBarometer.class);
Mockito.when(barometer.hasValue()).thenReturn(true);
Mockito.when(barometer.getValue()).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
Mockito.when(barometer.getValue(Mockito.any())).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
sensorDataSet.add(barometer);
} else {
sensorDataSet.add(new AggregatorBarometer("test", null));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
import org.junit.Assert;
import org.junit.Test;

import java.time.Instant;

import de.dennisguse.opentracks.data.models.AtmosphericPressure;

public class AggregatorBarometerTest {

private static void addSensorValue(AggregatorBarometer aggregatorBarometer, float[] values) {
for (float f : values) {
aggregatorBarometer.add(new Raw<>(AtmosphericPressure.ofHPA(f)));
aggregatorBarometer.add(new Raw<>(Instant.MIN, AtmosphericPressure.ofHPA(f)));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;

import java.time.Instant;

import de.dennisguse.opentracks.data.models.Cadence;
import de.dennisguse.opentracks.data.models.Distance;
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
Expand All @@ -23,35 +25,35 @@ public void compute_cadence_1() {
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");

// when
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 2048)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 2048)));

// then
assertEquals(60, current.getValue().getRPM(), 0.01);
assertEquals(60, current.getValue(Instant.MIN).getRPM(), 0.01);
}

@Test
public void compute_cadence_2() {
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");

// when
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 6184)));
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 8016)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 6184)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 8016)));

// then
assertEquals(33.53, current.getValue().getRPM(), 0.01);
assertEquals(33.53, current.getValue(Instant.MIN).getRPM(), 0.01);
}

@Test
public void compute_cadence_sameCount() {
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");

// when
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 2048)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 2048)));

// then
assertEquals(Cadence.of(0), current.getValue());
assertEquals(Cadence.of(0), current.getValue(Instant.MIN));
}


Expand All @@ -60,8 +62,8 @@ public void compute_cadence_sameTime() {
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");

// when
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 1024)));

// then
assertFalse(current.hasValue()); //TODO Cadence should be 0?
Expand All @@ -72,11 +74,11 @@ public void compute_cadence_rollOverTime() {
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");

// when
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, UintUtils.UINT16_MAX - 1024)));
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 0)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(1, UintUtils.UINT16_MAX - 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(2, 0)));

// then
assertEquals(60, current.getValue().getRPM(), 0.01);
assertEquals(60, current.getValue(Instant.MIN).getRPM(), 0.01);
}

@Test
Expand All @@ -85,13 +87,13 @@ public void compute_cadence_rollOverCount() {
AggregatorCyclingCadence current = new AggregatorCyclingCadence("", "");

// when
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(UintUtils.UINT32_MAX - 1, 1024)));
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(0, 2048)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(UintUtils.UINT32_MAX - 1, 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingCadence.CrankData(0, 2048)));

// then
// TODO See #953
// assertEquals(60, current.getValue().getRPM(), 0.01);
assertNull(current.getValue());
assertNull(current.getValue(Instant.MIN));
}

@Test
Expand All @@ -100,12 +102,12 @@ public void compute_speed() {
current.setWheelCircumference(Distance.ofMM(2150));

// when
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(1, 6184)));
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(2, 8016)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(1, 6184)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(2, 8016)));

// then
assertEquals(2.15, current.getValue().distance().toM(), 0.01);
assertEquals(1.20, current.getValue().speed().toMPS(), 0.01);
assertEquals(2.15, current.getValue(Instant.MIN).distance().toM(), 0.01);
assertEquals(1.20, current.getValue(Instant.MIN).speed().toMPS(), 0.01);
}

@Test
Expand All @@ -115,14 +117,14 @@ public void compute_speed_rollOverCount() {
current.setWheelCircumference(Distance.ofMM(2000));

// when
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(UintUtils.UINT32_MAX - 1, 1024)));
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(0, 2048)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(UintUtils.UINT32_MAX - 1, 1024)));
current.add(new Raw<>(Instant.MIN, new BluetoothHandlerCyclingDistanceSpeed.WheelData(0, 2048)));


// then
// TODO See #953
// assertEquals(2, current.getValue().getDistance().toM(), 0.01);
// assertEquals(2, current.getValue().getSpeed().toMPS(), 0.01);
assertNull(current.getValue());
assertNull(current.getValue(Instant.MIN));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -304,11 +304,11 @@ public void testRecording_blesensor_only_no_distance() {
String sensor1 = "2020-02-02T02:02:03Z";
trackPointCreator.setClock(sensor1);

sensorManager.onChanged(new Raw<>(HeartRate.of(5))); //Should be ignored
sensorManager.onChanged(new Raw<>(sensor1, HeartRate.of(5))); //Should be ignored

String sensor3 = "2020-02-02T02:02:13Z";
trackPointCreator.setClock(sensor3);
sensorManager.onChanged(new Raw<>(HeartRate.of(7)));
sensorManager.onChanged(new Raw<>(sensor3, HeartRate.of(7)));

String stopTime = "2020-02-02T02:02:15Z";
trackPointCreator.setClock(stopTime);
Expand Down Expand Up @@ -646,12 +646,12 @@ public void testRecording_gpsAndSensor_gpsIdleMoving_sensorMoving() {
// when
String sensor1 = "2020-02-02T02:02:03Z";
trackPointCreator.setClock(sensor1);
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(0)))); //Should be ignored
sensorManager.onChanged(new Raw<>(sensor1, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(0)))); //Should be ignored

// when
String sensor2 = "2020-02-02T02:02:04Z";
trackPointCreator.setClock(sensor2);
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(2))));
sensorManager.onChanged(new Raw<>(sensor2, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(2))));

// when
String gps1 = "2020-02-02T02:02:05Z";
Expand All @@ -660,12 +660,12 @@ public void testRecording_gpsAndSensor_gpsIdleMoving_sensorMoving() {
// when
String sensor3 = "2020-02-02T02:02:06Z";
trackPointCreator.setClock(sensor3);
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(12))));
sensorManager.onChanged(new Raw<>(sensor3, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(12))));

// when
String sensor4 = "2020-02-02T02:02:07Z";
trackPointCreator.setClock(sensor4);
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(14)))); //Should be ignored
sensorManager.onChanged(new Raw<>(sensor4, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(14)))); //Should be ignored

// when
String gps2 = "2020-02-02T02:02:08Z";
Expand All @@ -674,7 +674,7 @@ public void testRecording_gpsAndSensor_gpsIdleMoving_sensorMoving() {
// when
String sensor5 = "2020-02-02T02:02:10Z";
trackPointCreator.setClock(sensor5);
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(16)))); //Should be ignored
sensorManager.onChanged(new Raw<>(sensor5, new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(16)))); //Should be ignored

// when
String gps3 = "2020-02-02T02:02:12Z";
Expand Down Expand Up @@ -730,7 +730,7 @@ public void testRecording_gpsAndSensor_gpsIdleMoving_sensorMoving() {
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
AggregatorBarometer barometer = Mockito.mock(AggregatorBarometer.class);
Mockito.when(barometer.hasValue()).thenReturn(true);
Mockito.when(barometer.getValue()).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));
Mockito.when(barometer.getValue(Mockito.any())).thenReturn(new AltitudeGainLoss(altitudeGain, altitudeGain));

trackPointCreator.getSensorManager().sensorDataSet.barometer = barometer;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void handlePayload(SensorManager.SensorDataChangedObserver observer, Serv
AtmosphericPressure value = parseEnvironmentalSensing(characteristic);
if (value == null) return;

observer.onChange(new Raw<>(value));
observer.onChange(new Raw<>(observer.getNow(), value));
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void handlePayload(SensorManager.SensorDataChangedObserver observer, Serv
if (serviceMeasurementUUID.equals(BluetoothHandlerManagerCyclingPower.CYCLING_POWER)) {
BluetoothHandlerManagerCyclingPower.Data data = BluetoothHandlerManagerCyclingPower.parseCyclingPower(characteristic);
if (data != null && data.crank() != null) {
observer.onChange(new Raw<>(data.crank()));
observer.onChange(new Raw<>(observer.getNow(), data.crank()));
}
return;
}
Expand All @@ -42,7 +42,7 @@ public void handlePayload(SensorManager.SensorDataChangedObserver observer, Serv
Pair<BluetoothHandlerCyclingDistanceSpeed.WheelData, CrankData> data = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel(address, sensorName, characteristic);

if (data != null && data.second != null) {
observer.onChange(new Raw<>(data.second));
observer.onChange(new Raw<>(observer.getNow(), data.second));
}
return;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public AggregatorCyclingDistanceSpeed createEmptySensorData(String address, Stri
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
Pair<WheelData, BluetoothHandlerCyclingCadence.CrankData> data = parseCyclingCrankAndWheel(address, sensorName, characteristic);
if (data.first != null) {
observer.onChange(new Raw<>(data.first));
observer.onChange(new Raw<>(observer.getNow(), data.first));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public void handlePayload(SensorManager.SensorDataChangedObserver observer, @Non
Data cyclingPower = parseCyclingPower(characteristic);

if (cyclingPower != null) {
observer.onChange(new Raw<>(cyclingPower));
observer.onChange(new Raw<>(observer.getNow(), cyclingPower));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public void handlePayload(SensorManager.SensorDataChangedObserver observer, @Non
HeartRate heartRate = parseHeartRate(characteristic);

if (heartRate != null) {
observer.onChange(new Raw<>(heartRate));
observer.onChange(new Raw<>(observer.getNow(), heartRate));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public AggregatorRunning createEmptySensorData(String address, String name) {
@Override
public void handlePayload(SensorManager.SensorDataChangedObserver observer, @NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
Data data = parseRunningSpeedAndCadence(sensorName, characteristic);
observer.onChange(new Raw<>(data));
observer.onChange(new Raw<>(observer.getNow(), data));
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import java.time.Instant;

import de.dennisguse.opentracks.data.models.TrackPoint;
import de.dennisguse.opentracks.sensors.sensorData.Aggregator;
import de.dennisguse.opentracks.sensors.sensorData.Raw;
Expand All @@ -21,7 +23,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange

//TODO Should be final and not be visible for testing
@VisibleForTesting
public SensorDataSet sensorDataSet = new SensorDataSet();
public SensorDataSet sensorDataSet;

private final TrackPointCreator observer;

Expand All @@ -47,6 +49,11 @@ public void onDisconnect(Aggregator<?, ?> aggregator) {
public void onRemove(Aggregator<?, ?> aggregator) {
sensorDataSet.remove(aggregator);
}

@Override
public Instant getNow() {
return observer.createNow();
}
};

private BluetoothRemoteSensorManager bluetoothSensorManager;
Expand All @@ -57,6 +64,7 @@ public void onRemove(Aggregator<?, ?> aggregator) {

public SensorManager(TrackPointCreator observer) {
this.observer = observer;
this.sensorDataSet = new SensorDataSet(observer);
}

public void start(Context context, Handler handler) {
Expand Down Expand Up @@ -138,5 +146,7 @@ public interface SensorDataChangedObserver {
void onDisconnect(Aggregator<?, ?> sensorData);

void onRemove(Aggregator<?, ?> sensorData);

Instant getNow();
}
}
Loading
Loading