mirror of
https://codeberg.org/OpenTracksApp/OpenTracks.git
synced 2026-09-30 16:52:21 +02:00
@@ -132,6 +132,7 @@ public class TestDataUtil {
|
||||
),
|
||||
null,
|
||||
HeartRate.of(100f + i % 80),
|
||||
null,
|
||||
Cadence.of(300f + i),
|
||||
Power.of(400f + i),
|
||||
altitudeGainLoss
|
||||
|
||||
@@ -39,6 +39,7 @@ public class TestSensorDataUtil {
|
||||
),
|
||||
null,
|
||||
HeartRate.ofOrNull(hr),
|
||||
null,
|
||||
cadence != null ? Cadence.of(cadence) : null,
|
||||
power != null ? Power.of(power) : null,
|
||||
new AltitudeGainLoss(3, 3)
|
||||
|
||||
@@ -812,6 +812,7 @@ public class CustomContentProviderUtilsTest {
|
||||
TestDataUtil.createTrackPoint(5).position(),
|
||||
null,
|
||||
HeartRate.of(1),
|
||||
null,
|
||||
Cadence.of(2),
|
||||
Power.of(3),
|
||||
null
|
||||
@@ -896,6 +897,7 @@ public class CustomContentProviderUtilsTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ public class TrackPointTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
@@ -105,6 +106,7 @@ public class TrackPointTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
// tp2 has sensor distance
|
||||
@@ -129,6 +131,7 @@ public class TrackPointTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
@@ -148,6 +151,7 @@ public class TrackPointTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
// tp1 and tp2 have sensor distance
|
||||
|
||||
+37
-9
@@ -60,6 +60,7 @@ import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackBuilder;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
@@ -72,6 +73,7 @@ import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorCyclingPower;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorHeartRate;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorTemperature;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorDataAggregator;
|
||||
import de.dennisguse.opentracks.services.TrackRecordingService;
|
||||
@@ -173,14 +175,14 @@ public class ExportImportTest {
|
||||
|
||||
// A sensor-only TrackPoint
|
||||
trackPointCreator.setClock("2020-02-02T02:02:04Z");
|
||||
mockSensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f, 1f);
|
||||
mockSensorData(trackPointCreator, 15f, sensorDistance, 66f, 3f, 50f, 1f, 27);
|
||||
|
||||
trackPointCreator.setClock("2020-02-02T02:02:14Z"); //ignored
|
||||
mockSensorData(trackPointCreator, 15f, null, 67f, 3f, 50f, null);
|
||||
mockSensorData(trackPointCreator, 15f, null, 67f, 3f, 50f, null, 28);
|
||||
trackPointCreator.setClock("2020-02-02T02:02:15Z");
|
||||
mockSensorData(trackPointCreator, null, null, 68f, 3f, 50f, null);
|
||||
mockSensorData(trackPointCreator, null, null, 68f, 3f, 50f, null, 29);
|
||||
trackPointCreator.setClock("2020-02-02T02:02:16Z");
|
||||
mockSensorData(trackPointCreator, 5f, Distance.of(2), 69f, 3f, 50f, null); // Distance will be added to next TrackPoint
|
||||
mockSensorData(trackPointCreator, 5f, Distance.of(2), 69f, 3f, 50f, null, 30); //Distance will be added to next TrackPoint
|
||||
|
||||
sendLocation(trackPointCreator, "2020-02-02T02:02:17Z", 3.1234567, 14.0014567, 10, 13, 15, 1020.25, 0f);
|
||||
contentProviderUtils.insertMarker(
|
||||
@@ -248,6 +250,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(1, 1)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -261,6 +264,7 @@ public class ExportImportTest {
|
||||
Speed.of(15)),
|
||||
Distance.of(10),
|
||||
HeartRate.of(66),
|
||||
Temperature.of(27),
|
||||
Cadence.of(3),
|
||||
Power.of(50),
|
||||
new AltitudeGainLoss(1, 1)
|
||||
@@ -271,6 +275,7 @@ public class ExportImportTest {
|
||||
Position.of(Instant.parse("2020-02-02T02:02:15Z")),
|
||||
null,
|
||||
HeartRate.of(68),
|
||||
Temperature.of(29),
|
||||
Cadence.of(3),
|
||||
Power.of(50),
|
||||
null
|
||||
@@ -286,6 +291,7 @@ public class ExportImportTest {
|
||||
Speed.of(5)),
|
||||
Distance.of(2),
|
||||
HeartRate.of(69),
|
||||
Temperature.of(30),
|
||||
Cadence.of(3),
|
||||
Power.of(50),
|
||||
new AltitudeGainLoss(0, 0)
|
||||
@@ -305,6 +311,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -319,6 +326,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -329,6 +337,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -343,6 +352,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_END_MANUAL, Instant.parse("2020-02-02T02:04:00Z"))
|
||||
), actual);
|
||||
@@ -365,7 +375,7 @@ public class ExportImportTest {
|
||||
//TODO Does not test marker images
|
||||
@LargeTest
|
||||
@Test
|
||||
public void kmz_with_trackdetail_and_sensordata() throws TimeoutException, IOException {
|
||||
public void kmz_with_trackdetail_and_sensordata() throws IOException {
|
||||
// given
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
@@ -417,7 +427,7 @@ public class ExportImportTest {
|
||||
|
||||
@LargeTest
|
||||
@Test(expected = ImportAlreadyExistsException.class)
|
||||
public void kml_with_trackdetail_and_sensordata_duplicate_trackUUID() throws TimeoutException, IOException {
|
||||
public void kml_with_trackdetail_and_sensordata_duplicate_trackUUID() throws IOException {
|
||||
// given
|
||||
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
|
||||
editor.putBoolean(context.getString(R.string.import_prevent_reimport_key), true);
|
||||
@@ -487,6 +497,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(1, 1)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -500,6 +511,7 @@ public class ExportImportTest {
|
||||
Speed.of(5)),
|
||||
Distance.of(12),
|
||||
HeartRate.of(69),
|
||||
Temperature.of(30),
|
||||
Cadence.of(3),
|
||||
Power.of(50),
|
||||
new AltitudeGainLoss(1, 1)
|
||||
@@ -517,6 +529,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -532,6 +545,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -547,6 +561,7 @@ public class ExportImportTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
)
|
||||
), actual);
|
||||
@@ -575,7 +590,7 @@ public class ExportImportTest {
|
||||
|
||||
@LargeTest
|
||||
@Test(expected = ImportAlreadyExistsException.class)
|
||||
public void gpx_duplicate_trackUUID() throws TimeoutException, IOException {
|
||||
public void gpx_duplicate_trackUUID() throws IOException {
|
||||
// given
|
||||
SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(context).edit();
|
||||
editor.putBoolean(context.getString(R.string.import_prevent_reimport_key), true);
|
||||
@@ -601,7 +616,7 @@ public class ExportImportTest {
|
||||
|
||||
@LargeTest
|
||||
@Test
|
||||
public void csv_export_only() throws TimeoutException, IOException {
|
||||
public void csv_export_only() throws IOException {
|
||||
// given
|
||||
Track track = contentProviderUtils.getTrack(trackId);
|
||||
|
||||
@@ -645,7 +660,7 @@ public class ExportImportTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void mockSensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power, Float altitudeGain) {
|
||||
private void mockSensorData(TrackPointCreator trackPointCreator, Float speed, Distance distance, float heartRate, float cadence, Float power, Float altitudeGain, float temperature) {
|
||||
SensorDataAggregator sensorDataAggregator = trackPointCreator.getSensorManager().sensorDataAggregator;
|
||||
|
||||
AggregatorCyclingPower cyclingPower = new AggregatorCyclingPower("", "");
|
||||
@@ -691,6 +706,19 @@ public class ExportImportTest {
|
||||
|
||||
mockAltitudeChange(trackPointCreator, altitudeGain);
|
||||
|
||||
sensorDataAggregator.add(new AggregatorTemperature("", "'") {
|
||||
@NonNull
|
||||
@Override
|
||||
public Temperature getAggregatedValue(Instant now) {
|
||||
return Temperature.of(temperature);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasReceivedData() {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
trackPointCreator.onChange();
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -210,6 +210,7 @@ public class GPXTrackImporterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(1, 1)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -223,6 +224,7 @@ public class GPXTrackImporterTest {
|
||||
Speed.of(5)),
|
||||
Distance.of(12),
|
||||
HeartRate.of(69),
|
||||
null,
|
||||
Cadence.of(3),
|
||||
Power.of(50),
|
||||
new AltitudeGainLoss(1, 1)
|
||||
@@ -240,6 +242,7 @@ public class GPXTrackImporterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -255,6 +258,7 @@ public class GPXTrackImporterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -270,6 +274,7 @@ public class GPXTrackImporterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
)
|
||||
), actual);
|
||||
|
||||
@@ -52,6 +52,8 @@ public class TrackPointAssert {
|
||||
|
||||
Assert.assertEquals("heartRate", expected.heartRate(), actual.heartRate());
|
||||
|
||||
Assert.assertEquals("temperature", expected.temperature(), actual.temperature());
|
||||
|
||||
Assert.assertEquals("power", expected.power(), actual.power());
|
||||
|
||||
Assert.assertEquals("cadence", expected.cadence(), actual.cadence());
|
||||
|
||||
+27
@@ -135,6 +135,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -217,6 +218,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
|
||||
@@ -239,6 +241,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(resumeTime))
|
||||
@@ -280,6 +283,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0))
|
||||
), trackPoints);
|
||||
}
|
||||
@@ -316,6 +320,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(TrackPoint.Type.SEGMENT_START_MANUAL, Instant.parse(resumeTime))
|
||||
@@ -360,6 +365,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
HeartRate.of(7),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -370,6 +376,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
HeartRate.of(7),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
@@ -434,6 +441,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -449,6 +457,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -464,6 +473,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -474,6 +484,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
@@ -535,6 +546,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -550,6 +562,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -565,6 +578,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
)
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
@@ -614,6 +628,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -629,6 +644,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)),
|
||||
new TrackPoint(
|
||||
null,
|
||||
@@ -638,6 +654,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -689,6 +706,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -745,6 +763,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -760,6 +779,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0)
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -770,6 +790,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
new AltitudeGainLoss(0, 0))
|
||||
), TestDataUtil.getTrackPoints(contentProviderUtils, trackId));
|
||||
}
|
||||
@@ -852,6 +873,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Speed.of(5)),
|
||||
Distance.of(2),
|
||||
null,
|
||||
null,
|
||||
Cadence.of(2),
|
||||
null,
|
||||
null
|
||||
@@ -867,6 +889,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Speed.of(5)),
|
||||
Distance.ZERO,
|
||||
null,
|
||||
null,
|
||||
Cadence.of(2),
|
||||
null,
|
||||
null
|
||||
@@ -882,6 +905,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Speed.of(5)),
|
||||
Distance.of(10),
|
||||
null,
|
||||
null,
|
||||
Cadence.of(3),
|
||||
null,
|
||||
null
|
||||
@@ -897,6 +921,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Speed.of(5)),
|
||||
Distance.of(4.0),
|
||||
null,
|
||||
null,
|
||||
Cadence.of(5),
|
||||
null,
|
||||
null
|
||||
@@ -912,6 +937,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Speed.of(5)),
|
||||
Distance.ZERO,
|
||||
null,
|
||||
null,
|
||||
Cadence.of(5),
|
||||
null,
|
||||
null
|
||||
@@ -927,6 +953,7 @@ public class TrackRecordingServiceRecordingTest {
|
||||
Speed.ZERO), //Sensor data is now outdated, but we do not fall back to GPS.
|
||||
Distance.ZERO,
|
||||
null,
|
||||
null,
|
||||
Cadence.of(0), //TODO This could be null, right?
|
||||
null,
|
||||
null
|
||||
|
||||
+16
-16
@@ -89,7 +89,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -129,7 +129,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -169,7 +169,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -209,7 +209,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -231,7 +231,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -271,7 +271,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -293,7 +293,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -333,7 +333,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -373,7 +373,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -413,7 +413,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -453,7 +453,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -475,7 +475,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -515,7 +515,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -537,7 +537,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -564,7 +564,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
@@ -597,7 +597,7 @@ public class VoiceAnnouncementUtilsTest {
|
||||
null,
|
||||
null,
|
||||
new SensorData<>(HeartRate.of(60), "unused"),
|
||||
null,
|
||||
null, null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
@@ -112,6 +112,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null);
|
||||
|
||||
// when
|
||||
@@ -191,6 +192,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
HeartRate.of(50),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -201,6 +203,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
HeartRate.of(50),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
),
|
||||
createTrackPoint(0, 1, Altitude.WGS84.of(0), Instant.ofEpochSecond(50)),
|
||||
@@ -228,6 +231,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -238,6 +242,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
HeartRate.of(50),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
),
|
||||
new TrackPoint(
|
||||
@@ -248,6 +253,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
HeartRate.of(50),
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
),
|
||||
createTrackPoint(0, 0, Altitude.WGS84.of(0), Instant.ofEpochSecond(50), null, Distance.of(10)),
|
||||
@@ -287,6 +293,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
@@ -306,6 +313,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
@@ -325,6 +333,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
)
|
||||
);
|
||||
@@ -407,6 +416,7 @@ public class TrackStatisticsUpdaterTest {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Statistics;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.statistics.SensorStatistics;
|
||||
@@ -538,6 +539,7 @@ public class ContentProviderUtils {
|
||||
int speedIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SPEED);
|
||||
int bearingIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.BEARING);
|
||||
int sensorHeartRateIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_HEARTRATE);
|
||||
int temperatureIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_TEMPERATURE);
|
||||
int sensorCadenceIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_CADENCE);
|
||||
int sensorDistanceIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_DISTANCE);
|
||||
int sensorPowerIndex = cursor.getColumnIndexOrThrow(TrackPointsColumns.SENSOR_POWER);
|
||||
@@ -564,6 +566,7 @@ public class ContentProviderUtils {
|
||||
),
|
||||
!cursor.isNull(sensorDistanceIndex) ? Distance.of(cursor.getFloat(sensorDistanceIndex)) : null,
|
||||
!cursor.isNull(sensorHeartRateIndex) ? HeartRate.of(cursor.getFloat(sensorHeartRateIndex)) : null,
|
||||
!cursor.isNull(temperatureIndex) ? Temperature.of(cursor.getFloat(temperatureIndex)) : null,
|
||||
!cursor.isNull(sensorCadenceIndex) ? Cadence.of(cursor.getFloat(sensorCadenceIndex)) : null,
|
||||
!cursor.isNull(sensorPowerIndex) ? Power.of(cursor.getFloat(sensorPowerIndex)) : null,
|
||||
altitudeGainLoss
|
||||
@@ -652,6 +655,9 @@ public class ContentProviderUtils {
|
||||
if (trackPoint.heartRate() != null) {
|
||||
values.put(TrackPointsColumns.SENSOR_HEARTRATE, trackPoint.heartRate().getBPM());
|
||||
}
|
||||
if (trackPoint.temperature() != null) {
|
||||
values.put(TrackPointsColumns.SENSOR_TEMPERATURE, trackPoint.temperature().getCelsius());
|
||||
}
|
||||
if (trackPoint.cadence() != null) {
|
||||
values.put(TrackPointsColumns.SENSOR_CADENCE, trackPoint.cadence().getRPM());
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
|
||||
private static final String TAG = CustomSQLiteOpenHelper.class.getSimpleName();
|
||||
|
||||
private static final int DATABASE_VERSION = 40;
|
||||
private static final int DATABASE_VERSION = 41;
|
||||
|
||||
private final Context context;
|
||||
|
||||
@@ -84,6 +84,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 38 -> upgradeFrom37to38(db);
|
||||
case 39 -> upgradeFrom38to39(db);
|
||||
case 40 -> upgradeFrom39to40(db);
|
||||
case 41 -> upgradeFrom40to41(db);
|
||||
default -> throw new RuntimeException("Not implemented: upgrade to " + toVersion);
|
||||
}
|
||||
}
|
||||
@@ -111,6 +112,7 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
case 37 -> downgradeFrom38to37(db);
|
||||
case 38 -> downgradeFrom39to38(db);
|
||||
case 39 -> downgradeFrom40to39(db);
|
||||
case 40 -> downgradeFrom41to40(db);
|
||||
default -> throw new RuntimeException("Not implemented: downgrade to " + toVersion);
|
||||
}
|
||||
}
|
||||
@@ -734,4 +736,32 @@ class CustomSQLiteOpenHelper extends SQLiteOpenHelper {
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
private void upgradeFrom40to41(SQLiteDatabase db) {
|
||||
db.beginTransaction();
|
||||
|
||||
db.execSQL("ALTER TABLE trackpoints RENAME TO trackpoints_old");
|
||||
db.execSQL("CREATE TABLE trackpoints (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackid INTEGER NOT NULL, longitude INTEGER, latitude INTEGER, time INTEGER, elevation FLOAT, accuracy FLOAT, speed FLOAT, bearing FLOAT, sensor_heartrate FLOAT, sensor_temperature FLOAT, sensor_cadence FLOAT, sensor_power FLOAT, elevation_gain FLOAT, elevation_loss FLOAT, type TEXT CHECK(type IN (-2, -1, 0, 1, 3)), sensor_distance FLOAT, accuracy_vertical FLOAT, FOREIGN KEY (trackid) REFERENCES tracks(_id) ON UPDATE CASCADE ON DELETE CASCADE)");
|
||||
db.execSQL("INSERT INTO trackpoints SELECT _id, trackid, longitude, latitude, time, elevation, accuracy, speed, bearing, sensor_heartrate, null, sensor_cadence, sensor_power, elevation_gain, elevation_gain, type, sensor_distance, accuracy_vertical FROM trackpoints_old");
|
||||
db.execSQL("DROP TABLE trackpoints_old");
|
||||
|
||||
db.execSQL("CREATE INDEX trackpoints_trackid_index ON trackpoints(trackid)");
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
|
||||
private void downgradeFrom41to40(SQLiteDatabase db) {
|
||||
db.beginTransaction();
|
||||
|
||||
db.execSQL("ALTER TABLE trackpoints RENAME TO trackpoints_old");
|
||||
db.execSQL("CREATE TABLE trackpoints (_id INTEGER PRIMARY KEY AUTOINCREMENT, trackid INTEGER NOT NULL, longitude INTEGER, latitude INTEGER, time INTEGER, elevation FLOAT, accuracy FLOAT, speed FLOAT, bearing FLOAT, sensor_heartrate FLOAT, sensor_cadence FLOAT, sensor_power FLOAT, elevation_gain FLOAT, elevation_loss FLOAT, type TEXT CHECK(type IN (-2, -1, 0, 1, 3)), sensor_distance FLOAT, accuracy_vertical FLOAT, FOREIGN KEY (trackid) REFERENCES tracks(_id) ON UPDATE CASCADE ON DELETE CASCADE)");
|
||||
db.execSQL("INSERT INTO trackpoints SELECT _id, trackid, longitude, latitude, time, elevation, accuracy, speed, bearing, sensor_heartrate, sensor_cadence, sensor_power, elevation_gain, elevation_gain, type, sensor_distance, accuracy_vertical FROM trackpoints_old");
|
||||
db.execSQL("DROP TABLE trackpoints_old");
|
||||
|
||||
db.execSQL("CREATE INDEX trackpoints_trackid_index ON trackpoints(trackid)");
|
||||
|
||||
db.setTransactionSuccessful();
|
||||
db.endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package de.dennisguse.opentracks.data.models;
|
||||
|
||||
public record Temperature(
|
||||
float value_celsius
|
||||
) {
|
||||
|
||||
public static Temperature of(float value_celsius) {
|
||||
return new Temperature(value_celsius);
|
||||
}
|
||||
|
||||
public static Temperature ofCentiCelsius(int value_centi_celsius) {
|
||||
return Temperature.of((float) (value_centi_celsius / 100.0));
|
||||
}
|
||||
|
||||
public float getCelsius() {
|
||||
return value_celsius;
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ public record TrackPoint(
|
||||
|
||||
Distance sensorDistance,
|
||||
HeartRate heartRate,
|
||||
Temperature temperature,
|
||||
Cadence cadence,
|
||||
Power power,
|
||||
AltitudeGainLoss altitudeGainLoss
|
||||
@@ -57,6 +58,7 @@ public record TrackPoint(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
@@ -71,6 +73,7 @@ public record TrackPoint(
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null
|
||||
);
|
||||
}
|
||||
@@ -95,6 +98,7 @@ public record TrackPoint(
|
||||
),
|
||||
trackPoint.sensorDistance,
|
||||
trackPoint.heartRate,
|
||||
null,
|
||||
trackPoint.cadence,
|
||||
trackPoint.power,
|
||||
trackPoint.altitudeGainLoss
|
||||
@@ -108,6 +112,7 @@ public record TrackPoint(
|
||||
position,
|
||||
sensorDistance,
|
||||
heartRate,
|
||||
null,
|
||||
cadence,
|
||||
power,
|
||||
altitudeGainLoss
|
||||
@@ -121,6 +126,7 @@ public record TrackPoint(
|
||||
newPosition,
|
||||
sensorDistance,
|
||||
heartRate,
|
||||
null,
|
||||
cadence,
|
||||
power,
|
||||
altitudeGainLoss
|
||||
@@ -150,6 +156,7 @@ public record TrackPoint(
|
||||
position,
|
||||
newSensorDistance,
|
||||
heartRate,
|
||||
null,
|
||||
cadence,
|
||||
power,
|
||||
newAltitudeGainLoss
|
||||
|
||||
@@ -50,6 +50,7 @@ public interface TrackPointsColumns extends BaseColumns {
|
||||
String SPEED = "speed";
|
||||
String BEARING = "bearing";
|
||||
String SENSOR_HEARTRATE = "sensor_heartrate";
|
||||
String SENSOR_TEMPERATURE = "sensor_temperature";
|
||||
String SENSOR_CADENCE = "sensor_cadence";
|
||||
String SENSOR_DISTANCE = "sensor_distance"; //DISTANCE from previous TrackPoint
|
||||
String SENSOR_POWER = "sensor_power";
|
||||
@@ -75,6 +76,7 @@ public interface TrackPointsColumns extends BaseColumns {
|
||||
+ SPEED + " FLOAT, "
|
||||
+ BEARING + " FLOAT, "
|
||||
+ SENSOR_HEARTRATE + " FLOAT, "
|
||||
+ SENSOR_TEMPERATURE + " FLOAT, "
|
||||
+ SENSOR_CADENCE + " FLOAT, "
|
||||
+ SENSOR_POWER + " FLOAT, "
|
||||
+ ALTITUDE_GAIN + " FLOAT, "
|
||||
|
||||
@@ -61,6 +61,7 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
private static final NumberFormat SPEED_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
private static final NumberFormat DISTANCE_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
private static final NumberFormat HEARTRATE_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
private static final NumberFormat TEMPERATURE_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
private static final NumberFormat CADENCE_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
private static final NumberFormat POWER_FORMAT = NumberFormat.getInstance(Locale.US);
|
||||
|
||||
@@ -82,6 +83,9 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
HEARTRATE_FORMAT.setMaximumFractionDigits(0);
|
||||
HEARTRATE_FORMAT.setGroupingUsed(false);
|
||||
|
||||
TEMPERATURE_FORMAT.setMaximumFractionDigits(2);
|
||||
TEMPERATURE_FORMAT.setGroupingUsed(false);
|
||||
|
||||
CADENCE_FORMAT.setMaximumFractionDigits(0);
|
||||
CADENCE_FORMAT.setGroupingUsed(false);
|
||||
|
||||
@@ -321,6 +325,10 @@ public class GPXTrackExporter implements TrackExporter {
|
||||
trackPointExtensionV2Content += "<gpxtpx:hr>" + HEARTRATE_FORMAT.format(trackPoint.heartRate().getBPM()) + "</gpxtpx:hr>\n";
|
||||
}
|
||||
|
||||
if (trackPoint.temperature() != null) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:atemp>" + TEMPERATURE_FORMAT.format(trackPoint.temperature().getCelsius()) + "</gpxtpx:atemp>\n";
|
||||
}
|
||||
|
||||
if (trackPoint.cadence() != null) {
|
||||
trackPointExtensionV2Content += "<gpxtpx:cad>" + CADENCE_FORMAT.format(trackPoint.cadence().getRPM()) + "</gpxtpx:cad>\n";
|
||||
}
|
||||
|
||||
@@ -67,8 +67,9 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
public static final String EXTENDED_DATA_TYPE_TRACKPOINT = "trackpoint_type";
|
||||
public static final String EXTENDED_DATA_TYPE_SPEED = "speed";
|
||||
public static final String EXTENDED_DATA_TYPE_DISTANCE = "distance";
|
||||
public static final String EXTENDED_DATA_TYPE_CADENCE = "cadence";
|
||||
public static final String EXTENDED_DATA_TYPE_HEARTRATE = "heartrate";
|
||||
public static final String EXTENDED_DATA_TYPE_TEMPERATURE = "temperature";
|
||||
public static final String EXTENDED_DATA_TYPE_CADENCE = "cadence";
|
||||
public static final String EXTENDED_DATA_TYPE_POWER = "power";
|
||||
public static final String EXTENDED_DATA_TYPE_ALTITUDE_GAIN = "elevation_gain";
|
||||
public static final String EXTENDED_DATA_TYPE_ALTITUDE_LOSS = "elevation_loss";
|
||||
@@ -95,6 +96,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
private final List<Float> powerList = new ArrayList<>();
|
||||
private final List<Float> cadenceList = new ArrayList<>();
|
||||
private final List<Float> heartRateList = new ArrayList<>();
|
||||
private final List<Float> temperatureList = new ArrayList<>();
|
||||
private final List<Float> altitudeGainList = new ArrayList<>(); //TODO Join with altitudeLossList
|
||||
private final List<Float> altitudeLossList = new ArrayList<>();
|
||||
private final List<Float> accuracyHorizontal = new ArrayList<>();
|
||||
@@ -237,7 +239,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.opengis.net/kml/2.3 http://schemas.opengis.net/kml/2.3/ogckml23.xsd
|
||||
http://opentracksapp.com/xmlschemas/v1 http://opentracksapp.com/xmlschemas/OpenTracks_v1.xsd">
|
||||
"""); //TODO ADD xsi:schemaLocation for atom
|
||||
"""); //NOTE: There is no XSD for Atom
|
||||
printWriter.println("<Document>");
|
||||
printWriter.println("<open>1</open>");
|
||||
printWriter.println("<visibility>1</visibility>");
|
||||
@@ -254,6 +256,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_POWER, context.getString(R.string.description_sensor_power));
|
||||
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_CADENCE, context.getString(R.string.description_sensor_cadence));
|
||||
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_HEARTRATE, context.getString(R.string.description_sensor_heart_rate));
|
||||
writeSimpleArrayStyle(EXTENDED_DATA_TYPE_TEMPERATURE, context.getString(R.string.description_sensor_temperature));
|
||||
|
||||
printWriter.println("</Schema>");
|
||||
}
|
||||
@@ -321,6 +324,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
powerList.clear();
|
||||
cadenceList.clear();
|
||||
heartRateList.clear();
|
||||
temperatureList.clear();
|
||||
altitudeGainList.clear();
|
||||
altitudeLossList.clear();
|
||||
accuracyHorizontal.clear();
|
||||
@@ -349,6 +353,9 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
if (heartRateList.stream().anyMatch(Objects::nonNull)) {
|
||||
writeSimpleArraySensorData(heartRateList, EXTENDED_DATA_TYPE_HEARTRATE);
|
||||
}
|
||||
if (temperatureList.stream().anyMatch(Objects::nonNull)) {
|
||||
writeSimpleArraySensorData(temperatureList, EXTENDED_DATA_TYPE_TEMPERATURE);
|
||||
}
|
||||
if (altitudeGainList.stream().anyMatch(Objects::nonNull)) {
|
||||
writeSimpleArraySensorData(altitudeGainList, EXTENDED_DATA_TYPE_ALTITUDE_GAIN);
|
||||
}
|
||||
@@ -381,6 +388,7 @@ public class KMLTrackExporter implements TrackExporter {
|
||||
|
||||
distanceList.add(trackPoint.sensorDistance() != null ? (float) trackPoint.sensorDistance().toM() : null);
|
||||
heartRateList.add(trackPoint.heartRate() != null ? trackPoint.heartRate().getBPM() : null);
|
||||
temperatureList.add(trackPoint.temperature() != null ? trackPoint.temperature().getCelsius() : null);
|
||||
cadenceList.add(trackPoint.cadence() != null ? trackPoint.cadence().getRPM() : null);
|
||||
powerList.add(trackPoint.power() != null ? trackPoint.power().getW() : null);
|
||||
if (trackPoint.altitudeGainLoss() != null) {
|
||||
|
||||
@@ -40,6 +40,7 @@ import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.data.statistics.SegmentStatisticUpdater;
|
||||
@@ -83,6 +84,7 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
*/
|
||||
private static final String TAG_EXTENSION_SPEED_COMPAT = "speed";
|
||||
private static final String TAG_EXTENSION_HEARTRATE = "gpxtpx:hr";
|
||||
private static final String TAG_EXTENSION_TEMPERATURE = "gpxtpx:atemp";
|
||||
private static final String TAG_EXTENSION_CADENCE = "gpxtpx:cad";
|
||||
private static final String TAG_EXTENSION_POWER = "pwr:PowerInWatts";
|
||||
|
||||
@@ -113,6 +115,7 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
private String time;
|
||||
private String speed;
|
||||
private String heartrate;
|
||||
private String temperature;
|
||||
private String cadence;
|
||||
private String power;
|
||||
private String markerType;
|
||||
@@ -218,6 +221,11 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
heartrate = content.trim();
|
||||
}
|
||||
}
|
||||
case TAG_EXTENSION_TEMPERATURE -> {
|
||||
if (content != null) {
|
||||
temperature = content.trim();
|
||||
}
|
||||
}
|
||||
case TAG_EXTENSION_CADENCE -> {
|
||||
if (content != null) {
|
||||
cadence = content.trim();
|
||||
@@ -354,6 +362,15 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
}
|
||||
}
|
||||
|
||||
Temperature parsedTemperature = null;
|
||||
if (temperature != null) {
|
||||
try {
|
||||
parsedTemperature = Temperature.of(Float.parseFloat(temperature));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new ParsingException(createErrorMessage(String.format(Locale.US, "Unable to parse temperature: %s", temperature)), e);
|
||||
}
|
||||
}
|
||||
|
||||
Cadence parsedCadence = null;
|
||||
if (cadence != null) {
|
||||
try {
|
||||
@@ -396,6 +413,7 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
),
|
||||
parsedSensorDistance,
|
||||
parsedHeartRate,
|
||||
parsedTemperature,
|
||||
parsedCadence,
|
||||
parsedPower,
|
||||
altitudeGainLoss
|
||||
@@ -415,9 +433,10 @@ public class GPXTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
sensorDistance = null;
|
||||
accuracyHorizontal = null;
|
||||
accuracyVertical = null;
|
||||
power = null;
|
||||
heartrate = null;
|
||||
temperature = null;
|
||||
cadence = null;
|
||||
power = null;
|
||||
}
|
||||
|
||||
private void onMarkerStart(Attributes attributes) {
|
||||
|
||||
@@ -42,6 +42,7 @@ import de.dennisguse.opentracks.data.models.Marker;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.data.models.Track;
|
||||
import de.dennisguse.opentracks.data.models.TrackPoint;
|
||||
import de.dennisguse.opentracks.io.file.exporter.KMLTrackExporter;
|
||||
@@ -109,6 +110,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
private final ArrayList<Float> sensorDistanceList = new ArrayList<>();
|
||||
private final ArrayList<Float> sensorCadenceList = new ArrayList<>();
|
||||
private final ArrayList<Float> sensorHeartRateList = new ArrayList<>();
|
||||
private final ArrayList<Float> sensorTemperatureList = new ArrayList<>();
|
||||
private final ArrayList<Float> sensorPowerList = new ArrayList<>();
|
||||
private final ArrayList<Float> altitudeGainList = new ArrayList<>();
|
||||
private final ArrayList<Float> altitudeLossList = new ArrayList<>();
|
||||
@@ -312,6 +314,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
sensorSpeedList.clear();
|
||||
sensorDistanceList.clear();
|
||||
sensorHeartRateList.clear();
|
||||
sensorTemperatureList.clear();
|
||||
sensorCadenceList.clear();
|
||||
sensorPowerList.clear();
|
||||
altitudeGainList.clear();
|
||||
@@ -334,6 +337,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
Speed speed = null;
|
||||
Distance sensorDistance = null;
|
||||
HeartRate heartRate = null;
|
||||
Temperature temperature = null;
|
||||
Cadence cadence = null;
|
||||
Power power = null;
|
||||
AltitudeGainLoss altitudeGainLoss = null;
|
||||
@@ -352,6 +356,9 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
if (i < sensorHeartRateList.size()) {
|
||||
heartRate = HeartRate.ofOrNull(sensorHeartRateList.get(i));
|
||||
}
|
||||
if (i < sensorTemperatureList.size() && sensorTemperatureList.get(i) != null) {
|
||||
temperature = Temperature.of(sensorTemperatureList.get(i));
|
||||
}
|
||||
if (i < sensorCadenceList.size() && sensorCadenceList.get(i) != null) {
|
||||
cadence = Cadence.of(sensorCadenceList.get(i));
|
||||
}
|
||||
@@ -399,6 +406,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
position,
|
||||
sensorDistance,
|
||||
heartRate,
|
||||
temperature,
|
||||
cadence,
|
||||
power,
|
||||
altitudeGainLoss
|
||||
@@ -467,6 +475,7 @@ public class KMLTrackImporter extends DefaultHandler implements XMLImporter.Trac
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_POWER -> sensorPowerList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_HEARTRATE,
|
||||
EXTENDED_DATA_TYPE_HEART_RATE_LEGACY -> sensorHeartRateList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_TEMPERATURE -> sensorTemperatureList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_CADENCE -> sensorCadenceList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ALTITUDE_GAIN -> altitudeGainList.add(value);
|
||||
case KMLTrackExporter.EXTENDED_DATA_TYPE_ALTITUDE_LOSS -> altitudeLossList.add(value);
|
||||
|
||||
+3
-5
@@ -12,10 +12,10 @@ import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
public class BluetoothHandlerBarometricPressure implements SensorHandlerInterface {
|
||||
private static final UUID ENVIRONMENTAL_SENSING_SERVICE = new UUID(0x181A00001000L, 0x800000805f9b34fbL);
|
||||
static final UUID ENVIRONMENTAL_SENSING_SERVICE = new UUID(0x181A00001000L, 0x800000805f9b34fbL);
|
||||
public static final ServiceMeasurementUUID BAROMETRIC_PRESSURE = new ServiceMeasurementUUID(
|
||||
ENVIRONMENTAL_SENSING_SERVICE,
|
||||
new UUID(0x2A6D00001000L, 0x800000805f9b34fbL)
|
||||
new UUID(0x2A6D00001000L, 0x800000805f9b34fbL) //TODO extract leastSigBits
|
||||
);
|
||||
|
||||
@Override
|
||||
@@ -37,9 +37,7 @@ public class BluetoothHandlerBarometricPressure implements SensorHandlerInterfac
|
||||
}
|
||||
|
||||
/**
|
||||
* Decoding:
|
||||
* org.bluetooth.service.environmental_sensing.xml
|
||||
* org.bluetooth.characteristic.pressure.xml
|
||||
* Decoding: org.bluetooth.characteristic.pressure.xml
|
||||
*/
|
||||
public static AtmosphericPressure parseEnvironmentalSensing(BluetoothGattCharacteristic characteristic) {
|
||||
byte[] raw = characteristic.getValue();
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
package de.dennisguse.opentracks.sensors;
|
||||
|
||||
import static de.dennisguse.opentracks.sensors.BluetoothHandlerBarometricPressure.ENVIRONMENTAL_SENSING_SERVICE;
|
||||
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Aggregator;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.AggregatorTemperature;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.Raw;
|
||||
import de.dennisguse.opentracks.sensors.sensorData.SensorHandlerInterface;
|
||||
|
||||
public class BluetoothHandlerTemperature implements SensorHandlerInterface {
|
||||
public static final ServiceMeasurementUUID TEMPERATURE = new ServiceMeasurementUUID(
|
||||
ENVIRONMENTAL_SENSING_SERVICE,
|
||||
new UUID(0x2A6E00001000L, 0x800000805f9b34fbL)
|
||||
);
|
||||
|
||||
@Override
|
||||
public List<ServiceMeasurementUUID> getServices() {
|
||||
return List.of(TEMPERATURE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Aggregator<?, ?> createEmptySensorData(String address, String name) {
|
||||
return new AggregatorTemperature(address, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlePayload(SensorManager.SensorDataChangedObserver observer, ServiceMeasurementUUID serviceMeasurementUUID, String sensorName, String address, BluetoothGattCharacteristic characteristic) {
|
||||
Temperature value = parseEnvironmentalSensing(characteristic);
|
||||
if (value == null) return;
|
||||
|
||||
observer.onChange(new Raw<>(observer.getNow(), value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decoding: org.bluetooth.characteristic.temperature.xml
|
||||
*/
|
||||
public static Temperature parseEnvironmentalSensing(BluetoothGattCharacteristic characteristic) {
|
||||
byte[] raw = characteristic.getValue();
|
||||
|
||||
if (raw.length < 2) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Integer pressure = characteristic.getIntValue(BluetoothGattCharacteristic.FORMAT_SINT16, 0);
|
||||
return Temperature.ofCentiCelsius(pressure);
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,6 @@ import android.os.Handler;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.R;
|
||||
import de.dennisguse.opentracks.settings.PreferencesUtils;
|
||||
|
||||
@@ -40,13 +38,12 @@ 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);
|
||||
|
||||
private final Context context;
|
||||
private final Handler handler;
|
||||
private boolean started = false;
|
||||
|
||||
private final BluetoothConnectionManager heartRate;
|
||||
private final BluetoothConnectionManager temperature;
|
||||
private final BluetoothConnectionManager cyclingCadence;
|
||||
private final BluetoothConnectionManager cyclingSpeed;
|
||||
private final BluetoothConnectionManager cyclingPower;
|
||||
@@ -58,6 +55,7 @@ public class BluetoothRemoteSensorManager implements SensorConnector, SharedPref
|
||||
|
||||
BluetoothAdapter bluetoothAdapter = BluetoothUtils.getAdapter(context);
|
||||
this.heartRate = new BluetoothConnectionManager(bluetoothAdapter, observer, new BluetoothHandlerHeartRate());
|
||||
this.temperature = new BluetoothConnectionManager(bluetoothAdapter, observer, new BluetoothHandlerTemperature());
|
||||
this.cyclingCadence = new BluetoothConnectionManager(bluetoothAdapter, observer, new BluetoothHandlerCyclingCadence());
|
||||
this.cyclingSpeed = new BluetoothConnectionManager(bluetoothAdapter, observer, new BluetoothHandlerCyclingDistanceSpeed());
|
||||
this.cyclingPower = new BluetoothConnectionManager(bluetoothAdapter, observer, new BluetoothHandlerCyclingPower());
|
||||
@@ -75,6 +73,7 @@ public class BluetoothRemoteSensorManager implements SensorConnector, SharedPref
|
||||
@Override
|
||||
public synchronized void stop(Context context) {
|
||||
heartRate.disconnect();
|
||||
temperature.disconnect();
|
||||
cyclingCadence.disconnect();
|
||||
cyclingSpeed.disconnect();
|
||||
cyclingPower.disconnect();
|
||||
@@ -96,6 +95,11 @@ public class BluetoothRemoteSensorManager implements SensorConnector, SharedPref
|
||||
connect(heartRate, address);
|
||||
}
|
||||
|
||||
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_temperature_key, key)) {
|
||||
String address = PreferencesUtils.getBluetoothTemperatureSensorAddress();
|
||||
connect(temperature, address);
|
||||
}
|
||||
|
||||
if (PreferencesUtils.isKey(R.string.settings_sensor_bluetooth_cycling_cadence_key, key)) {
|
||||
String address = PreferencesUtils.getBluetoothCyclingCadenceSensorAddress();
|
||||
connect(cyclingCadence, address);
|
||||
|
||||
@@ -2,12 +2,13 @@ package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.BluetoothRemoteSensorManager;
|
||||
|
||||
public abstract class Aggregator<Input, Output> {
|
||||
|
||||
private static final Duration MAX_SENSOR_DATE_SET_AGE = Duration.ofSeconds(5);
|
||||
|
||||
protected Raw<Input> previous;
|
||||
|
||||
protected Output aggregatedValue;
|
||||
@@ -43,6 +44,7 @@ public abstract class Aggregator<Input, Output> {
|
||||
return aggregatedValue != null;
|
||||
}
|
||||
|
||||
@Deprecated //TODO Remove: for sensor there is no default value. Make getAggregatedValue() @Nullable
|
||||
@NonNull
|
||||
protected abstract Output getNoneValue();
|
||||
|
||||
@@ -84,10 +86,14 @@ public abstract class Aggregator<Input, Output> {
|
||||
return now
|
||||
.isAfter(
|
||||
previous.time()
|
||||
.plus(BluetoothRemoteSensorManager.MAX_SENSOR_DATE_SET_AGE)
|
||||
.plus(getMaxSensorAge())
|
||||
);
|
||||
}
|
||||
|
||||
protected Duration getMaxSensorAge() {
|
||||
return MAX_SENSOR_DATE_SET_AGE;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package de.dennisguse.opentracks.sensors.sensorData;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
|
||||
public class AggregatorTemperature extends Aggregator<Temperature, Temperature> {
|
||||
|
||||
public AggregatorTemperature(String sensorAddress, String sensorName) {
|
||||
super(sensorAddress, sensorName);
|
||||
}
|
||||
|
||||
protected void computeValue(Raw<Temperature> current) {
|
||||
this.aggregatedValue = current.value();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected Temperature getNoneValue() {
|
||||
return Temperature.ofCentiCelsius(0);
|
||||
}
|
||||
|
||||
protected void resetImmediate() {
|
||||
aggregatedValue = getNoneValue();
|
||||
}
|
||||
|
||||
public void resetAggregated() {};
|
||||
|
||||
@Override
|
||||
protected Duration getMaxSensorAge() {
|
||||
return Duration.ofMinutes(1);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import de.dennisguse.opentracks.data.models.Distance;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingCadence;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingDistanceSpeed;
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerCyclingPower;
|
||||
@@ -27,6 +28,9 @@ public class SensorDataAggregator {
|
||||
@VisibleForTesting
|
||||
public AggregatorHeartRate heartRate;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorTemperature temperature;
|
||||
|
||||
@VisibleForTesting
|
||||
public AggregatorCyclingCadence cyclingCadence;
|
||||
|
||||
@@ -97,6 +101,7 @@ public class SensorDataAggregator {
|
||||
set(data, data);
|
||||
}
|
||||
|
||||
//TODO Refactor generic "fun" here: go explicit.
|
||||
public void update(@NonNull Raw<?> data) {
|
||||
Object value = data.value();
|
||||
|
||||
@@ -105,6 +110,11 @@ public class SensorDataAggregator {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof Temperature) {
|
||||
this.temperature.add((Raw<Temperature>) data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (value instanceof BluetoothHandlerCyclingCadence.CrankData) {
|
||||
this.cyclingCadence.add((Raw<BluetoothHandlerCyclingCadence.CrankData>) data);
|
||||
return;
|
||||
@@ -142,6 +152,7 @@ public class SensorDataAggregator {
|
||||
public void clear() {
|
||||
Log.i(TAG, "Removing all aggregators");
|
||||
this.heartRate = null;
|
||||
this.temperature = null;
|
||||
this.cyclingCadence = null;
|
||||
this.cyclingDistanceSpeed = null;
|
||||
this.cyclingPower = null;
|
||||
@@ -156,6 +167,7 @@ public class SensorDataAggregator {
|
||||
getSpeed(now),
|
||||
getDistance(now),
|
||||
getHeartRate(now),
|
||||
temperature != null && temperature.hasReceivedData() ? temperature.getAggregatedValueWithSensorName(now) : null,
|
||||
getCadence(now),
|
||||
cyclingPower != null && cyclingPower.hasReceivedData() ? cyclingPower.getAggregatedValueWithSensorName(now) : null,
|
||||
barometer != null && barometer.hasReceivedData() ? barometer.getAggregatedValueWithSensorName(now) : null
|
||||
@@ -166,6 +178,7 @@ public class SensorDataAggregator {
|
||||
Log.i(TAG, "Resetting data");
|
||||
|
||||
if (heartRate != null) heartRate.resetAggregated();
|
||||
if (temperature != null) temperature.resetAggregated();
|
||||
if (cyclingCadence != null) cyclingCadence.resetAggregated();
|
||||
if (cyclingDistanceSpeed != null) cyclingDistanceSpeed.resetAggregated();
|
||||
if (cyclingPower != null) cyclingPower.resetAggregated();
|
||||
@@ -182,6 +195,10 @@ public class SensorDataAggregator {
|
||||
heartRate = (AggregatorHeartRate) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorTemperature) {
|
||||
temperature = (AggregatorTemperature) sensorData;
|
||||
return;
|
||||
}
|
||||
if (type instanceof AggregatorCyclingCadence) {
|
||||
cyclingCadence = (AggregatorCyclingCadence) sensorData;
|
||||
return;
|
||||
|
||||
@@ -10,6 +10,7 @@ import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Speed;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
|
||||
public record SensorDataSet(
|
||||
@NonNull
|
||||
@@ -21,6 +22,7 @@ public record SensorDataSet(
|
||||
@Nullable
|
||||
SensorData<HeartRate> heartRate,
|
||||
@Nullable
|
||||
SensorData<Temperature> temperature,
|
||||
SensorData<Cadence> cadence,
|
||||
@Nullable
|
||||
SensorData<Power> power,
|
||||
|
||||
@@ -113,6 +113,7 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
|
||||
position,
|
||||
sensorDataSet.distance() != null ? sensorDataSet.distance().data() : null,
|
||||
sensorDataSet.heartRate() != null ? sensorDataSet.heartRate().data() : null,
|
||||
sensorDataSet.temperature() != null ? sensorDataSet.temperature().data() : null,
|
||||
sensorDataSet.cadence() != null ? sensorDataSet.cadence().data() : null,
|
||||
sensorDataSet.power() != null ? sensorDataSet.power().data() : null,
|
||||
sensorDataSet.altitudeGainLoss() != null ? sensorDataSet.altitudeGainLoss().data() : null
|
||||
@@ -138,6 +139,7 @@ public class TrackPointCreator implements SharedPreferences.OnSharedPreferenceCh
|
||||
position,
|
||||
sensorDataSet.distance() != null ? sensorDataSet.distance().data() : null,
|
||||
sensorDataSet.heartRate() != null ? sensorDataSet.heartRate().data() : null,
|
||||
sensorDataSet.temperature() != null ? sensorDataSet.temperature().data() : null,
|
||||
sensorDataSet.cadence() != null ? sensorDataSet.cadence().data() : null,
|
||||
sensorDataSet.power() != null ? sensorDataSet.power().data() : null,
|
||||
sensorDataSet.altitudeGainLoss() != null ? sensorDataSet.altitudeGainLoss().data() : null
|
||||
|
||||
@@ -274,6 +274,10 @@ public class PreferencesUtils {
|
||||
return getString(R.string.settings_sensor_bluetooth_heart_rate_key, getBluetoothSensorAddressNone());
|
||||
}
|
||||
|
||||
public static String getBluetoothTemperatureSensorAddress() {
|
||||
return getString(R.string.settings_sensor_bluetooth_temperature_key, getBluetoothSensorAddressNone());
|
||||
}
|
||||
|
||||
public static String getBluetoothCyclingCadenceSensorAddress() {
|
||||
return getString(R.string.settings_sensor_bluetooth_cycling_cadence_key, getBluetoothSensorAddressNone());
|
||||
}
|
||||
@@ -830,7 +834,8 @@ public class PreferencesUtils {
|
||||
R.array.stats_custom_layout_fields_default_value_17,
|
||||
R.array.stats_custom_layout_fields_default_value_18,
|
||||
R.array.stats_custom_layout_fields_default_value_19,
|
||||
R.array.stats_custom_layout_fields_default_value_20
|
||||
R.array.stats_custom_layout_fields_default_value_20,
|
||||
R.array.stats_custom_layout_fields_default_value_21
|
||||
).map(id -> resources.obtainTypedArray(id))
|
||||
.toList();
|
||||
}
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
package de.dennisguse.opentracks.settings.bluetooth;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import androidx.preference.PreferenceDialogFragmentCompat;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.dennisguse.opentracks.sensors.BluetoothHandlerTemperature;
|
||||
|
||||
public class BluetoothLeTemperaturePreference extends BluetoothLeSensorPreference {
|
||||
|
||||
public BluetoothLeTemperaturePreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public BluetoothLeTemperaturePreference(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
public BluetoothLeTemperaturePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public BluetoothLeTemperaturePreference(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PreferenceDialogFragmentCompat createInstance() {
|
||||
return BluetoothLeSensorPreferenceDialog
|
||||
.newInstance(getKey(), List.of(BluetoothHandlerTemperature.TEMPERATURE));
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,6 @@ package de.dennisguse.opentracks.util;
|
||||
import static java.time.temporal.ChronoUnit.DAYS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.location.Location;
|
||||
import android.text.TextUtils;
|
||||
import android.text.format.DateUtils;
|
||||
import android.util.Log;
|
||||
@@ -47,6 +46,7 @@ import de.dennisguse.opentracks.data.models.DistanceFormatter;
|
||||
import de.dennisguse.opentracks.data.models.HeartRate;
|
||||
import de.dennisguse.opentracks.data.models.Position;
|
||||
import de.dennisguse.opentracks.data.models.Power;
|
||||
import de.dennisguse.opentracks.data.models.Temperature;
|
||||
import de.dennisguse.opentracks.settings.UnitSystem;
|
||||
|
||||
/**
|
||||
@@ -156,6 +156,15 @@ public class StringUtils {
|
||||
return new Pair<>(value, context.getString(R.string.sensor_unit_beats_per_minute));
|
||||
}
|
||||
|
||||
public static Pair<String, String> getTemperatureParts(Context context, Temperature temperature) {
|
||||
String value = context.getString(R.string.value_unknown);
|
||||
if (temperature != null) {
|
||||
value = StringUtils.formatDecimal(temperature.getCelsius(), 1);
|
||||
}
|
||||
|
||||
return new Pair<>(value, context.getString(R.string.sensor_unit_temperature));
|
||||
}
|
||||
|
||||
public static Pair<String, String> getCadenceParts(Context context, Cadence cadence) {
|
||||
String value = context.getString(R.string.value_unknown);
|
||||
if (cadence != null) {
|
||||
|
||||
@@ -34,6 +34,7 @@ public class Mapping {
|
||||
m.put(context.getString(R.string.stats_custom_layout_coordinates_key), GenericStatisticsViewHolder.Coordinates::new);
|
||||
|
||||
m.put(context.getString(R.string.stats_custom_layout_heart_rate_key), SensorStatisticsViewHolder.SensorHeartRate::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_temperature_key), SensorStatisticsViewHolder.SensorTemperature::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_cadence_key), SensorStatisticsViewHolder.SensorCadence::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_power_key), SensorStatisticsViewHolder.SensorPower::new);
|
||||
m.put(context.getString(R.string.stats_custom_layout_clock_key), ClockViewHolder::new);
|
||||
|
||||
@@ -60,6 +60,29 @@ public abstract class SensorStatisticsViewHolder extends StatisticViewHolder<Sta
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorTemperature extends SensorStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
public void onChanged(UnitSystem unitSystem, RecordingData data) {
|
||||
SensorDataSet sensorDataSet = data.sensorDataSet();
|
||||
String sensorName = getContext().getString(R.string.value_unknown);
|
||||
|
||||
Pair<String, String> valueAndUnit;
|
||||
if (sensorDataSet != null && sensorDataSet.temperature() != null) {
|
||||
valueAndUnit = StringUtils.getTemperatureParts(getContext(), sensorDataSet.temperature().data());
|
||||
sensorName = sensorDataSet.temperature().sensorNameOrAddress();
|
||||
} else {
|
||||
valueAndUnit = StringUtils.getTemperatureParts(getContext(), null);
|
||||
}
|
||||
|
||||
getBinding().statsValue.setText(valueAndUnit.first);
|
||||
getBinding().statsUnit.setText(valueAndUnit.second);
|
||||
getBinding().statsDescriptionMain.setText(R.string.stats_sensors_temperature);
|
||||
|
||||
getBinding().statsDescriptionSecondary.setText(sensorName);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SensorCadence extends SensorStatisticsViewHolder {
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,7 +41,8 @@ limitations under the License.
|
||||
|
||||
<string name="sensor_unit_beats_per_minute" translatable="false">bpm</string>
|
||||
<string name="sensor_unit_rounds_per_minute" translatable="false">rpm</string>
|
||||
<string name="sensor_unit_power" translatable="false">w</string>
|
||||
<string name="sensor_unit_power" translatable="false">W</string>
|
||||
<string name="sensor_unit_temperature" translatable="false">C</string>
|
||||
|
||||
<string name="value_unknown" translatable="false">-</string>
|
||||
<string name="empty" translatable="false" />
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
<string name="settings_reset_key" translatable="false">settingsReset</string>
|
||||
|
||||
<string name="settings_sensor_bluetooth_heart_rate_key" translatable="false">bluetoothSensor</string>
|
||||
<string name="settings_sensor_bluetooth_temperature_key" translatable="false">bluetoothTemperature</string>
|
||||
<string name="settings_sensor_bluetooth_cycling_cadence_key" translatable="false">bluetoothCyclingCadenceSensor</string>
|
||||
<string name="settings_sensor_bluetooth_cycling_speed_key" translatable="false">bluetoothCyclingSpeedSensor</string>
|
||||
<string name="settings_sensor_bluetooth_cycling_power_key" translatable="false">bluetoothCyclingPowerSensor</string>
|
||||
@@ -361,6 +362,7 @@
|
||||
<string name="stats_custom_layout_coordinates_key" translatable="false">coordinates</string>
|
||||
<string name="stats_custom_layout_heart_rate_key" translatable="false">heart_rate</string>
|
||||
<string name="stats_custom_layout_average_heart_rate_key" translatable="false">average_heart_rate</string>
|
||||
<string name="stats_custom_layout_temperature_key" translatable="false">temperature</string>
|
||||
<string name="stats_custom_layout_cadence_key" translatable="false">cadence</string>
|
||||
<string name="stats_custom_layout_average_cadence_key" translatable="false">average_cadence</string>
|
||||
<string name="stats_custom_layout_power_key" translatable="false">power</string>
|
||||
@@ -370,6 +372,7 @@
|
||||
Every array has two items:
|
||||
- Key value for the dataField.
|
||||
- Comma separated flags for: visible, primary and span/wide for the dataField.
|
||||
TODO: refactor, so this data is not stored here, but in de.dennisguse.opentracks.viewmodels.Mapping. No need to have two places.
|
||||
-->
|
||||
<string-array name="stats_custom_layout_fields_default_value_0">
|
||||
<item>@string/stats_custom_layout_distance_key</item>
|
||||
@@ -455,6 +458,10 @@
|
||||
<item>@string/stats_custom_layout_clock_key</item>
|
||||
<item>0,0,0</item>
|
||||
</string-array>
|
||||
<string-array name="stats_custom_layout_fields_default_value_21">
|
||||
<item>@string/stats_custom_layout_temperature_key</item>
|
||||
<item>0,0,0</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Stats empty values -->
|
||||
<string name="stats_empty_value_integer" translatable="false">0</string>
|
||||
|
||||
@@ -173,6 +173,7 @@ limitations under the License.
|
||||
<string name="description_speed_ms">Speed (m/s)</string>
|
||||
<string name="description_sensor_cadence">Cadence (rpm)</string>
|
||||
<string name="description_sensor_heart_rate">Heart rate (bpm)</string>
|
||||
<string name="description_sensor_temperature">Temperature (Celsius)</string>
|
||||
<string name="description_sensor_power">Power (W)</string>
|
||||
<string name="description_default_speed_or_pace">By activity type</string>
|
||||
<string name="description_speed_imperial">Speed (mi/hr)</string>
|
||||
@@ -312,6 +313,7 @@ limitations under the License.
|
||||
<string name="sensor_state_heart_rate_unit">bpm</string>
|
||||
<string name="sensor_state_heart_rate_value">%1$d bpm</string>
|
||||
<string name="sensor_state_power">Power</string>
|
||||
<string name="sensor_state_temperature">Thermometer</string>
|
||||
<string name="sensor_state_pressure">Barometer</string>
|
||||
<string name="sensor_state_power_avg">Avg Power</string>
|
||||
<string name="sensor_state_power_max">Max Power</string>
|
||||
@@ -471,6 +473,7 @@ limitations under the License.
|
||||
<string name="stats_total_time">Total time</string>
|
||||
<string name="stats_split_interval">Split interval</string>
|
||||
<string name="stats_sensors_heart_rate">Heart rate</string>
|
||||
<string name="stats_sensors_temperature">Temperature</string>
|
||||
<string name="stats_sensors_cadence">Cadence</string>
|
||||
<string name="stats_sensors_power">Power</string>
|
||||
<string name="stats_clock">Clock</string>
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
android:key="@string/settings_sensor_heart_rate_max_key"
|
||||
android:title="@string/settings_sensor_heart_rate_max"
|
||||
app:useSimpleSummaryProvider="true" />
|
||||
<de.dennisguse.opentracks.settings.bluetooth.BluetoothLeTemperaturePreference
|
||||
android:defaultValue="@string/sensor_type_value_none"
|
||||
android:key="@string/settings_sensor_bluetooth_temperature_key"
|
||||
android:title="@string/sensor_state_temperature" />
|
||||
<de.dennisguse.opentracks.settings.bluetooth.BluetoothLePressurePreference
|
||||
android:defaultValue="@string/sensor_type_value_none"
|
||||
android:key="@string/settings_sensor_bluetooth_pressure_key"
|
||||
|
||||
Reference in New Issue
Block a user