mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-09-30 16:52:21 +02:00
+10
-4
@@ -548,22 +548,28 @@ public class ExportImportTest {
|
||||
private void mockBLESensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power) {
|
||||
|
||||
SensorDataSet sensorDataSet = new SensorDataSet();
|
||||
sensorDataSet.set(new SensorDataCyclingPower("power", "power", Power.of(power)));
|
||||
sensorDataSet.set(new SensorDataHeartRate("heartRate", "heartRate", HeartRate.of(heartRate)));
|
||||
|
||||
sensorDataSet.cyclingPower = Mockito.mock(SensorDataCyclingPower.class);
|
||||
Mockito.when( sensorDataSet.cyclingPower.hasValue()).thenReturn(true);
|
||||
Mockito.when(sensorDataSet.cyclingPower.getValue()).thenReturn(Power.of(power));
|
||||
|
||||
sensorDataSet.heartRate = Mockito.mock(SensorDataHeartRate.class);
|
||||
Mockito.when(sensorDataSet.heartRate.getValue()).thenReturn(HeartRate.of(heartRate));
|
||||
|
||||
SensorDataCyclingCadence cyclingCadence = Mockito.mock(SensorDataCyclingCadence.class);
|
||||
Mockito.when(cyclingCadence.hasValue()).thenReturn(true);
|
||||
Mockito.when(cyclingCadence.getValue()).thenReturn(Cadence.of(cadence));
|
||||
sensorDataSet.set(cyclingCadence);
|
||||
sensorDataSet.cyclingCadence = 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);
|
||||
sensorDataSet.cyclingDistanceSpeed = distanceSpeed;
|
||||
}
|
||||
|
||||
trackPointCreator.getSensorManager().sensorDataSet = sensorDataSet;
|
||||
|
||||
+10
-11
@@ -4,11 +4,10 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.util.Pair;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
|
||||
|
||||
public class BluetoothHandlerCyclingDistanceSpeedTest {
|
||||
@Test
|
||||
public void parseCyclingSpeedCadence_crankOnly() {
|
||||
@@ -16,11 +15,11 @@ public class BluetoothHandlerCyclingDistanceSpeedTest {
|
||||
characteristic.setValue(new byte[]{0x02, (byte) 0xC8, 0x00, 0x00, 0x00, 0x06, (byte) 0x99});
|
||||
|
||||
// when
|
||||
SensorDataCyclingCadenceAndDistanceSpeed sensor = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
|
||||
Pair<BluetoothHandlerCyclingDistanceSpeed.WheelData, BluetoothHandlerCyclingCadence.CrankData> sensor = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
|
||||
|
||||
// then
|
||||
assertNull(sensor.getDistanceSpeed());
|
||||
assertEquals(200, sensor.getCadence().getCrankRevolutionsCount());
|
||||
assertNull(sensor.first);
|
||||
assertEquals(200, sensor.second.crankRevolutionsCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -29,11 +28,11 @@ public class BluetoothHandlerCyclingDistanceSpeedTest {
|
||||
characteristic.setValue(new byte[]{0x01, (byte) 0xFF, (byte) 0xFF, 0, 1, 0x45, (byte) 0x99});
|
||||
|
||||
// when
|
||||
SensorDataCyclingCadenceAndDistanceSpeed sensor = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
|
||||
Pair<BluetoothHandlerCyclingDistanceSpeed.WheelData, BluetoothHandlerCyclingCadence.CrankData> sensor = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
|
||||
|
||||
// then
|
||||
assertEquals(65535 + 16777216, sensor.getDistanceSpeed().getWheelRevolutionsCount());
|
||||
assertNull(sensor.getCadence());
|
||||
assertEquals(65535 + 16777216, sensor.first.wheelRevolutionsCount());
|
||||
assertNull(sensor.second);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -42,11 +41,11 @@ public class BluetoothHandlerCyclingDistanceSpeedTest {
|
||||
characteristic.setValue(new byte[]{0x03, (byte) 0xC8, 0x00, 0x00, 0x01, 0x06, (byte) 0x99, (byte) 0xE1, 0x00, 0x45, (byte) 0x99});
|
||||
|
||||
// when
|
||||
SensorDataCyclingCadenceAndDistanceSpeed sensor = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
|
||||
Pair<BluetoothHandlerCyclingDistanceSpeed.WheelData, BluetoothHandlerCyclingCadence.CrankData> sensor = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel("address", "sensorName", characteristic);
|
||||
|
||||
// then
|
||||
assertEquals(200 + 16777216, sensor.getDistanceSpeed().getWheelRevolutionsCount());
|
||||
assertEquals(225, sensor.getCadence().getCrankRevolutionsCount());
|
||||
assertEquals(200 + 16777216, sensor.first.wheelRevolutionsCount());
|
||||
assertEquals(225, sensor.second.crankRevolutionsCount());
|
||||
}
|
||||
|
||||
}
|
||||
+6
-8
@@ -6,8 +6,6 @@ import android.bluetooth.BluetoothGattCharacteristic;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
|
||||
|
||||
public class BluetoothHandlerCyclingPowerTest {
|
||||
|
||||
@Test
|
||||
@@ -16,10 +14,10 @@ public class BluetoothHandlerCyclingPowerTest {
|
||||
characteristic.setValue(new byte[]{0, 0, 40, 0});
|
||||
|
||||
// when
|
||||
SensorDataCyclingPower.Data powerCadence = BluetoothHandlerManagerCyclingPower.parseCyclingPower("", "", characteristic);
|
||||
BluetoothHandlerManagerCyclingPower.Data powerCadence = BluetoothHandlerManagerCyclingPower.parseCyclingPower(characteristic);
|
||||
|
||||
// then
|
||||
assertEquals(40, powerCadence.power().getValue().getW(), 0.01);
|
||||
assertEquals(40, powerCadence.power().getW(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -28,13 +26,13 @@ public class BluetoothHandlerCyclingPowerTest {
|
||||
characteristic.setValue(new byte[]{0x2C, 0x00, 0x00, 0x00, (byte) 0x9F, 0x00, 0x0C, 0x00, (byte) 0xE5, 0x42});
|
||||
|
||||
// when
|
||||
SensorDataCyclingPower.Data powerCadence = BluetoothHandlerManagerCyclingPower.parseCyclingPower("", "", characteristic);
|
||||
BluetoothHandlerManagerCyclingPower.Data powerCadence = BluetoothHandlerManagerCyclingPower.parseCyclingPower(characteristic);
|
||||
|
||||
// then
|
||||
assertEquals(0, powerCadence.power().getValue().getW(), 0.01);
|
||||
assertEquals(0, powerCadence.power().getW(), 0.01);
|
||||
|
||||
assertEquals(12, powerCadence.cadence().getCrankRevolutionsCount());
|
||||
assertEquals(17125, powerCadence.cadence().getCrankRevolutionsTime());
|
||||
assertEquals(12, powerCadence.crank().crankRevolutionsCount());
|
||||
assertEquals(17125, powerCadence.crank().crankRevolutionsTime());
|
||||
}
|
||||
|
||||
}
|
||||
+4
-5
@@ -9,7 +9,6 @@ import org.junit.Test;
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
|
||||
|
||||
public class BluetoothHandlerRunningSpeedAndCadenceTest {
|
||||
|
||||
@@ -19,11 +18,11 @@ public class BluetoothHandlerRunningSpeedAndCadenceTest {
|
||||
characteristic.setValue(new byte[]{2, 0, 5, 80, (byte) 0xFF, (byte) 0xFF, 0, 1});
|
||||
|
||||
// when
|
||||
SensorDataRunning sensor = BluetoothHandlerRunningSpeedAndCadence.parseRunningSpeedAndCadence("address", "sensorName", characteristic);
|
||||
BluetoothHandlerRunningSpeedAndCadence.Data sensor = BluetoothHandlerRunningSpeedAndCadence.parseRunningSpeedAndCadence("sensorName", characteristic);
|
||||
|
||||
// then
|
||||
assertEquals(Speed.of(5), sensor.getSpeed());
|
||||
assertEquals(Cadence.of(80), sensor.getCadence());
|
||||
assertEquals(Distance.of(6553.5 + 1677721.6), sensor.getTotalDistance());
|
||||
assertEquals(Speed.of(5), sensor.speed());
|
||||
assertEquals(Cadence.of(80), sensor.cadence());
|
||||
assertEquals(Distance.of(6553.5 + 1677721.6), sensor.totalDistance());
|
||||
}
|
||||
}
|
||||
+35
-92
@@ -2,17 +2,17 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.UintUtils;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -20,12 +20,11 @@ public class SensorDataCyclingTest {
|
||||
|
||||
@Test
|
||||
public void compute_cadence_1() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", 1, 1024); // 1s
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 2, 2048); // 2s
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 2048)));
|
||||
|
||||
// then
|
||||
assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
@@ -33,12 +32,11 @@ public class SensorDataCyclingTest {
|
||||
|
||||
@Test
|
||||
public void compute_cadence_2() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", 1, 6184);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 2, 8016);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 6184)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 8016)));
|
||||
|
||||
// then
|
||||
assertEquals(33.53, current.getValue().getRPM(), 0.01);
|
||||
@@ -46,12 +44,11 @@ public class SensorDataCyclingTest {
|
||||
|
||||
@Test
|
||||
public void compute_cadence_sameCount() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", 1, 1024);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 1, 2048);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 2048)));
|
||||
|
||||
// then
|
||||
assertEquals(Cadence.of(0), current.getValue());
|
||||
@@ -60,126 +57,72 @@ public class SensorDataCyclingTest {
|
||||
|
||||
@Test
|
||||
public void compute_cadence_sameTime() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", 1, 1024);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 2, 1024);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 1024)));
|
||||
|
||||
// then
|
||||
assertFalse(current.hasValue());
|
||||
assertFalse(current.hasValue()); //TODO Cadence should be 0?
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compute_cadence_rollOverTime() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", 1, UintUtils.UINT16_MAX - 1024);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 2, 0);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(1, UintUtils.UINT16_MAX - 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(2, 0)));
|
||||
|
||||
// then
|
||||
assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
}
|
||||
|
||||
@Ignore("Disabled from #953")
|
||||
@Test
|
||||
@Deprecated
|
||||
public void compute_cadence_rollOverCount() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", UintUtils.UINT32_MAX - 1, 1024);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 0, 2048);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("", "");
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
|
||||
// then
|
||||
assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compute_cadence_overflow() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress", "sensorName", UintUtils.UINT32_MAX - 1, 1024);
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 0, 2048);
|
||||
|
||||
// when
|
||||
current.compute(previous);
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(UintUtils.UINT32_MAX - 1, 1024)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingCadence.CrankData(0, 2048)));
|
||||
|
||||
// then
|
||||
// TODO See #953
|
||||
// assertEquals(60, current.getValue().getRPM(), 0.01);
|
||||
assertNull(current.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compute_speed() {
|
||||
// given
|
||||
SensorDataCyclingDistanceSpeed previous = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", 1, 6184);
|
||||
SensorDataCyclingDistanceSpeed current = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", 2, 8016);
|
||||
SensorDataCyclingDistanceSpeed current = new SensorDataCyclingDistanceSpeed("", "");
|
||||
current.setWheelCircumference(Distance.ofMM(2150));
|
||||
|
||||
// when
|
||||
current.compute(previous, Distance.ofMM(2150));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(1, 6184)));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(2, 8016)));
|
||||
|
||||
// then
|
||||
assertEquals(2.15, current.getValue().getDistance().toM(), 0.01);
|
||||
assertEquals(1.20, current.getValue().getSpeed().toMPS(), 0.01);
|
||||
}
|
||||
|
||||
@Ignore("Disabled from #953")
|
||||
@Test
|
||||
@Deprecated
|
||||
public void compute_speed_rollOverCount() {
|
||||
// given
|
||||
SensorDataCyclingDistanceSpeed previous = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", UintUtils.UINT32_MAX - 1, 1024);
|
||||
SensorDataCyclingDistanceSpeed current = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", 0, 2048);
|
||||
SensorDataCyclingDistanceSpeed current = new SensorDataCyclingDistanceSpeed("", "");
|
||||
current.setWheelCircumference(Distance.ofMM(2000));
|
||||
|
||||
// when
|
||||
current.compute(previous, Distance.ofMM(2000));
|
||||
|
||||
// then
|
||||
assertEquals(2, current.getValue().getDistance().toM(), 0.01);
|
||||
assertEquals(2, current.getValue().getSpeed().toMPS(), 0.01);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compute_speed_overflow() {
|
||||
// given
|
||||
SensorDataCyclingDistanceSpeed previous = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", UintUtils.UINT32_MAX - 1, 1024);
|
||||
SensorDataCyclingDistanceSpeed current = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", 0, 2048);
|
||||
|
||||
// when
|
||||
current.compute(previous, Distance.ofMM(2000));
|
||||
current.add(new Raw<>(new BluetoothHandlerCyclingDistanceSpeed.WheelData(UintUtils.UINT32_MAX - 1, 1024)));
|
||||
current.add(new Raw<>(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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_speed_with_no_data() {
|
||||
// given
|
||||
SensorDataCyclingDistanceSpeed previous = new SensorDataCyclingDistanceSpeed("sensorAddress");
|
||||
SensorDataCyclingDistanceSpeed current = new SensorDataCyclingDistanceSpeed("sensorAddress", "sensorName", 0, 2048);
|
||||
|
||||
// when
|
||||
previous.toString();
|
||||
|
||||
// then
|
||||
assertNotEquals(previous, current);
|
||||
assertNotEquals(previous, previous);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void equals_cadence_with_no_data() {
|
||||
// given
|
||||
SensorDataCyclingCadence previous = new SensorDataCyclingCadence("sensorAddress");
|
||||
SensorDataCyclingCadence current = new SensorDataCyclingCadence("sensorAddress", "sensorName", 0, 2048);
|
||||
|
||||
// when
|
||||
previous.toString();
|
||||
|
||||
// then
|
||||
assertNotEquals(previous, current);
|
||||
assertNotEquals(previous, previous);
|
||||
}
|
||||
}
|
||||
+11
-8
@@ -35,7 +35,9 @@ import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.importer.TrackPointAssert;
|
||||
import de.dennisguse.opentracks.sensors.AltitudeSumManager;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerRunningSpeedAndCadence;
|
||||
import de.dennisguse.opentracks.sensors.SensorManager;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataHeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
|
||||
import de.dennisguse.opentracks.services.handlers.TrackPointCreator;
|
||||
@@ -253,16 +255,16 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
SensorManager sensorManager = trackPointCreator.getSensorManager();
|
||||
|
||||
sensorManager.sensorDataSet.add(new SensorDataHeartRate("", ""));
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(sensor1);
|
||||
|
||||
sensorManager.onChanged(new SensorDataHeartRate("", "", HeartRate.of(5))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(HeartRate.of(5))); //Should be ignored
|
||||
|
||||
String sensor3 = "2020-02-02T02:02:13Z";
|
||||
trackPointCreator.setClock(sensor3);
|
||||
sensorManager.onChanged(new SensorDataHeartRate("", "", HeartRate.of(7)));
|
||||
sensorManager.onChanged(new Raw<>(HeartRate.of(7)));
|
||||
|
||||
String stopTime = "2020-02-02T02:02:15Z";
|
||||
trackPointCreator.setClock(stopTime);
|
||||
@@ -590,16 +592,17 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Track.Id trackId = service.startNewTrack();
|
||||
trackPointCreator.getSensorManager().setAltitudeSumManager(altitudeSumManager);
|
||||
SensorManager sensorManager = trackPointCreator.getSensorManager();
|
||||
sensorManager.sensorDataSet.add(new SensorDataRunning("", ""));
|
||||
|
||||
// when
|
||||
String sensor1 = "2020-02-02T02:02:03Z";
|
||||
trackPointCreator.setClock(sensor1);
|
||||
sensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(0))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(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 SensorDataRunning("", "", Speed.of(5), null, Distance.of(2)));
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(2))));
|
||||
|
||||
// when
|
||||
String gps1 = "2020-02-02T02:02:05Z";
|
||||
@@ -608,12 +611,12 @@ public class TrackRecordingServiceRecordingTest {
|
||||
// when
|
||||
String sensor3 = "2020-02-02T02:02:06Z";
|
||||
trackPointCreator.setClock(sensor3);
|
||||
sensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(12)));
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(12))));
|
||||
|
||||
// when
|
||||
String sensor4 = "2020-02-02T02:02:07Z";
|
||||
trackPointCreator.setClock(sensor4);
|
||||
sensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(14))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(14)))); //Should be ignored
|
||||
|
||||
// when
|
||||
String gps2 = "2020-02-02T02:02:08Z";
|
||||
@@ -622,7 +625,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
// when
|
||||
String sensor5 = "2020-02-02T02:02:10Z";
|
||||
trackPointCreator.setClock(sensor5);
|
||||
sensorManager.onChanged(new SensorDataRunning("", "", Speed.of(5), null, Distance.of(16))); //Should be ignored
|
||||
sensorManager.onChanged(new Raw<>(new BluetoothHandlerRunningSpeedAndCadence.Data(Speed.of(5), null, Distance.of(16)))); //Should be ignored
|
||||
|
||||
// when
|
||||
String gps3 = "2020-02-02T02:02:12Z";
|
||||
|
||||
@@ -33,7 +33,6 @@ import androidx.annotation.NonNull;
|
||||
import java.util.Optional;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorData;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
/**
|
||||
@@ -140,8 +139,7 @@ public class BluetoothConnectionManager {
|
||||
|
||||
bluetoothGatt = device.connectGatt(context, false, connectCallback, BluetoothDevice.TRANSPORT_AUTO, 0, handler);
|
||||
|
||||
SensorData<?> sensorData = sensorHandler.createEmptySensorData(bluetoothGatt.getDevice().getAddress());
|
||||
observer.onChange(sensorData);
|
||||
observer.onConnect(sensorHandler.createEmptySensorData(bluetoothGatt.getDevice().getAddress()));
|
||||
}
|
||||
|
||||
private synchronized void clearData() {
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ public class BluetoothHandlerBarometricPressure implements SensorHandlerInterfac
|
||||
}
|
||||
|
||||
@Override
|
||||
public SensorData<?> createEmptySensorData(String address) {
|
||||
public SensorData<?, ?> createEmptySensorData(String address) {
|
||||
return null; //TODO
|
||||
}
|
||||
|
||||
|
||||
+18
-14
@@ -2,12 +2,12 @@ package de.dennisguse.opentracks.sensors;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
public class BluetoothHandlerCyclingCadence implements SensorHandlerInterface {
|
||||
@@ -30,24 +30,28 @@ public class BluetoothHandlerCyclingCadence implements SensorHandlerInterface {
|
||||
|
||||
@Override
|
||||
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
|
||||
|
||||
//TODO Implement to ServiceMeasurement.parse()?
|
||||
if (serviceMeasurementUUID.equals(BluetoothHandlerManagerCyclingPower.CYCLING_POWER)) {
|
||||
SensorDataCyclingPower.Data data = BluetoothHandlerManagerCyclingPower.parseCyclingPower(address, sensorName, characteristic);
|
||||
if (data!= null) {
|
||||
observer.onChange(data.cadence());
|
||||
}
|
||||
} else if (serviceMeasurementUUID.equals(BluetoothHandlerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE)) {
|
||||
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel(address, sensorName, characteristic);
|
||||
if (cadenceAndSpeed == null) {
|
||||
return;
|
||||
BluetoothHandlerManagerCyclingPower.Data data = BluetoothHandlerManagerCyclingPower.parseCyclingPower(characteristic);
|
||||
if (data != null && data.crank() != null) {
|
||||
observer.onChange(new Raw<>(data.crank()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (cadenceAndSpeed.getCadence() != null) {
|
||||
observer.onChange(cadenceAndSpeed.getCadence());
|
||||
if (serviceMeasurementUUID.equals(BluetoothHandlerCyclingDistanceSpeed.CYCLING_SPEED_CADENCE)) {
|
||||
Pair<BluetoothHandlerCyclingDistanceSpeed.WheelData, CrankData> data = BluetoothHandlerCyclingDistanceSpeed.parseCyclingCrankAndWheel(address, sensorName, characteristic);
|
||||
|
||||
if (data != null && data.second != null) {
|
||||
observer.onChange(new Raw<>(data.second));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Log.e(TAG, "Don't know how to decode this payload.");
|
||||
}
|
||||
|
||||
public record CrankData(
|
||||
long crankRevolutionsCount, // UINT32
|
||||
int crankRevolutionsTime // UINT16; 1/1024s
|
||||
) {}
|
||||
}
|
||||
|
||||
+19
-16
@@ -1,6 +1,7 @@
|
||||
package de.dennisguse.opentracks.sensors;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
@@ -8,8 +9,7 @@ import androidx.annotation.VisibleForTesting;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadenceAndDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
@@ -32,19 +32,15 @@ public class BluetoothHandlerCyclingDistanceSpeed implements SensorHandlerInterf
|
||||
|
||||
@Override
|
||||
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
|
||||
SensorDataCyclingCadenceAndDistanceSpeed cadenceAndSpeed = parseCyclingCrankAndWheel(address, sensorName, characteristic);
|
||||
if (cadenceAndSpeed == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (cadenceAndSpeed.getDistanceSpeed() != null) {
|
||||
observer.onChange(cadenceAndSpeed.getDistanceSpeed());
|
||||
Pair<WheelData, BluetoothHandlerCyclingCadence.CrankData> data = parseCyclingCrankAndWheel(address, sensorName, characteristic);
|
||||
if (data.first != null) {
|
||||
observer.onChange(new Raw<>(data.first));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public static SensorDataCyclingCadenceAndDistanceSpeed parseCyclingCrankAndWheel(String address, String sensorName, @NonNull BluetoothGattCharacteristic characteristic) {
|
||||
public static Pair<WheelData, BluetoothHandlerCyclingCadence.CrankData> parseCyclingCrankAndWheel(String address, String sensorName, @NonNull BluetoothGattCharacteristic characteristic) {
|
||||
// DOCUMENTATION https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.csc_measurement.xml
|
||||
int valueLength = characteristic.getValue().length;
|
||||
if (valueLength == 0) {
|
||||
@@ -56,24 +52,31 @@ public class BluetoothHandlerCyclingDistanceSpeed implements SensorHandlerInterf
|
||||
boolean hasCrank = (flags & 0x02) > 0;
|
||||
|
||||
int index = 1;
|
||||
SensorDataCyclingDistanceSpeed speed = null;
|
||||
WheelData wheelData = null;
|
||||
if (hasWheel && valueLength - index >= 6) {
|
||||
int wheelTotalRevolutionCount = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, index);
|
||||
long wheelTotalRevolutionCount = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, index);
|
||||
index += 4;
|
||||
int wheelTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index); // 1/1024s
|
||||
speed = new SensorDataCyclingDistanceSpeed(address, sensorName, wheelTotalRevolutionCount, wheelTime);
|
||||
wheelData = new WheelData(wheelTotalRevolutionCount, wheelTime);
|
||||
index += 2;
|
||||
}
|
||||
|
||||
SensorDataCyclingCadence cadence = null;
|
||||
BluetoothHandlerCyclingCadence.CrankData crankData = null;
|
||||
if (hasCrank && valueLength - index >= 4) {
|
||||
long crankCount = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index);
|
||||
index += 2;
|
||||
|
||||
int crankTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index); // 1/1024s
|
||||
cadence = new SensorDataCyclingCadence(address, sensorName, crankCount, crankTime);
|
||||
crankData = new BluetoothHandlerCyclingCadence.CrankData(crankCount, crankTime);
|
||||
}
|
||||
|
||||
return new SensorDataCyclingCadenceAndDistanceSpeed(address, sensorName, cadence, speed);
|
||||
return new Pair<>(wheelData, crankData);
|
||||
}
|
||||
|
||||
public record WheelData(
|
||||
|
||||
long wheelRevolutionsCount, // UINT32
|
||||
|
||||
int wheelRevolutionsTime // UINT16; 1/1024s
|
||||
) {}
|
||||
}
|
||||
|
||||
+10
-9
@@ -9,7 +9,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
@@ -32,16 +32,16 @@ public class BluetoothHandlerManagerCyclingPower implements SensorHandlerInterfa
|
||||
|
||||
@Override
|
||||
public void handlePayload(SensorManager.SensorDataChangedObserver observer, @NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
|
||||
SensorDataCyclingPower.Data cyclingPower = parseCyclingPower(address, sensorName, characteristic);
|
||||
Data cyclingPower = parseCyclingPower(characteristic);
|
||||
|
||||
if (cyclingPower != null) {
|
||||
observer.onChange(cyclingPower.power());
|
||||
observer.onChange(new Raw<>(cyclingPower));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@VisibleForTesting
|
||||
public static SensorDataCyclingPower.Data parseCyclingPower(String address, String sensorName, BluetoothGattCharacteristic characteristic) {
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
|
||||
public static Data parseCyclingPower(BluetoothGattCharacteristic characteristic) {
|
||||
// DOCUMENTATION https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.cycling_power_measurement.xml
|
||||
int valueLength = characteristic.getValue().length;
|
||||
if (valueLength == 0) {
|
||||
@@ -69,18 +69,19 @@ public class BluetoothHandlerManagerCyclingPower implements SensorHandlerInterfa
|
||||
index += 2 + 2;
|
||||
}
|
||||
|
||||
SensorDataCyclingCadence cadence = null;
|
||||
BluetoothHandlerCyclingCadence.CrankData crankData = null;
|
||||
if (hasCrank && valueLength - index >= 4) {
|
||||
long crankCount = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index);
|
||||
index += 2;
|
||||
|
||||
int crankTime = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT16, index); // 1/1024s
|
||||
|
||||
cadence = new SensorDataCyclingCadence(address, sensorName, crankCount, crankTime);
|
||||
crankData = new BluetoothHandlerCyclingCadence.CrankData(crankCount, crankTime);
|
||||
}
|
||||
|
||||
|
||||
return new SensorDataCyclingPower.Data(new SensorDataCyclingPower(sensorName, address, Power.of(instantaneousPower)), cadence);
|
||||
return new Data(Power.of(instantaneousPower), crankData);
|
||||
}
|
||||
|
||||
public record Data(Power power, BluetoothHandlerCyclingCadence.CrankData crank) {}
|
||||
|
||||
}
|
||||
|
||||
+2
-1
@@ -9,6 +9,7 @@ import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataHeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
@@ -44,7 +45,7 @@ public class BluetoothHandlerManagerHeartRate implements SensorHandlerInterface
|
||||
HeartRate heartRate = parseHeartRate(characteristic);
|
||||
|
||||
if (heartRate != null) {
|
||||
observer.onChange(new SensorDataHeartRate(address, sensorName, heartRate));
|
||||
observer.onChange(new Raw<>(heartRate));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+7
-3
@@ -11,6 +11,7 @@ import java.util.UUID;
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataRunning;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
@@ -34,11 +35,12 @@ public class BluetoothHandlerRunningSpeedAndCadence implements SensorHandlerInte
|
||||
|
||||
@Override
|
||||
public void handlePayload(SensorManager.SensorDataChangedObserver observer, @NonNull ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
|
||||
observer.onChange(parseRunningSpeedAndCadence(address, sensorName, characteristic));
|
||||
Data data = parseRunningSpeedAndCadence(sensorName, characteristic);
|
||||
observer.onChange(new Raw<>(data));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public static SensorDataRunning parseRunningSpeedAndCadence(String address, String sensorName, @NonNull BluetoothGattCharacteristic characteristic) {
|
||||
public static Data parseRunningSpeedAndCadence(String sensorName, @NonNull BluetoothGattCharacteristic characteristic) {
|
||||
// DOCUMENTATION https://www.bluetooth.com/wp-content/uploads/Sitecore-Media-Library/Gatt/Xml/Characteristics/org.bluetooth.characteristic.rsc_measurement.xml
|
||||
int valueLength = characteristic.getValue().length;
|
||||
if (valueLength == 0) {
|
||||
@@ -79,6 +81,8 @@ public class BluetoothHandlerRunningSpeedAndCadence implements SensorHandlerInte
|
||||
totalDistance = Distance.ofDM(characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_UINT32, index));
|
||||
}
|
||||
|
||||
return new SensorDataRunning(address, sensorName, speed, cadence, totalDistance);
|
||||
return new Data(speed, cadence, totalDistance);
|
||||
}
|
||||
|
||||
public record Data(Speed speed, Cadence cadence, Distance totalDistance) {}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ public class BluetoothRemoteSensorManager implements SensorConnector, SharedPref
|
||||
|
||||
private static final String TAG = BluetoothRemoteSensorManager.class.getSimpleName();
|
||||
|
||||
public static final Duration MAX_SENSOR_DATE_SET_AGE = Duration.ofSeconds(5);
|
||||
public static final Duration MAX_SENSOR_DATE_SET_AGE = Duration.ofSeconds(50); //TODO
|
||||
|
||||
private final BluetoothAdapter bluetoothAdapter;
|
||||
private final Context context;
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorData;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataSet;
|
||||
import de.dennisguse.opentracks.services.handlers.GPSManager;
|
||||
@@ -27,13 +28,19 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
private final SensorDataChangedObserver listener = new SensorDataChangedObserver() {
|
||||
|
||||
@Override
|
||||
public void onChange(SensorData<?> sensorData) {
|
||||
sensorDataSet.set(sensorData);
|
||||
public void onConnect(SensorData<?, ?> sensorData) {
|
||||
sensorDataSet.add(sensorData);
|
||||
observer.onChange(new SensorDataSet(sensorDataSet));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect(SensorData<?> sensorData) {
|
||||
public void onChange(Raw<?> sensorData) {
|
||||
sensorDataSet.update(sensorData);
|
||||
observer.onChange(new SensorDataSet(sensorDataSet));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect(SensorData<?, ?> sensorData) {
|
||||
sensorDataSet.remove(sensorData);
|
||||
observer.onChange(new SensorDataSet(sensorDataSet));
|
||||
}
|
||||
@@ -91,7 +98,7 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
|
||||
@Deprecated
|
||||
@VisibleForTesting
|
||||
public void onChanged(SensorData<?> data) {
|
||||
public void onChanged(Raw<?> data) {
|
||||
listener.onChange(data);
|
||||
}
|
||||
|
||||
@@ -120,8 +127,10 @@ public class SensorManager implements SharedPreferences.OnSharedPreferenceChange
|
||||
}
|
||||
|
||||
public interface SensorDataChangedObserver {
|
||||
void onChange(SensorData<?> sensorData);
|
||||
|
||||
void onDisconnect(SensorData<?> sensorData);
|
||||
void onConnect(SensorData<?, ?> sensorData);
|
||||
void onChange(Raw<?> sensorData);
|
||||
|
||||
void onDisconnect(SensorData<?, ?> sensorData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public record Raw<T extends Record>(
|
||||
@NonNull T value,
|
||||
|
||||
@NonNull Instant time
|
||||
) {
|
||||
public Raw(@NonNull T value) {
|
||||
this(value, Instant.now()); //TODO We should be using the MonotonicClock
|
||||
}
|
||||
}
|
||||
@@ -1,48 +1,48 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager;
|
||||
|
||||
public abstract class SensorData<T> {
|
||||
public abstract class SensorData<Input extends Record, Output> {
|
||||
|
||||
protected T value;
|
||||
protected Raw<Input> previous;
|
||||
|
||||
protected Output value;
|
||||
|
||||
private final String sensorAddress;
|
||||
private final String sensorName;
|
||||
|
||||
private final Instant time;
|
||||
|
||||
SensorData(String sensorAddress) {
|
||||
this(sensorAddress, null);
|
||||
}
|
||||
|
||||
SensorData(String sensorAddress, String sensorName) {
|
||||
this(sensorAddress, sensorName, Instant.now());
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
SensorData(String sensorAddress, String sensorName, Instant time) {
|
||||
this.sensorAddress = sensorAddress;
|
||||
this.sensorName = sensorName;
|
||||
this.time = time;
|
||||
}
|
||||
|
||||
public String getSensorNameOrAddress() {
|
||||
return sensorName != null ? sensorName : sensorAddress;
|
||||
}
|
||||
|
||||
public final void add(Raw<Input> current) {
|
||||
computeValue(current);
|
||||
previous = current;
|
||||
}
|
||||
|
||||
protected abstract void computeValue(Raw<Input> current);
|
||||
|
||||
public boolean hasValue() {
|
||||
return value != null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract T getNoneValue();
|
||||
protected abstract Output getNoneValue();
|
||||
|
||||
public T getValue() {
|
||||
public Output getValue() {
|
||||
if (!hasValue()) {
|
||||
return null;
|
||||
}
|
||||
@@ -55,20 +55,23 @@ public abstract class SensorData<T> {
|
||||
/**
|
||||
* Reset long term aggregated values (more than derived from previous SensorData). e.g. overall distance.
|
||||
*/
|
||||
public void reset() {
|
||||
}
|
||||
public void reset() {};
|
||||
|
||||
/**
|
||||
* Is the data recent considering the current time.
|
||||
*/
|
||||
private boolean isRecent() {
|
||||
if (previous == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Instant.now()
|
||||
.isBefore(time.plus(BluetoothRemoteSensorManager.MAX_SENSOR_DATE_SET_AGE));
|
||||
.isBefore(previous.time().plus(BluetoothRemoteSensorManager.MAX_SENSOR_DATE_SET_AGE));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "sensorAddress='" + sensorAddress;
|
||||
return "sensorAddress=" + sensorAddress + " data=" + value;
|
||||
}
|
||||
}
|
||||
|
||||
+10
-45
@@ -3,53 +3,29 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.UintUtils;
|
||||
|
||||
public class SensorDataCyclingCadence extends SensorData<Cadence> {
|
||||
public class SensorDataCyclingCadence extends SensorData<BluetoothHandlerCyclingCadence.CrankData, Cadence> {
|
||||
|
||||
private final String TAG = SensorDataCyclingCadence.class.getSimpleName();
|
||||
|
||||
private final Long crankRevolutionsCount; // UINT32
|
||||
private final Integer crankRevolutionsTime; // UINT16; 1/1024s
|
||||
|
||||
public SensorDataCyclingCadence(String sensorAddress) {
|
||||
super(sensorAddress);
|
||||
this.crankRevolutionsCount = null;
|
||||
this.crankRevolutionsTime = null;
|
||||
}
|
||||
|
||||
public SensorDataCyclingCadence(String sensorAddress, String sensorName, long crankRevolutionsCount, int crankRevolutionsTime) {
|
||||
public SensorDataCyclingCadence(String sensorAddress, String sensorName) {
|
||||
super(sensorAddress, sensorName);
|
||||
this.crankRevolutionsCount = crankRevolutionsCount;
|
||||
this.crankRevolutionsTime = crankRevolutionsTime;
|
||||
}
|
||||
|
||||
public boolean hasData() {
|
||||
return crankRevolutionsCount != null && crankRevolutionsTime != null;
|
||||
}
|
||||
|
||||
public long getCrankRevolutionsCount() {
|
||||
return crankRevolutionsCount;
|
||||
}
|
||||
|
||||
public int getCrankRevolutionsTime() {
|
||||
return crankRevolutionsTime;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Cadence getNoneValue() {
|
||||
return Cadence.of(0);
|
||||
}
|
||||
|
||||
public void compute(SensorDataCyclingCadence previous) {
|
||||
if (hasData() && previous != null && previous.hasData()) {
|
||||
float timeDiff_ms = UintUtils.diff(crankRevolutionsTime, previous.crankRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * 1000;
|
||||
protected void computeValue(Raw<BluetoothHandlerCyclingCadence.CrankData> current) {
|
||||
if (previous != null) {
|
||||
float timeDiff_ms = UintUtils.diff(current.value().crankRevolutionsTime(), previous.value().crankRevolutionsTime(), UintUtils.UINT16_MAX) / 1024f * 1000;
|
||||
Duration timeDiff = Duration.ofMillis((long) timeDiff_ms);
|
||||
if (timeDiff.isZero() || timeDiff.isNegative()) {
|
||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
||||
@@ -58,30 +34,19 @@ public class SensorDataCyclingCadence extends SensorData<Cadence> {
|
||||
}
|
||||
|
||||
// TODO We have to treat with overflow according to the documentation: read https://github.com/OpenTracksApp/OpenTracks/pull/953#discussion_r711625268
|
||||
if (crankRevolutionsCount < previous.crankRevolutionsCount) {
|
||||
if (current.value().crankRevolutionsCount() < previous.value().crankRevolutionsCount()) {
|
||||
Log.e(TAG, "Crank revolutions count difference is invalid: cannot compute cadence.");
|
||||
return;
|
||||
}
|
||||
|
||||
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
||||
long crankDiff = UintUtils.diff(current.value().crankRevolutionsCount(), previous.value().crankRevolutionsCount(), UintUtils.UINT32_MAX);
|
||||
value = Cadence.of(crankDiff, timeDiff);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " cadence=" + value + " time=" + crankRevolutionsTime + " count=" + crankRevolutionsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof SensorDataCyclingCadence comp)) return false;
|
||||
|
||||
if (hasData() && comp.hasData() == hasData()) {
|
||||
return getCrankRevolutionsCount() == comp.getCrankRevolutionsCount() && getCrankRevolutionsTime() == comp.getCrankRevolutionsTime();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
protected Cadence getNoneValue() {
|
||||
return Cadence.of(0);
|
||||
}
|
||||
}
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.core.util.Pair;
|
||||
|
||||
public class SensorDataCyclingCadenceAndDistanceSpeed extends SensorData<Pair<SensorDataCyclingCadence, SensorDataCyclingDistanceSpeed>> {
|
||||
|
||||
public SensorDataCyclingCadenceAndDistanceSpeed(String sensorAddress, String sensorName, @Nullable SensorDataCyclingCadence cadence, @Nullable SensorDataCyclingDistanceSpeed distanceSpeed) {
|
||||
super(sensorAddress, sensorName);
|
||||
this.value = new Pair<>(cadence, distanceSpeed);
|
||||
}
|
||||
|
||||
public SensorDataCyclingCadence getCadence() {
|
||||
return this.value != null ? this.value.first : null;
|
||||
}
|
||||
|
||||
public SensorDataCyclingDistanceSpeed getDistanceSpeed() {
|
||||
return this.value != null ? this.value.second : null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Pair<SensorDataCyclingCadence, SensorDataCyclingDistanceSpeed> getNoneValue() {
|
||||
return new Pair<>(null, null);
|
||||
}
|
||||
}
|
||||
+21
-49
@@ -3,58 +3,32 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.UintUtils;
|
||||
|
||||
public class SensorDataCyclingDistanceSpeed extends SensorData<SensorDataCyclingDistanceSpeed.Data> {
|
||||
public class SensorDataCyclingDistanceSpeed extends SensorData<BluetoothHandlerCyclingDistanceSpeed.WheelData, SensorDataCyclingDistanceSpeed.Data> {
|
||||
|
||||
private final String TAG = SensorDataCyclingDistanceSpeed.class.getSimpleName();
|
||||
|
||||
private final Long wheelRevolutionsCount; // UINT32
|
||||
private final Integer wheelRevolutionsTime; // UINT16; 1/1024s
|
||||
private Distance wheelCircumference;
|
||||
|
||||
public SensorDataCyclingDistanceSpeed(String sensorAddress) {
|
||||
super(sensorAddress);
|
||||
this.wheelRevolutionsCount = null;
|
||||
this.wheelRevolutionsTime = null;
|
||||
}
|
||||
|
||||
public SensorDataCyclingDistanceSpeed(String sensorAddress, String sensorName, long wheelRevolutionsCount, int wheelRevolutionsTime) {
|
||||
public SensorDataCyclingDistanceSpeed(String sensorAddress, String sensorName) {
|
||||
super(sensorAddress, sensorName);
|
||||
this.wheelRevolutionsCount = wheelRevolutionsCount;
|
||||
this.wheelRevolutionsTime = wheelRevolutionsTime;
|
||||
}
|
||||
|
||||
public boolean hasData() {
|
||||
return wheelRevolutionsCount != null && wheelRevolutionsTime != null;
|
||||
}
|
||||
|
||||
public long getWheelRevolutionsCount() {
|
||||
return wheelRevolutionsCount;
|
||||
}
|
||||
|
||||
public int getWheelRevolutionsTime() {
|
||||
return wheelRevolutionsTime;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Data getNoneValue() {
|
||||
if (value != null) {
|
||||
return new Data(value.distance, value.distanceOverall, Speed.zero());
|
||||
} else {
|
||||
return new Data(Distance.of(0), Distance.of(0), Speed.zero());
|
||||
}
|
||||
}
|
||||
|
||||
public void compute(SensorDataCyclingDistanceSpeed previous, Distance wheelCircumference) {
|
||||
if (hasData() && previous != null && previous.hasData()) {
|
||||
float timeDiff_ms = UintUtils.diff(wheelRevolutionsTime, previous.wheelRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * 1000;
|
||||
protected void computeValue(Raw<BluetoothHandlerCyclingDistanceSpeed.WheelData> current) {
|
||||
if (previous != null) {
|
||||
float timeDiff_ms = UintUtils.diff(current.value().wheelRevolutionsTime(), previous.value().wheelRevolutionsTime(), UintUtils.UINT16_MAX) / 1024f * 1000;
|
||||
Duration timeDiff = Duration.ofMillis((long) timeDiff_ms);
|
||||
if (timeDiff.isZero() || timeDiff.isNegative()) {
|
||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute speed.");
|
||||
@@ -62,16 +36,16 @@ public class SensorDataCyclingDistanceSpeed extends SensorData<SensorDataCycling
|
||||
return;
|
||||
}
|
||||
|
||||
if (wheelRevolutionsCount < previous.wheelRevolutionsCount) {
|
||||
if (current.value().wheelRevolutionsCount() < previous.value().wheelRevolutionsCount()) {
|
||||
Log.e(TAG, "Wheel revolutions count difference is invalid: cannot compute speed.");
|
||||
return;
|
||||
}
|
||||
long wheelDiff = UintUtils.diff(wheelRevolutionsCount, previous.wheelRevolutionsCount, UintUtils.UINT32_MAX);
|
||||
long wheelDiff = UintUtils.diff(current.value().wheelRevolutionsCount(), previous.value().wheelRevolutionsCount(), UintUtils.UINT32_MAX);
|
||||
|
||||
Distance distance = wheelCircumference.multipliedBy(wheelDiff);
|
||||
Distance distanceOverall = distance;
|
||||
if (previous.hasValue()) {
|
||||
distanceOverall = distance.plus(previous.getValue().distanceOverall);
|
||||
if (value != null) {
|
||||
distanceOverall = distance.plus(value.distanceOverall);
|
||||
}
|
||||
Speed speed_mps = Speed.of(distance, timeDiff);
|
||||
value = new Data(distance, distanceOverall, speed_mps);
|
||||
@@ -87,21 +61,19 @@ public class SensorDataCyclingDistanceSpeed extends SensorData<SensorDataCycling
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " data=" + value + " time=" + wheelRevolutionsTime + " count=" + wheelRevolutionsCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (!(obj instanceof SensorDataCyclingDistanceSpeed comp)) return false;
|
||||
|
||||
if (!(hasData() && comp.hasData())) {
|
||||
return false;
|
||||
protected Data getNoneValue() {
|
||||
if (value != null) {
|
||||
return new Data(value.distance, value.distanceOverall, Speed.zero());
|
||||
} else {
|
||||
return new Data(Distance.of(0), Distance.of(0), Speed.zero());
|
||||
}
|
||||
|
||||
return getWheelRevolutionsCount() == comp.getWheelRevolutionsCount() && getWheelRevolutionsTime() == comp.getWheelRevolutionsTime();
|
||||
}
|
||||
|
||||
public void setWheelCircumference(Distance wheelCircumference) {
|
||||
this.wheelCircumference = wheelCircumference;
|
||||
}
|
||||
|
||||
// TODO Make record
|
||||
public static class Data {
|
||||
private final Distance distance;
|
||||
private final Distance distanceOverall;
|
||||
|
||||
+7
-26
@@ -1,19 +1,22 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
|
||||
public class SensorDataCyclingPower extends SensorData<Power> {
|
||||
public class SensorDataCyclingPower extends SensorData<Power, Power> {
|
||||
|
||||
public SensorDataCyclingPower(String address) {
|
||||
super(address);
|
||||
}
|
||||
|
||||
public SensorDataCyclingPower(String name, String address, Power power) {
|
||||
public SensorDataCyclingPower(String name, String address) {
|
||||
super(name, address);
|
||||
this.value = power;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void computeValue(Raw<Power> current) {
|
||||
this.value = current.value();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -21,26 +24,4 @@ public class SensorDataCyclingPower extends SensorData<Power> {
|
||||
protected Power getNoneValue() {
|
||||
return Power.of(0f);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " data=" + value;
|
||||
}
|
||||
|
||||
public record Data(SensorDataCyclingPower power, SensorDataCyclingCadence cadence) {
|
||||
public Data(SensorDataCyclingPower power, @Nullable SensorDataCyclingCadence cadence) {
|
||||
this.power = power;
|
||||
this.cadence = cadence;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Data{" +
|
||||
"power=" + power +
|
||||
", cadence=" + cadence +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,21 +4,19 @@ import androidx.annotation.NonNull;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
|
||||
public class SensorDataHeartRate extends SensorData<HeartRate> {
|
||||
public class SensorDataHeartRate extends SensorData<HeartRate, HeartRate> {
|
||||
|
||||
public SensorDataHeartRate(String address) {
|
||||
super(address);
|
||||
}
|
||||
|
||||
public SensorDataHeartRate(String name, String address, @NonNull HeartRate heartRate) {
|
||||
public SensorDataHeartRate(String name, String address) {
|
||||
super(name, address);
|
||||
this.value = heartRate;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.toString() + " heart=" + value;
|
||||
protected void computeValue(Raw<HeartRate> current) {
|
||||
this.value = current.value();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
||||
@@ -1,56 +1,48 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Cadence;
|
||||
import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerRunningSpeedAndCadence;
|
||||
|
||||
/**
|
||||
* Provides cadence in rpm and speed in milliseconds from Bluetooth LE Running Speed and Cadence sensors.
|
||||
*/
|
||||
public final class SensorDataRunning extends SensorData<SensorDataRunning.Data> {
|
||||
public final class SensorDataRunning extends SensorData<BluetoothHandlerRunningSpeedAndCadence.Data, SensorDataRunning.Data> {
|
||||
|
||||
private static final String TAG = SensorDataRunning.class.getSimpleName();
|
||||
|
||||
private final Speed speed;
|
||||
|
||||
private final Cadence cadence;
|
||||
|
||||
private final Distance totalDistance;
|
||||
|
||||
public SensorDataRunning(String sensorAddress) {
|
||||
super(sensorAddress);
|
||||
this.speed = null;
|
||||
this.cadence = null;
|
||||
this.totalDistance = null;
|
||||
}
|
||||
|
||||
public SensorDataRunning(String sensorAddress, String sensorName, Speed speed, Cadence cadence, Distance totalDistance) {
|
||||
public SensorDataRunning(String sensorAddress, String sensorName) {
|
||||
super(sensorAddress, sensorName);
|
||||
this.speed = speed;
|
||||
this.cadence = cadence;
|
||||
this.totalDistance = totalDistance;
|
||||
}
|
||||
|
||||
private boolean hasTotalDistance() {
|
||||
return totalDistance != null;
|
||||
@Override
|
||||
public void computeValue(Raw<BluetoothHandlerRunningSpeedAndCadence.Data> current) {
|
||||
if (previous != null) {
|
||||
|
||||
Distance distance = null;
|
||||
if (previous.value().totalDistance() != null && current.value().totalDistance() != null) {
|
||||
distance = current.value().totalDistance().minus(previous.value().totalDistance());
|
||||
if (value != null) {
|
||||
distance = distance.plus(value.distance);
|
||||
}
|
||||
}
|
||||
|
||||
value = new Data(current.value().speed(), current.value().cadence(), distance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Cadence getCadence() {
|
||||
return cadence;
|
||||
}
|
||||
|
||||
public Speed getSpeed() {
|
||||
return speed;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public Distance getTotalDistance() {
|
||||
return totalDistance;
|
||||
@Override
|
||||
public void reset() {
|
||||
if (value != null) {
|
||||
value = new Data(value.speed, value.cadence, Distance.of(0));
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -63,27 +55,7 @@ public final class SensorDataRunning extends SensorData<SensorDataRunning.Data>
|
||||
}
|
||||
}
|
||||
|
||||
public void compute(SensorDataRunning previous) {
|
||||
if (speed != null && hasTotalDistance()) {
|
||||
Distance overallDistance = null;
|
||||
if (previous != null && previous.hasTotalDistance()) {
|
||||
overallDistance = this.totalDistance.minus(previous.totalDistance);
|
||||
if (previous.hasValue() && previous.getValue().distance() != null) {
|
||||
overallDistance = overallDistance.plus(previous.getValue().distance());
|
||||
}
|
||||
}
|
||||
|
||||
value = new Data(speed, cadence, overallDistance);
|
||||
}
|
||||
public record Data(Speed speed, Cadence cadence, @NonNull Distance distance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
if (value != null) {
|
||||
value = new Data(value.speed, value.cadence, Distance.of(0));
|
||||
}
|
||||
}
|
||||
|
||||
public record Data(Speed speed, Cadence cadence, @Nullable Distance distance) {}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +1,40 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
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.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerManagerCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerRunningSpeedAndCadence;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
public final class SensorDataSet {
|
||||
|
||||
private static final String TAG = SensorDataSet.class.getSimpleName();
|
||||
|
||||
private SensorDataHeartRate heartRate;
|
||||
@VisibleForTesting
|
||||
public SensorDataHeartRate heartRate;
|
||||
|
||||
private SensorDataCyclingCadence cyclingCadence;
|
||||
@VisibleForTesting
|
||||
public SensorDataCyclingCadence cyclingCadence;
|
||||
|
||||
private SensorDataCyclingDistanceSpeed cyclingDistanceSpeed;
|
||||
@VisibleForTesting
|
||||
public SensorDataCyclingDistanceSpeed cyclingDistanceSpeed;
|
||||
|
||||
private SensorDataCyclingPower cyclingPower;
|
||||
@VisibleForTesting
|
||||
public SensorDataCyclingPower cyclingPower;
|
||||
|
||||
private SensorDataRunning runningDistanceSpeedCadence;
|
||||
@VisibleForTesting
|
||||
public SensorDataRunning runningDistanceSpeedCadence;
|
||||
|
||||
public SensorDataSet() {
|
||||
}
|
||||
@@ -51,8 +60,8 @@ public final class SensorDataSet {
|
||||
return new Pair<>(cyclingCadence.getValue(), cyclingCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null) {
|
||||
return new Pair<>(runningDistanceSpeedCadence.getCadence(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasValue() && runningDistanceSpeedCadence.value.cadence() != null) {
|
||||
return new Pair<>(runningDistanceSpeedCadence.value.cadence(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -64,33 +73,51 @@ public final class SensorDataSet {
|
||||
}
|
||||
|
||||
if (runningDistanceSpeedCadence != null && runningDistanceSpeedCadence.hasValue() && runningDistanceSpeedCadence.getValue().speed() != null) {
|
||||
return new Pair<>(runningDistanceSpeedCadence.getSpeed(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
return new Pair<>(runningDistanceSpeedCadence.value.speed(), runningDistanceSpeedCadence.getSensorNameOrAddress());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public SensorDataCyclingCadence getCyclingCadence() {
|
||||
return cyclingCadence;
|
||||
}
|
||||
|
||||
public SensorDataCyclingDistanceSpeed getCyclingDistanceSpeed() {
|
||||
return cyclingDistanceSpeed;
|
||||
}
|
||||
|
||||
public SensorDataCyclingPower getCyclingPower() {
|
||||
return cyclingPower;
|
||||
}
|
||||
|
||||
public SensorDataRunning getRunningDistanceSpeedCadence() {
|
||||
return runningDistanceSpeedCadence;
|
||||
}
|
||||
|
||||
public void set(SensorData<?> data) {
|
||||
public void add(@NonNull SensorData<?, ?> data) {
|
||||
set(data, data);
|
||||
}
|
||||
|
||||
public void remove(SensorData<?> type) {
|
||||
public void update(@NonNull Raw<?> data) {
|
||||
Record value = data.value();
|
||||
|
||||
if (value instanceof HeartRate) {
|
||||
this.heartRate.add((Raw<HeartRate>) 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 BluetoothHandlerManagerCyclingPower.Data) {
|
||||
this.cyclingPower.add((Raw<Power>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException(data.getClass().getCanonicalName());
|
||||
}
|
||||
|
||||
public void remove(@NonNull SensorData<?, ?> type) {
|
||||
set(type, null);
|
||||
}
|
||||
|
||||
@@ -136,71 +163,25 @@ public final class SensorDataSet {
|
||||
if (runningDistanceSpeedCadence != null) runningDistanceSpeedCadence.reset();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return (heartRate != null ? "" + heartRate : "")
|
||||
+ (cyclingCadence != null ? " " + cyclingCadence : "")
|
||||
+ (cyclingDistanceSpeed != null ? " " + cyclingDistanceSpeed : "")
|
||||
+ (cyclingPower != null ? " " + cyclingPower : "")
|
||||
+ (runningDistanceSpeedCadence != null ? " " + runningDistanceSpeedCadence : "");
|
||||
}
|
||||
|
||||
private void set(@NonNull SensorData<?> type, @Nullable SensorData<?> sensorData) {
|
||||
if (type instanceof SensorDataHeartRate) {
|
||||
this.heartRate = (SensorDataHeartRate) sensorData;
|
||||
private void set(@NonNull SensorData<?, ?> type, @Nullable SensorData<?, ?> sensorData) {
|
||||
if (type instanceof SensorDataHeartRate hr) {
|
||||
heartRate = hr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type instanceof SensorDataCyclingCadence) {
|
||||
SensorDataCyclingCadence previous = getCyclingCadence();
|
||||
Log.d(TAG, "Previous: " + previous + "; current: " + sensorData);
|
||||
|
||||
if (sensorData != null && sensorData.equals(previous)) {
|
||||
Log.d(TAG, "onChanged: cadence data repeated.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.cyclingCadence = (SensorDataCyclingCadence) sensorData;
|
||||
if (this.cyclingCadence != null) {
|
||||
this.cyclingCadence.compute(previous);
|
||||
}
|
||||
if (type instanceof SensorDataCyclingCadence cc) {
|
||||
cyclingCadence = cc;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type instanceof SensorDataCyclingDistanceSpeed) {
|
||||
SensorDataCyclingDistanceSpeed previous = getCyclingDistanceSpeed();
|
||||
Log.d(TAG, "Previous: " + previous + "; Current" + sensorData);
|
||||
if (sensorData != null && 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;
|
||||
if (this.cyclingDistanceSpeed != null) {
|
||||
this.cyclingDistanceSpeed.compute(previous, preferenceWheelCircumference);
|
||||
}
|
||||
if (type instanceof SensorDataCyclingDistanceSpeed ds) {
|
||||
cyclingDistanceSpeed = ds;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type instanceof SensorDataCyclingPower) {
|
||||
this.cyclingPower = (SensorDataCyclingPower) sensorData;
|
||||
if (type instanceof SensorDataCyclingPower cp) {
|
||||
cyclingPower = cp;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type instanceof SensorDataRunning) {
|
||||
SensorDataRunning previous = getRunningDistanceSpeedCadence();
|
||||
Log.d(TAG, "Previous: " + previous + "; Current" + sensorData);
|
||||
if (sensorData != null && sensorData.equals(previous)) {
|
||||
Log.d(TAG, "onChanged: running speed data repeated.");
|
||||
return;
|
||||
}
|
||||
|
||||
this.runningDistanceSpeedCadence = (SensorDataRunning) sensorData;
|
||||
if (this.runningDistanceSpeedCadence != null) {
|
||||
this.runningDistanceSpeedCadence.compute(previous);
|
||||
}
|
||||
if (type instanceof SensorDataRunning rr) {
|
||||
runningDistanceSpeedCadence = rr;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ public interface SensorHandlerInterface {
|
||||
|
||||
List<ServiceMeasurementUUID> getServices();
|
||||
|
||||
SensorData<?> createEmptySensorData(String address);
|
||||
SensorData<?, ?> createEmptySensorData(String address);
|
||||
|
||||
void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user