From c6cb388ce42f4cb8839f650a808b12c8ef4bd6ab Mon Sep 17 00:00:00 2001 From: Dennis Guse Date: Fri, 30 Jan 2026 09:09:33 +0100 Subject: [PATCH] Created HeartRateHandler. --- .../io/file/importer/ExportImportTest.java | 4 +- .../TrackRecordingServiceRecordingTest.java | 10 +++- .../opentracks/sensors/HeartRateHandler.java | 58 +++++++++++++++++++ .../opentracks/sensors/SensorManager.java | 49 ++++++++-------- 4 files changed, 92 insertions(+), 29 deletions(-) create mode 100644 src/main/java/de/dennisguse/opentracks/sensors/HeartRateHandler.java 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 43bcbc68d..8b240c8bd 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 @@ -659,7 +659,7 @@ public class ExportImportTest { } } - private void mockSensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power, Float altitudeGain, float temperature) { + private static void mockSensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power, Float altitudeGain, float temperature) { SensorManager sensorManager = trackPointCreator.getSensorManager(); AggregatorCyclingPower cyclingPower = new AggregatorCyclingPower("", ""); @@ -721,7 +721,7 @@ public class ExportImportTest { trackPointCreator.onChange(); } - private void mockAltitudeChange(TrackPointCreator trackPointCreator, Float altitudeGain) { + private static void mockAltitudeChange(TrackPointCreator trackPointCreator, Float altitudeGain) { SensorManager sensorManager = trackPointCreator.getSensorManager(); if (altitudeGain == null) { diff --git a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java index 3eea9229e..67b1ac760 100644 --- a/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java +++ b/src/androidTest/java/de/dennisguse/opentracks/services/TrackRecordingServiceRecordingTest.java @@ -336,17 +336,21 @@ public class TrackRecordingServiceRecordingTest { mockAltitudeChange(trackPointCreator, 0); SensorManager sensorManager = trackPointCreator.getSensorManager(); - sensorManager.add(new AggregatorHeartRate("", "")); // when String sensor1 = "2020-02-02T02:02:03Z"; trackPointCreator.setClock(sensor1); + AggregatorHeartRate avgHeartRate = new AggregatorHeartRate("", ""); + sensorManager.add(avgHeartRate); + //Should be ignored - sensorManager.onChange(HeartRate.of(5)); + avgHeartRate.add(trackPointCreator.getNow(), HeartRate.of(5)); + sensorManager.onChange(); String sensor3 = "2020-02-02T02:02:13Z"; trackPointCreator.setClock(sensor3); - sensorManager.onChange(HeartRate.of(7)); + avgHeartRate.add(trackPointCreator.getNow(), HeartRate.of(7)); + sensorManager.onChange(); String stopTime = "2020-02-02T02:02:15Z"; trackPointCreator.setClock(stopTime); diff --git a/src/main/java/de/dennisguse/opentracks/sensors/HeartRateHandler.java b/src/main/java/de/dennisguse/opentracks/sensors/HeartRateHandler.java new file mode 100644 index 000000000..55df2dba6 --- /dev/null +++ b/src/main/java/de/dennisguse/opentracks/sensors/HeartRateHandler.java @@ -0,0 +1,58 @@ +package de.dennisguse.opentracks.sensors; + +import androidx.annotation.NonNull; + +import de.dennisguse.opentracks.R; +import de.dennisguse.opentracks.data.models.HeartRate; +import de.dennisguse.opentracks.sensors.driver.Driver; +import de.dennisguse.opentracks.sensors.driver.DriverObserver0; +import de.dennisguse.opentracks.sensors.sensorData.Aggregator; +import de.dennisguse.opentracks.sensors.sensorData.AggregatorHeartRate; + +public class HeartRateHandler extends SensorHandler { + + protected HeartRateHandler(SensorManager sensorManager) { + super(sensorManager); + } + + @NonNull + @Override + protected Driver createDriverBluetooth(String address) { + return new BluetoothConnectionManager( + BluetoothUtils.getAdapter(getContext()), + new DriverObserver0() { + @Override + public void onConnect(Aggregator emptySensorData) { + driverObserver.onConnect(); + } + + @Override + public void onDisconnect(Aggregator emptySensorData) { + driverObserver.onDisconnect(); + } + + @Override + public void onRemove(Aggregator emptySensorData) { + driverObserver.onRemove(); + } + + @Override + public void onChange(Record value) { + driverObserver.onData((HeartRate) value); + } + }, + new BluetoothHandlerHeartRate() + ); + } + + @NonNull + @Override + protected Aggregator createAggregator() { + return new AggregatorHeartRate("", null); + } + + @Override + protected int getSensorPreferenceKey() { + return R.string.settings_sensor_bluetooth_heart_rate_key; + } +} diff --git a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java index f7206fd74..a6620a10b 100644 --- a/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java +++ b/src/main/java/de/dennisguse/opentracks/sensors/SensorManager.java @@ -50,7 +50,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange private final TrackPointCreator observer; - private BluetoothConnectionManager heartRateManager; + private HeartRateHandler heartRateHandler; private BluetoothConnectionManager temperatureManager; private BluetoothConnectionManager cyclingCadenceManager; private BluetoothConnectionManager cyclingSpeedManager; @@ -77,7 +77,9 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange gpsManager = new GpsManager(observer, this); altitudeSumManager = new GainManager(this); BluetoothAdapter bluetoothAdapter = BluetoothUtils.getAdapter(context); - this.heartRateManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerHeartRate()); + this.heartRateHandler = new HeartRateHandler(this); + + new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerHeartRate()); this.temperatureManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerTemperature()); this.cyclingCadenceManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerCyclingCadence()); this.cyclingSpeedManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerCyclingDistanceSpeed()); @@ -85,7 +87,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange this.runningSpeedAndCadenceManager = new BluetoothConnectionManager(bluetoothAdapter, this, new BluetoothHandlerRunningSpeedAndCadence()); altitudeSumManager.start(context, handler); - + heartRateHandler.start(context, handler); onSharedPreferenceChanged(null, null); gpsManager.start(context, handler); @@ -94,8 +96,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange public void stop() { wakeLock = SystemUtils.releaseWakeLock(wakeLock); - heartRateManager.disconnect(); - heartRateManager = null; + heartRateHandler.stop(); + heartRateHandler = null; temperatureManager.disconnect(); temperatureManager = null; @@ -132,7 +134,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange Log.i(TAG, "Resetting data"); - if (heartRate != null) heartRate.resetAggregated(); + if (heartRateHandler.getAggregator() != null) heartRateHandler.getAggregator().resetAggregated(); if (temperature != null) temperature.resetAggregated(); if (cyclingCadence != null) cyclingCadence.resetAggregated(); if (cyclingDistanceSpeed != null) cyclingDistanceSpeed.resetAggregated(); @@ -171,9 +173,8 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange altitudeSumManager.connect(); } - if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_heart_rate_key, key)) { - String address = PreferencesUtils.getBluetoothHeartRateSensorAddress(); - connect(heartRateManager, address); + if (PreferencesUtils.isKey(heartRateHandler.getSensorPreferenceKey(), key)) { + heartRateHandler.connect(); } if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_temperature_key, key)) { @@ -226,9 +227,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange return observer.getNow(); } - @VisibleForTesting - public AggregatorHeartRate heartRate; - @VisibleForTesting public AggregatorTemperature temperature; @@ -246,8 +244,9 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange @VisibleForTesting public SensorData getHeartRate(Instant now) { - if (heartRate != null) { - SensorData value = heartRate.getAggregatedValueWithSensorName(now); + if (heartRateHandler.getAggregator() != null) { + SensorData value = (SensorData) heartRateHandler.getAggregator().getAggregatedValueWithSensorName(now); + //TODO Move this check into HeartRateHandler if (value.data().isValid()) return value; } @@ -293,7 +292,14 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange return null; } + //TODO Remove + @VisibleForTesting + @Deprecated public void add(@NonNull Aggregator data) { + if (data instanceof AggregatorHeartRate) { + heartRateHandler.setAggregator((AggregatorHeartRate) data); + return; + } set(data, data); } @@ -308,14 +314,10 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange } //TODO Refactor generic "fun" here: go explicit. + @Deprecated private void update(@NonNull Record value) { Instant now = getNow(); - if (value instanceof HeartRate) { - this.heartRate.add(now, (HeartRate) value); - return; - } - if (value instanceof Temperature) { this.temperature.add(now, (Temperature) value); return; @@ -343,6 +345,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange throw new UnsupportedOperationException(value.getClass().getCanonicalName()); } + @Deprecated public void remove(@NonNull Aggregator type) { set(type, null); } @@ -351,7 +354,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange @VisibleForTesting public void clear() { Log.i(TAG, "Removing all aggregators"); - this.heartRate = null; this.temperature = null; this.cyclingCadence = null; this.cyclingDistanceSpeed = null; @@ -362,6 +364,9 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange if (this.altitudeSumManager != null) { this.altitudeSumManager.setAggregator(null); } + if (this.heartRateHandler != null) { + this.heartRateHandler.setAggregator(null); + } if (this.gpsManager != null) { this.gpsManager.setAggregatorGPS(); } @@ -387,10 +392,6 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange 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;