From d046ca1cd8ba702fce68d8ec71cc4997e5e6cc4a Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Sat, 27 May 2023 10:02:56 +0200 Subject: [PATCH] SensorManager handles SensorDataSet. Part of #1424. --- .../io/file/importer/ExportImportTest.java | 37 +++++------ .../AbstractBluetoothConnectionManager.java | 1 + .../sensors/BluetoothRemoteSensorManager.java | 64 ++----------------- .../opentracks/sensors/SensorManager.java | 43 ++++++++++--- .../sensors/sensorData/SensorDataSet.java | 44 +++++++++++-- .../services/handlers/TrackPointCreator.java | 5 ++ 6 files changed, 98 insertions(+), 96 deletions(-) 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 bdaf92f5c..c80d5129c 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 @@ -57,7 +57,6 @@ 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.AltitudeSumManager; -import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed; import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower; @@ -165,8 +164,7 @@ public class ExportImportTest { service.insertMarker("Marker 2", "Marker 2 category", "Marker 2 desc", null); trackPointCreator.setClock("2020-02-02T02:02:18Z"); - BluetoothRemoteSensorManager mockRemoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class); - trackPointCreator.getSensorManager().setBluetoothSensorManager(mockRemoteSensorManager); + trackPointCreator.getSensorManager().sensorDataSet = new SensorDataSet(); service.endCurrentTrack(); trackPointCreator.setClock("2020-02-02T02:03:20Z"); @@ -179,7 +177,6 @@ public class ExportImportTest { sendLocation(trackPointCreator, "2020-02-02T02:03:23Z", 3, 16.001, 10, 27, 15, 10, 0); trackPointCreator.setClock("2020-02-02T02:03:24Z"); - trackPointCreator.getSensorManager().setBluetoothSensorManager(mockRemoteSensorManager); service.endCurrentTrack(); Track track = contentProviderUtils.getTrack(trackId); @@ -495,9 +492,6 @@ public class ExportImportTest { } private void mockBLESensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power) { - BluetoothRemoteSensorManager remoteSensorManager = Mockito.mock(BluetoothRemoteSensorManager.class); - Mockito.when(remoteSensorManager.fill(Mockito.any())).thenAnswer(invocation -> { - TrackPoint trackPoint = invocation.getArgument(0); SensorDataSet sensorDataSet = new SensorDataSet(); sensorDataSet.set(new SensorDataCyclingPower("power", "power", Power.of(power))); @@ -508,21 +502,20 @@ public class ExportImportTest { Mockito.when(cyclingCadence.getValue()).thenReturn(Cadence.of(cadence)); sensorDataSet.set(cyclingCadence); - if (distance != null && speed != null) { - SensorDataCyclingDistanceSpeed.Data distanceSpeedData = Mockito.mock(SensorDataCyclingDistanceSpeed.Data.class); - Mockito.when(distanceSpeedData.getDistanceOverall()).thenReturn(distance); - Mockito.when(distanceSpeedData.getSpeed()).thenReturn(Speed.of(speed)); - SensorDataCyclingDistanceSpeed distanceSpeed = Mockito.mock(SensorDataCyclingDistanceSpeed.class); - Mockito.when(distanceSpeed.hasValue()).thenReturn(true); - Mockito.when(distanceSpeed.getValue()).thenReturn(distanceSpeedData); - sensorDataSet.set(distanceSpeed); - } + if (distance != null && speed != null) { + SensorDataCyclingDistanceSpeed.Data distanceSpeedData = Mockito.mock(SensorDataCyclingDistanceSpeed.Data.class); + Mockito.when(distanceSpeedData.getDistanceOverall()).thenReturn(distance); + Mockito.when(distanceSpeedData.getSpeed()).thenReturn(Speed.of(speed)); + SensorDataCyclingDistanceSpeed distanceSpeed = Mockito.mock(SensorDataCyclingDistanceSpeed.class); + Mockito.when(distanceSpeed.hasValue()).thenReturn(true); + Mockito.when(distanceSpeed.getValue()).thenReturn(distanceSpeedData); + sensorDataSet.set(distanceSpeed); + } - sensorDataSet.fillTrackPoint(trackPoint); - return sensorDataSet; - }); - trackPointCreator.getSensorManager().setBluetoothSensorManager(remoteSensorManager); - trackPointCreator.onChange(new SensorDataSet()); + trackPointCreator.getSensorManager().sensorDataSet = sensorDataSet; + trackPointCreator.onChange(sensorDataSet); + + //TODO Might require: getSensorManager().sensorDataSet = new SensorDataSet() } private void mockAltitudeChange(TrackPointCreator trackPointCreator, float altitudeGain) { @@ -545,6 +538,6 @@ public class ExportImportTest { mockAltitudeChange(trackPointCreator, altitudeGain); trackPointCreator.setClock(time); - trackPointCreator.getGpsHandler().onLocationChanged(location); + trackPointCreator.onChange(location); } } \ No newline at end of file diff --git a/src/main/java/de/dennisguse/opentracks/sensors/AbstractBluetoothConnectionManager.java b/src/main/java/de/dennisguse/opentracks/sensors/AbstractBluetoothConnectionManager.java index 7e0c19f8e..218fbd786 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/AbstractBluetoothConnectionManager.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/AbstractBluetoothConnectionManager.java @@ -189,6 +189,7 @@ public abstract class AbstractBluetoothConnectionManager { */ protected abstract SensorData parsePayload(@NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, @NonNull BluetoothGattCharacteristic characteristic); + @Deprecated //TODO REMOVE interface SensorDataObserver { void onChanged(SensorData sensorData); diff --git a/src/main/java/de/dennisguse/opentracks/sensors/BluetoothRemoteSensorManager.java b/src/main/java/de/dennisguse/opentracks/sensors/BluetoothRemoteSensorManager.java index 2711aa1bf..53036f066 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/BluetoothRemoteSensorManager.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/BluetoothRemoteSensorManager.java @@ -24,17 +24,12 @@ import android.os.Handler; import android.util.Log; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import java.time.Duration; import de.dennisguse.opentracks.R; -import de.dennisguse.opentracks.data.models.Distance; -import de.dennisguse.opentracks.data.models.TrackPoint; import de.dennisguse.opentracks.sensors.sensorData.SensorData; -import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence; -import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed; -import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning; -import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet; import de.dennisguse.opentracks.settings.PreferencesUtils; import de.dennisguse.opentracks.util.PermissionRequester; @@ -61,20 +56,15 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl private final BluetoothAdapter bluetoothAdapter; private final Context context; private final Handler handler; + private final SensorManager.SensorDataChangedObserver observer; private boolean started = false; - private Distance preferenceWheelCircumference; - private final BluetoothConnectionManagerHeartRate heartRate = new BluetoothConnectionManagerHeartRate(this); private final BluetoothConnectionManagerCyclingCadence cyclingCadence = new BluetoothConnectionManagerCyclingCadence(this); private final BluetoothConnectionManagerCyclingDistanceSpeed cyclingSpeed = new BluetoothConnectionManagerCyclingDistanceSpeed(this); private final BluetoothConnectionManagerCyclingPower cyclingPower = new BluetoothConnectionManagerCyclingPower(this); private final BluetoothConnectionRunningSpeedAndCadence runningSpeedAndCadence = new BluetoothConnectionRunningSpeedAndCadence(this); - private final SensorDataSet sensorDataSet = new SensorDataSet(); - - private final SensorManager.SensorDataSetChangeObserver observer; - private final SharedPreferences.OnSharedPreferenceChangeListener sharedPreferenceChangeListener = new SharedPreferences.OnSharedPreferenceChangeListener() { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { @@ -95,9 +85,6 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl connect(cyclingSpeed, address); } - if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_speed_wheel_circumference_key, key)) { - preferenceWheelCircumference = PreferencesUtils.getWheelCircumference(); - } if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_power_key, key)) { String address = PreferencesUtils.getBluetoothCyclingPowerSensorAddress(); @@ -114,7 +101,7 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl } }; - public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @NonNull SensorManager.SensorDataSetChangeObserver observer) { + public BluetoothRemoteSensorManager(@NonNull Context context, @NonNull Handler handler, @Nullable SensorManager.SensorDataChangedObserver observer) { this.context = context; this.handler = handler; this.observer = observer; @@ -137,8 +124,6 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl cyclingPower.disconnect(); runningSpeedAndCadence.disconnect(); - sensorDataSet.clear(); - PreferencesUtils.unregisterOnSharedPreferenceChangeListener(sharedPreferenceChangeListener); started = false; } @@ -178,53 +163,14 @@ public class BluetoothRemoteSensorManager implements SensorConnector, AbstractBl } } - public SensorDataSet fill(@NonNull TrackPoint trackPoint) { - sensorDataSet.fillTrackPoint(trackPoint); - return new SensorDataSet(sensorDataSet); - } - - public void reset() { - sensorDataSet.reset(); - } - @Override public synchronized void onChanged(SensorData sensorData) { - if (sensorData instanceof SensorDataCyclingCadence) { - SensorDataCyclingCadence previous = sensorDataSet.getCyclingCadence(); - Log.d(TAG, "Previous: " + previous + "; current: " + sensorData); - - if (sensorData.equals(previous)) { - Log.d(TAG, "onChanged: cadence data repeated."); - return; - } - ((SensorDataCyclingCadence) sensorData).compute(previous); - } - if (sensorData instanceof SensorDataCyclingDistanceSpeed) { - SensorDataCyclingDistanceSpeed previous = sensorDataSet.getCyclingDistanceSpeed(); - Log.d(TAG, "Previous: " + previous + "; Current" + sensorData); - if (sensorData.equals(previous)) { - Log.d(TAG, "onChanged: cycling speed data repeated."); - return; - } - ((SensorDataCyclingDistanceSpeed) sensorData).compute(previous, preferenceWheelCircumference); - } - if (sensorData instanceof SensorDataRunning) { - SensorDataRunning previous = sensorDataSet.getRunningDistanceSpeedCadence(); - Log.d(TAG, "Previous: " + previous + "; Current" + sensorData); - if (sensorData.equals(previous)) { - Log.d(TAG, "onChanged: running speed data repeated."); - return; - } - ((SensorDataRunning) sensorData).compute(previous); - } - - sensorDataSet.set(sensorData); - observer.onChange(new SensorDataSet(sensorDataSet)); + observer.onChange(sensorData); } @Override public void onDisconnecting(SensorData sensorData) { - sensorDataSet.remove(sensorData); + observer.onDisconnect(sensorData); } @NonNull diff --git a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java index bf8e82d08..d2e02fdf6 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java @@ -14,12 +14,34 @@ public class SensorManager { private static final String TAG = SensorManager.class.getSimpleName(); + //TODO Should be final and not be visible for testing + @VisibleForTesting + public SensorDataSet sensorDataSet = new SensorDataSet(); + + private final SensorManager.SensorDataSetChangeObserver observer; + + private final SensorDataChangedObserver listener = new SensorDataChangedObserver() { + + @Override + public void onChange(SensorData sensorData) { + sensorDataSet.set(sensorData); + observer.onChange(new SensorDataSet(sensorDataSet)); + } + + @Override + public void onDisconnect(SensorData sensorData) { + sensorDataSet.remove(sensorData); + observer.onChange(new SensorDataSet(sensorDataSet)); + } + }; + private BluetoothRemoteSensorManager bluetoothSensorManager; private AltitudeSumManager altitudeSumManager; public SensorManager(Context context, Handler handler, SensorDataSetChangeObserver observer) { - bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, observer); + this.observer = observer; + bluetoothSensorManager = new BluetoothRemoteSensorManager(context, handler, listener); altitudeSumManager = new AltitudeSumManager(); } @@ -38,11 +60,14 @@ public class SensorManager { altitudeSumManager.stop(context); altitudeSumManager = null; } + + sensorDataSet.clear(); } public SensorDataSet fill(TrackPoint trackPoint) { altitudeSumManager.fill(trackPoint); - return bluetoothSensorManager.fill(trackPoint); + sensorDataSet.fillTrackPoint(trackPoint); + return new SensorDataSet(sensorDataSet); } public void reset() { @@ -50,7 +75,7 @@ public class SensorManager { Log.d(TAG, "No recording running and no reset necessary."); return; } - bluetoothSensorManager.reset(); + sensorDataSet.reset(); altitudeSumManager.reset(); } @@ -60,12 +85,6 @@ public class SensorManager { return bluetoothSensorManager; } - @Deprecated - @VisibleForTesting - public void setBluetoothSensorManager(BluetoothRemoteSensorManager remoteSensorManager) { - this.bluetoothSensorManager = remoteSensorManager; - } - @Deprecated @VisibleForTesting public AltitudeSumManager getAltitudeSumManager() { @@ -78,6 +97,12 @@ public class SensorManager { this.altitudeSumManager = altitudeSumManager; } + public interface SensorDataChangedObserver { + void onChange(SensorData sensorData); + + void onDisconnect(SensorData sensorData); + } + @Deprecated public interface SensorDataSetChangeObserver { void onChange(SensorDataSet sensorDataSet); diff --git a/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java b/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java index 07cb2535f..3ae7b3141 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/sensorData/SensorDataSet.java @@ -1,16 +1,21 @@ package de.dennisguse.opentracks.sensors.sensorData; +import android.util.Log; import android.util.Pair; import androidx.annotation.NonNull; 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.Speed; import de.dennisguse.opentracks.data.models.TrackPoint; +import de.dennisguse.opentracks.settings.PreferencesUtils; public final class SensorDataSet { + private static final String TAG = SensorDataSet.class.getSimpleName(); + private SensorDataHeartRate heartRate; private SensorDataCyclingCadence cyclingCadence; @@ -140,28 +145,55 @@ public final class SensorDataSet { + (runningDistanceSpeedCadence != null ? " " + runningDistanceSpeedCadence : ""); } - private void set(@NonNull SensorData type, SensorData data) { + private void set(@NonNull SensorData type, SensorData sensorData) { if (type instanceof SensorDataHeartRate) { - this.heartRate = (SensorDataHeartRate) data; + this.heartRate = (SensorDataHeartRate) sensorData; return; } if (type instanceof SensorDataCyclingCadence) { - this.cyclingCadence = (SensorDataCyclingCadence) data; + SensorDataCyclingCadence previous = getCyclingCadence(); + Log.d(TAG, "Previous: " + previous + "; current: " + sensorData); + + if (sensorData.equals(previous)) { + Log.d(TAG, "onChanged: cadence data repeated."); + return; + } + + this.cyclingCadence = (SensorDataCyclingCadence) sensorData; + this.cyclingCadence.compute(previous); return; } + if (type instanceof SensorDataCyclingDistanceSpeed) { - this.cyclingDistanceSpeed = (SensorDataCyclingDistanceSpeed) data; + SensorDataCyclingDistanceSpeed previous = getCyclingDistanceSpeed(); + Log.d(TAG, "Previous: " + previous + "; Current" + sensorData); + if (sensorData.equals(previous)) { + Log.d(TAG, "onChanged: cycling speed data repeated."); + return; + } + Distance preferenceWheelCircumference = PreferencesUtils.getWheelCircumference(); //TODO Fetch once and then listen for changes. + + this.cyclingDistanceSpeed = (SensorDataCyclingDistanceSpeed) sensorData; + this.cyclingDistanceSpeed.compute(previous, preferenceWheelCircumference); return; } if (type instanceof SensorDataCyclingPower) { - this.cyclingPower = (SensorDataCyclingPower) data; + this.cyclingPower = (SensorDataCyclingPower) sensorData; return; } if (type instanceof SensorDataRunning) { - this.runningDistanceSpeedCadence = (SensorDataRunning) data; + SensorDataRunning previous = getRunningDistanceSpeedCadence(); + Log.d(TAG, "Previous: " + previous + "; Current" + sensorData); + if (sensorData.equals(previous)) { + Log.d(TAG, "onChanged: running speed data repeated."); + return; + } + + this.runningDistanceSpeedCadence = (SensorDataRunning) sensorData; + this.runningDistanceSpeedCadence.compute(previous); return; } diff --git a/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java b/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java index 744760401..aab81ac6b 100644 --- a/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java +++ b/src/main/java/de/dennisguse/opentracks/services/handlers/TrackPointCreator.java @@ -142,6 +142,11 @@ public class TrackPointCreator implements SensorManager.SensorDataSetChangeObser return sensorManager; } + @VisibleForTesting + public void setSensorManager(SensorManager sensorManager) { + this.sensorManager = sensorManager; + } + @VisibleForTesting public void setClock(@NonNull String time) { this.clock = Clock.fixed(Instant.parse(time), ZoneId.of("CET"));