mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-09-30 16:52:21 +02:00
Cleanup: SensorDataAggregator inlined into SensorManager.
Preparation for refactoring.
This commit is contained in:
+14
-13
@@ -67,6 +67,7 @@ import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.TrackFileFormat;
|
||||
import de.dennisguse.opentracks.io.file.exporter.TrackExporter;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.SensorManager;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Aggregator;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorBarometer;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingCadence;
|
||||
@@ -75,7 +76,6 @@ import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorHeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorTemperature;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataAggregator;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
|
||||
@@ -197,7 +197,7 @@ public class ExportImportTest {
|
||||
));
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:02:18Z");
|
||||
trackPointCreator.getSensorManager().sensorDataAggregator = new SensorDataAggregator();
|
||||
trackPointCreator.getSensorManager().clear();
|
||||
service.endCurrentTrack();
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:03:20Z");
|
||||
@@ -212,7 +212,7 @@ public class ExportImportTest {
|
||||
|
||||
sendLocation(trackPointCreator, "2020-02-02T02:03:50Z", 3.1234567, 16.001, 10, 27, 15, 999.123, 0f);
|
||||
|
||||
trackPointCreator.getSensorManager().sensorDataAggregator = new SensorDataAggregator();
|
||||
trackPointCreator.getSensorManager().clear();
|
||||
trackPointCreator.setClock("2020-02-02T02:04:00Z");
|
||||
service.endCurrentTrack();
|
||||
|
||||
@@ -661,16 +661,16 @@ public class ExportImportTest {
|
||||
}
|
||||
|
||||
private void mockSensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power, Float altitudeGain, float temperature) {
|
||||
SensorDataAggregator sensorDataAggregator = trackPointCreator.getSensorManager().sensorDataAggregator;
|
||||
SensorManager sensorManager = trackPointCreator.getSensorManager();
|
||||
|
||||
AggregatorCyclingPower cyclingPower = new AggregatorCyclingPower("", "");
|
||||
cyclingPower.add(new Raw<>(trackPointCreator.createNow(), new BluetoothHandlerCyclingPower.Data(Power.of(power), null)));
|
||||
sensorDataAggregator.add(cyclingPower);
|
||||
sensorManager.add(cyclingPower);
|
||||
|
||||
|
||||
AggregatorHeartRate avgHeartRate = new AggregatorHeartRate("", "");
|
||||
avgHeartRate.add(new Raw<>(trackPointCreator.createNow(), HeartRate.of(heartRate)));
|
||||
sensorDataAggregator.add(avgHeartRate);
|
||||
sensorManager.add(avgHeartRate);
|
||||
|
||||
AggregatorCyclingCadence cyclingCadence = new AggregatorCyclingCadence("", "") {
|
||||
@NonNull
|
||||
@@ -684,7 +684,7 @@ public class ExportImportTest {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
sensorDataAggregator.add(cyclingCadence);
|
||||
sensorManager.add(cyclingCadence);
|
||||
|
||||
if (distance != null && speed != null) {
|
||||
AggregatorCyclingDistanceSpeed aggregatorCyclingDistanceSpeed = new AggregatorCyclingDistanceSpeed("", "") {
|
||||
@@ -699,14 +699,14 @@ public class ExportImportTest {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
sensorDataAggregator.add(aggregatorCyclingDistanceSpeed);
|
||||
sensorManager.add(aggregatorCyclingDistanceSpeed);
|
||||
} else {
|
||||
sensorDataAggregator.add(new AggregatorCyclingDistanceSpeed("", ""));
|
||||
sensorManager.add(new AggregatorCyclingDistanceSpeed("", ""));
|
||||
}
|
||||
|
||||
mockAltitudeChange(trackPointCreator, altitudeGain);
|
||||
|
||||
sensorDataAggregator.add(new AggregatorTemperature("", "'") {
|
||||
sensorManager.add(new AggregatorTemperature("", "'") {
|
||||
@NonNull
|
||||
@Override
|
||||
public Temperature getAggregatedValue(Instant now) {
|
||||
@@ -723,10 +723,11 @@ public class ExportImportTest {
|
||||
}
|
||||
|
||||
private void mockAltitudeChange(TrackPointCreator trackPointCreator, Float altitudeGain) {
|
||||
SensorDataAggregator sensorDataAggregator = trackPointCreator.getSensorManager().sensorDataAggregator;
|
||||
SensorManager sensorManager = trackPointCreator.getSensorManager();
|
||||
sensorManager.reset();
|
||||
|
||||
if (altitudeGain == null) {
|
||||
sensorDataAggregator.add(new AggregatorBarometer("test", null));
|
||||
sensorManager.add(new AggregatorBarometer("test", null));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -742,7 +743,7 @@ public class ExportImportTest {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
sensorDataAggregator.add(aggregatorBarometer);
|
||||
sensorManager.add(aggregatorBarometer);
|
||||
}
|
||||
|
||||
private void sendLocation(TrackPointCreator trackPointCreator, String time, double latitude, double longitude, float accuracy, float verticalAccuracy, float speed, double altitude, Float altitudeGain) {
|
||||
|
||||
+4
-4
@@ -339,7 +339,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
mockAltitudeChange(trackPointCreator, 0);
|
||||
|
||||
SensorManager sensorManager = trackPointCreator.getSensorManager();
|
||||
sensorManager.sensorDataAggregator.add(new AggregatorHeartRate("", ""));
|
||||
sensorManager.add(new AggregatorHeartRate("", ""));
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(sensor1);
|
||||
@@ -809,8 +809,8 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
|
||||
SensorManager sensorManager = trackPointCreator.getSensorManager();
|
||||
sensorManager.sensorDataAggregator.add(new AggregatorRunning("", ""));
|
||||
sensorManager.sensorDataAggregator.barometer = null;
|
||||
sensorManager.add(new AggregatorRunning("", ""));
|
||||
sensorManager.barometer = null;
|
||||
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
@@ -962,7 +962,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
}
|
||||
|
||||
private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) {
|
||||
trackPointCreator.getSensorManager().sensorDataAggregator.barometer = new AggregatorBarometer("", "") {
|
||||
trackPointCreator.getSensorManager().barometer = new AggregatorBarometer("", "") {
|
||||
@Override
|
||||
public boolean hasReceivedData() {
|
||||
return true;
|
||||
|
||||
@@ -6,26 +6,39 @@ import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
|
||||
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.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Aggregator;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorBarometer;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorGPS;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorHeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorRunning;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorTemperature;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataAggregator;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorData;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
import de.dennisguse.opentracks.util.SystemUtils;
|
||||
|
||||
public class SensorManager implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
||||
private static final String TAG = SensorManager.class.getSimpleName();
|
||||
|
||||
//TODO Should be final and not be visible for testing
|
||||
@VisibleForTesting
|
||||
public SensorDataAggregator sensorDataAggregator;
|
||||
|
||||
private PowerManager.WakeLock wakeLock;
|
||||
|
||||
private final TrackPointCreator observer;
|
||||
@@ -34,23 +47,23 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
|
||||
@Override
|
||||
public void onConnect(Aggregator<?, ?> aggregator) {
|
||||
sensorDataAggregator.add(aggregator);
|
||||
add(aggregator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChange(Raw<?> data) {
|
||||
sensorDataAggregator.update(data);
|
||||
update(data);
|
||||
observer.onChange();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect(Aggregator<?, ?> aggregator) {
|
||||
sensorDataAggregator.add(aggregator);
|
||||
add(aggregator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRemove(Aggregator<?, ?> aggregator) {
|
||||
sensorDataAggregator.remove(aggregator);
|
||||
remove(aggregator);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -67,7 +80,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
|
||||
public SensorManager(TrackPointCreator observer) {
|
||||
this.observer = observer;
|
||||
this.sensorDataAggregator = new SensorDataAggregator();
|
||||
}
|
||||
|
||||
public void start(Context context, Handler handler) {
|
||||
@@ -100,11 +112,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
gpsManager.stop();
|
||||
gpsManager = null;
|
||||
|
||||
sensorDataAggregator.clear();
|
||||
}
|
||||
|
||||
public SensorDataSet getSensorDataSet(Instant now) {
|
||||
return sensorDataAggregator.getSensorData(now);
|
||||
clear();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
@@ -112,7 +120,17 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
Log.d(TAG, "No recording running and no reset necessary.");
|
||||
return;
|
||||
}
|
||||
sensorDataAggregator.reset();
|
||||
|
||||
Log.i(TAG, "Resetting data");
|
||||
|
||||
if (heartRate != null) heartRate.resetAggregated();
|
||||
if (temperature != null) temperature.resetAggregated();
|
||||
if (cyclingCadence != null) cyclingCadence.resetAggregated();
|
||||
if (cyclingDistanceSpeed != null) cyclingDistanceSpeed.resetAggregated();
|
||||
if (cyclingPower != null) cyclingPower.resetAggregated();
|
||||
if (runningDistanceSpeedCadence != null) runningDistanceSpeedCadence.resetAggregated();
|
||||
if (barometer != null) barometer.resetAggregated();
|
||||
if (gps != null) gps.resetAggregated();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -155,4 +173,197 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
|
||||
Instant getNow();
|
||||
}
|
||||
|
||||
|
||||
//TODO Inline from SensorDataAggregator; Aggregators will be moved into Drivers.
|
||||
@VisibleForTesting
|
||||
public AggregatorHeartRate heartRate;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorTemperature temperature;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingCadence cyclingCadence;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingDistanceSpeed cyclingDistanceSpeed;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingPower cyclingPower;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorRunning runningDistanceSpeedCadence;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorBarometer barometer;
|
||||
|
||||
public AggregatorGPS gps;
|
||||
|
||||
@VisibleForTesting
|
||||
public SensorData<HeartRate> getHeartRate(Instant now) {
|
||||
if (heartRate != null) {
|
||||
SensorData<HeartRate> value = heartRate.getAggregatedValueWithSensorName(now);
|
||||
if (value.data().isValid()) return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SensorData<Cadence> getCadence(Instant now) {
|
||||
if (cyclingCadence != null) {
|
||||
return cyclingCadence.getAggregatedValueWithSensorName(now);
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasReceivedData() && runningDistanceSpeedCadence.getAggregatedValue(now).cadence() != null) {
|
||||
return new SensorData<>(runningDistanceSpeedCadence.getAggregatedValue().cadence(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SensorData<Distance> getDistance(Instant now) {
|
||||
if (cyclingDistanceSpeed != null && cyclingDistanceSpeed.hasReceivedData()) {
|
||||
return new SensorData<>(cyclingDistanceSpeed.getAggregatedValue(now).distanceOverall(), cyclingDistanceSpeed.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasReceivedData()) {
|
||||
return new SensorData<>(runningDistanceSpeedCadence.getAggregatedValue(now).distance(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//TOOD simplify?
|
||||
private SensorData<Speed> getSpeed(Instant now) {
|
||||
|
||||
if (cyclingDistanceSpeed != null && cyclingDistanceSpeed.hasReceivedData() && cyclingDistanceSpeed.getAggregatedValue(now).speed() != null) {
|
||||
return new SensorData<>(cyclingDistanceSpeed.getAggregatedValue(now).speed(), cyclingDistanceSpeed.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasReceivedData() && runningDistanceSpeedCadence.getAggregatedValue(now).speed() != null) {
|
||||
return new SensorData<>(runningDistanceSpeedCadence.getAggregatedValue().speed(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void add(@NonNull Aggregator<?, ?> data) {
|
||||
set(data, data);
|
||||
}
|
||||
|
||||
//TODO Refactor generic "fun" here: go explicit.
|
||||
public void update(@NonNull Raw<?> data) {
|
||||
Object value = data.value();
|
||||
|
||||
if (value instanceof HeartRate) {
|
||||
this.heartRate.add((Raw<HeartRate>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Temperature) {
|
||||
this.temperature.add((Raw<Temperature>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof BluetoothHandlerCyclingCadence.CrankData) {
|
||||
this.cyclingCadence.add((Raw<BluetoothHandlerCyclingCadence.CrankData>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof BluetoothHandlerCyclingDistanceSpeed.WheelData) {
|
||||
this.cyclingDistanceSpeed.setWheelCircumference(PreferencesUtils.getWheelCircumference()); //TODO Fetch once and then listen for changes.
|
||||
this.cyclingDistanceSpeed.add((Raw<BluetoothHandlerCyclingDistanceSpeed.WheelData>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof BluetoothHandlerRunningSpeedAndCadence.Data) {
|
||||
this.runningDistanceSpeedCadence.add((Raw<BluetoothHandlerRunningSpeedAndCadence.Data>) data);
|
||||
|
||||
return;
|
||||
}
|
||||
if (value instanceof BluetoothHandlerCyclingPower.Data) {
|
||||
this.cyclingPower.add((Raw<BluetoothHandlerCyclingPower.Data>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof AtmosphericPressure) {
|
||||
this.barometer.add((Raw<AtmosphericPressure>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Position) {
|
||||
this.gps.add((Raw<Position>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(data.getClass().getCanonicalName() + " " + data.value().getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
public void remove(@NonNull Aggregator<?, ?> type) {
|
||||
set(type, null);
|
||||
}
|
||||
|
||||
// TODO inline with stop()?
|
||||
@VisibleForTesting
|
||||
public void clear() {
|
||||
Log.i(TAG, "Removing all aggregators");
|
||||
this.heartRate = null;
|
||||
this.temperature = null;
|
||||
this.cyclingCadence = null;
|
||||
this.cyclingDistanceSpeed = null;
|
||||
this.cyclingPower = null;
|
||||
this.runningDistanceSpeedCadence = null;
|
||||
this.barometer = null;
|
||||
this.gps = null;
|
||||
}
|
||||
|
||||
public SensorDataSet getSensorDataSet(Instant now) {
|
||||
return new SensorDataSet(
|
||||
gps != null && gps.hasReceivedData() ? gps.getAggregatedValueWithSensorName(now) : new SensorData<>(Position.of(now), ""),
|
||||
getSpeed(now),
|
||||
getDistance(now),
|
||||
getHeartRate(now),
|
||||
temperature != null && temperature.hasReceivedData() ? temperature.getAggregatedValueWithSensorName(now) : null,
|
||||
getCadence(now),
|
||||
cyclingPower != null && cyclingPower.hasReceivedData() ? cyclingPower.getAggregatedValueWithSensorName(now) : null,
|
||||
barometer != null && barometer.hasReceivedData() ? barometer.getAggregatedValueWithSensorName(now) : null
|
||||
);
|
||||
}
|
||||
|
||||
//TODO Refactor generic "fun" here: go explicit.
|
||||
private void set(@NonNull Aggregator<?, ?> type, @Nullable Aggregator<?, ?> sensorData) {
|
||||
Log.i(TAG, "Setting aggregator " + type.getClass().getCanonicalName() + " to " + sensorData);
|
||||
|
||||
if (type instanceof AggregatorHeartRate) {
|
||||
heartRate = (AggregatorHeartRate) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorTemperature) {
|
||||
temperature = (AggregatorTemperature) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingCadence) {
|
||||
cyclingCadence = (AggregatorCyclingCadence) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingDistanceSpeed) {
|
||||
cyclingDistanceSpeed = (AggregatorCyclingDistanceSpeed) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingPower) {
|
||||
cyclingPower = (AggregatorCyclingPower) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorRunning) {
|
||||
runningDistanceSpeedCadence = (AggregatorRunning) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorBarometer) {
|
||||
barometer = (AggregatorBarometer) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorGPS) {
|
||||
gps = (AggregatorGPS) sensorData;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(type.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,6 +48,11 @@ public abstract class Aggregator<Input, Output> {
|
||||
@NonNull
|
||||
protected abstract Output getNoneValue();
|
||||
|
||||
@Deprecated //TODO Removed; just implemented for refactoring. This code is bypassing core functionality of this class.
|
||||
public Output getAggregatedValue() {
|
||||
return aggregatedValue;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Output getAggregatedValue(Instant now) {
|
||||
if (!hasReceivedData()) {
|
||||
|
||||
@@ -1,229 +0,0 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.AtmosphericPressure;
|
||||
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.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerRunningSpeedAndCadence;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
public class SensorDataAggregator {
|
||||
|
||||
private static final String TAG = SensorDataAggregator.class.getSimpleName();
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorHeartRate heartRate;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorTemperature temperature;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingCadence cyclingCadence;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingDistanceSpeed cyclingDistanceSpeed;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingPower cyclingPower;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorRunning runningDistanceSpeedCadence;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorBarometer barometer;
|
||||
|
||||
public AggregatorGPS gps;
|
||||
|
||||
@VisibleForTesting
|
||||
public SensorData<HeartRate> getHeartRate(Instant now) {
|
||||
if (heartRate != null) {
|
||||
SensorData<HeartRate> value = heartRate.getAggregatedValueWithSensorName(now);
|
||||
if (value.data().isValid()) return value;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SensorData<Cadence> getCadence(Instant now) {
|
||||
if (cyclingCadence != null) {
|
||||
return cyclingCadence.getAggregatedValueWithSensorName(now);
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasReceivedData() && runningDistanceSpeedCadence.getAggregatedValue(now).cadence() != null) {
|
||||
return new SensorData<>(runningDistanceSpeedCadence.aggregatedValue.cadence(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private SensorData<Distance> getDistance(Instant now) {
|
||||
if (cyclingDistanceSpeed != null && cyclingDistanceSpeed.hasReceivedData()) {
|
||||
return new SensorData<>(cyclingDistanceSpeed.getAggregatedValue(now).distanceOverall(), cyclingDistanceSpeed.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasReceivedData()) {
|
||||
return new SensorData<>(runningDistanceSpeedCadence.getAggregatedValue(now).distance(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
//TOOD simplify?
|
||||
private SensorData<Speed> getSpeed(Instant now) {
|
||||
|
||||
if (cyclingDistanceSpeed != null && cyclingDistanceSpeed.hasReceivedData() && cyclingDistanceSpeed.getAggregatedValue(now).speed() != null) {
|
||||
return new SensorData<>(cyclingDistanceSpeed.getAggregatedValue(now).speed(), cyclingDistanceSpeed.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasReceivedData() && runningDistanceSpeedCadence.getAggregatedValue(now).speed() != null) {
|
||||
return new SensorData<>(runningDistanceSpeedCadence.aggregatedValue.speed(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void add(@NonNull Aggregator<?, ?> data) {
|
||||
set(data, data);
|
||||
}
|
||||
|
||||
//TODO Refactor generic "fun" here: go explicit.
|
||||
public void update(@NonNull Raw<?> data) {
|
||||
Object value = data.value();
|
||||
|
||||
if (value instanceof HeartRate) {
|
||||
this.heartRate.add((Raw<HeartRate>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Temperature) {
|
||||
this.temperature.add((Raw<Temperature>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof BluetoothHandlerCyclingCadence.CrankData) {
|
||||
this.cyclingCadence.add((Raw<BluetoothHandlerCyclingCadence.CrankData>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof BluetoothHandlerCyclingDistanceSpeed.WheelData) {
|
||||
this.cyclingDistanceSpeed.setWheelCircumference(PreferencesUtils.getWheelCircumference()); //TODO Fetch once and then listen for changes.
|
||||
this.cyclingDistanceSpeed.add((Raw<BluetoothHandlerCyclingDistanceSpeed.WheelData>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof BluetoothHandlerRunningSpeedAndCadence.Data) {
|
||||
this.runningDistanceSpeedCadence.add((Raw<BluetoothHandlerRunningSpeedAndCadence.Data>) data);
|
||||
|
||||
return;
|
||||
}
|
||||
if (value instanceof BluetoothHandlerCyclingPower.Data) {
|
||||
this.cyclingPower.add((Raw<BluetoothHandlerCyclingPower.Data>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof AtmosphericPressure) {
|
||||
this.barometer.add((Raw<AtmosphericPressure>) data);
|
||||
return;
|
||||
}
|
||||
if (value instanceof Position) {
|
||||
this.gps.add((Raw<Position>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(data.getClass().getCanonicalName() + " " + data.value().getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
public void remove(@NonNull Aggregator<?, ?> type) {
|
||||
set(type, null);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
Log.i(TAG, "Removing all aggregators");
|
||||
this.heartRate = null;
|
||||
this.temperature = null;
|
||||
this.cyclingCadence = null;
|
||||
this.cyclingDistanceSpeed = null;
|
||||
this.cyclingPower = null;
|
||||
this.runningDistanceSpeedCadence = null;
|
||||
this.barometer = null;
|
||||
this.gps = null;
|
||||
}
|
||||
|
||||
public SensorDataSet getSensorData(Instant now) {
|
||||
return new SensorDataSet(
|
||||
gps != null && gps.hasReceivedData() ? gps.getAggregatedValueWithSensorName(now) : new SensorData<>(Position.of(now), ""),
|
||||
getSpeed(now),
|
||||
getDistance(now),
|
||||
getHeartRate(now),
|
||||
temperature != null && temperature.hasReceivedData() ? temperature.getAggregatedValueWithSensorName(now) : null,
|
||||
getCadence(now),
|
||||
cyclingPower != null && cyclingPower.hasReceivedData() ? cyclingPower.getAggregatedValueWithSensorName(now) : null,
|
||||
barometer != null && barometer.hasReceivedData() ? barometer.getAggregatedValueWithSensorName(now) : null
|
||||
);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
Log.i(TAG, "Resetting data");
|
||||
|
||||
if (heartRate != null) heartRate.resetAggregated();
|
||||
if (temperature != null) temperature.resetAggregated();
|
||||
if (cyclingCadence != null) cyclingCadence.resetAggregated();
|
||||
if (cyclingDistanceSpeed != null) cyclingDistanceSpeed.resetAggregated();
|
||||
if (cyclingPower != null) cyclingPower.resetAggregated();
|
||||
if (runningDistanceSpeedCadence != null) runningDistanceSpeedCadence.resetAggregated();
|
||||
if (barometer != null) barometer.resetAggregated();
|
||||
if (gps != null) gps.resetAggregated();
|
||||
}
|
||||
|
||||
//TODO Refactor generic "fun" here: go explicit.
|
||||
private void set(@NonNull Aggregator<?, ?> type, @Nullable Aggregator<?, ?> sensorData) {
|
||||
Log.i(TAG, "Setting aggregator " + type.getClass().getCanonicalName() + " to " + sensorData);
|
||||
|
||||
if (type instanceof AggregatorHeartRate) {
|
||||
heartRate = (AggregatorHeartRate) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorTemperature) {
|
||||
temperature = (AggregatorTemperature) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingCadence) {
|
||||
cyclingCadence = (AggregatorCyclingCadence) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingDistanceSpeed) {
|
||||
cyclingDistanceSpeed = (AggregatorCyclingDistanceSpeed) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingPower) {
|
||||
cyclingPower = (AggregatorCyclingPower) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorRunning) {
|
||||
runningDistanceSpeedCadence = (AggregatorRunning) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorBarometer) {
|
||||
barometer = (AggregatorBarometer) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorGPS) {
|
||||
gps = (AggregatorGPS) sensorData;
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(type.getClass().getCanonicalName());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user