forked from upstream-mirrors/OpenTracks
Cadence set to 0 when connected but user is not pedaling. Fixes #931.
Speed set to 0 when connected but last value is outdated. Fixes #930. Bug: overflow when reset sensors (cadence and speed). Fixes #833. Moving time stops when is not moving (the last track point is not moving) and restarts when last track point is moving.
This commit is contained in:
@@ -50,8 +50,14 @@ public abstract class SensorData<T> {
|
||||
return value != null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
protected abstract T getNoneValue();
|
||||
|
||||
public T getValue() {
|
||||
return value;
|
||||
if (isRecent()) {
|
||||
return value;
|
||||
}
|
||||
return getNoneValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +69,7 @@ public abstract class SensorData<T> {
|
||||
/**
|
||||
* Is the data recent considering the current time.
|
||||
*/
|
||||
public boolean isRecent() {
|
||||
private boolean isRecent() {
|
||||
return Instant.now()
|
||||
.isBefore(time.plus(BluetoothRemoteSensorManager.MAX_SENSOR_DATE_SET_AGE_MS));
|
||||
}
|
||||
|
||||
@@ -59,17 +59,30 @@ public final class SensorDataCycling {
|
||||
return crankRevolutionsTime;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Float getNoneValue() {
|
||||
return 0f;
|
||||
}
|
||||
|
||||
public void compute(Cadence previous) {
|
||||
if (hasData() && previous != null && previous.hasData()) {
|
||||
float timeDiff_ms = UintUtils.diff(crankRevolutionsTime, previous.crankRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * UnitConversions.S_TO_MS;
|
||||
if (timeDiff_ms <= 0) {
|
||||
Log.e(TAG, "Timestamps difference is invalid: cannot compute cadence.");
|
||||
value = null;
|
||||
} else {
|
||||
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
||||
float cadence_ms = crankDiff / timeDiff_ms;
|
||||
value = (float) (cadence_ms / UnitConversions.MS_TO_S / UnitConversions.S_TO_MIN);
|
||||
return;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
Log.e(TAG, "Crank revolutions count difference is invalid: cannot compute cadence.");
|
||||
return;
|
||||
}
|
||||
|
||||
long crankDiff = UintUtils.diff(crankRevolutionsCount, previous.crankRevolutionsCount, UintUtils.UINT32_MAX);
|
||||
float cadence_ms = crankDiff / timeDiff_ms;
|
||||
value = (float) (cadence_ms / UnitConversions.MS_TO_S / UnitConversions.S_TO_MIN);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +134,16 @@ public final class SensorDataCycling {
|
||||
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(DistanceSpeed previous, Distance wheelCircumference) {
|
||||
if (hasData() && previous != null && previous.hasData()) {
|
||||
float timeDiff_ms = UintUtils.diff(wheelRevolutionsTime, previous.wheelRevolutionsTime, UintUtils.UINT16_MAX) / 1024f * UnitConversions.S_TO_MS;
|
||||
@@ -131,6 +154,10 @@ public final class SensorDataCycling {
|
||||
return;
|
||||
}
|
||||
|
||||
if (wheelRevolutionsCount < previous.wheelRevolutionsCount) {
|
||||
Log.e(TAG, "Wheel revolutions count difference is invalid: cannot compute speed.");
|
||||
return;
|
||||
}
|
||||
long wheelDiff = UintUtils.diff(wheelRevolutionsCount, previous.wheelRevolutionsCount, UintUtils.UINT32_MAX);
|
||||
|
||||
Distance distance = wheelCircumference.multipliedBy(wheelDiff);
|
||||
@@ -217,6 +244,12 @@ public final class SensorDataCycling {
|
||||
public DistanceSpeed getDistanceSpeed() {
|
||||
return this.value != null ? this.value.second : null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Pair<Cadence, DistanceSpeed> getNoneValue() {
|
||||
return new Pair<>(null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,4 +18,10 @@ public class SensorDataCyclingPower extends SensorData<Float> {
|
||||
public String toString() {
|
||||
return super.toString() + " power=" + value;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Float getNoneValue() {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,4 +18,10 @@ public class SensorDataHeartRate extends SensorData<Float> {
|
||||
public String toString() {
|
||||
return super.toString() + " heart=" + value;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Float getNoneValue() {
|
||||
return 0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,6 +53,16 @@ public final class SensorDataRunning extends SensorData<SensorDataRunning.Data>
|
||||
return totalDistance;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Data getNoneValue() {
|
||||
if (value != null) {
|
||||
return new Data(Speed.zero(), 0f, ((Data) value).distance);
|
||||
} else {
|
||||
return new Data(Speed.zero(), 0f, Distance.of(0));
|
||||
}
|
||||
}
|
||||
|
||||
public void compute(SensorDataRunning previous) {
|
||||
Distance overallDistance = null;
|
||||
if (hasTotalDistance() && previous != null && previous.hasTotalDistance()) {
|
||||
|
||||
@@ -172,6 +172,7 @@ class TrackRecordingManager {
|
||||
insertTrackPoint(trackId, trackPoint);
|
||||
|
||||
isIdle = false;
|
||||
|
||||
lastTrackPoint = trackPoint;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -178,7 +178,9 @@ public class TrackStatisticsUpdater {
|
||||
}
|
||||
|
||||
// Update moving time
|
||||
currentSegment.addMovingTime(movingTime);
|
||||
if (lastTrackPoint.isMoving()) {
|
||||
currentSegment.addMovingTime(movingTime);
|
||||
}
|
||||
|
||||
// Update max speed
|
||||
if (trackPoint.hasSpeed() && lastTrackPoint.hasSpeed()) {
|
||||
|
||||
@@ -53,7 +53,7 @@ public class StatisticDataBuilder {
|
||||
boolean reportSpeed = fieldKey.equals("speed");
|
||||
title = fieldKey.equals("speed") ? context.getString(R.string.stats_speed) : context.getString(R.string.stats_pace);
|
||||
Speed speed = latestTrackPoint != null && latestTrackPoint.hasSpeed() ? latestTrackPoint.getSpeed() : null;
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingDistanceSpeed() != null && sensorDataSet.getCyclingDistanceSpeed().hasValue() && sensorDataSet.getCyclingDistanceSpeed().isRecent()) {
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingDistanceSpeed() != null && sensorDataSet.getCyclingDistanceSpeed().hasValue()) {
|
||||
valueAndUnit = StringUtils.getSpeedParts(context, sensorDataSet.getCyclingDistanceSpeed().getValue().getSpeed(), metricUnits, reportSpeed);
|
||||
description = context.getString(R.string.description_speed_source_sensor, sensorDataSet.getCyclingDistanceSpeed().getSensorNameOrAddress());
|
||||
} else {
|
||||
@@ -99,7 +99,7 @@ public class StatisticDataBuilder {
|
||||
}
|
||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_heart_rate_key))) {
|
||||
title = context.getString(R.string.stats_sensors_heart_rate);
|
||||
if (sensorDataSet != null && sensorDataSet.getHeartRate() != null && sensorDataSet.getHeartRate().hasValue() && sensorDataSet.getHeartRate().isRecent()) {
|
||||
if (sensorDataSet != null && sensorDataSet.getHeartRate() != null && sensorDataSet.getHeartRate().hasValue()) {
|
||||
valueAndUnit = StringUtils.getHeartRateParts(context, sensorDataSet.getHeartRate().getValue());
|
||||
description = sensorDataSet.getHeartRate().getSensorNameOrAddress();
|
||||
} else {
|
||||
@@ -108,7 +108,7 @@ public class StatisticDataBuilder {
|
||||
}
|
||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_cadence_key))) {
|
||||
title = context.getString(R.string.stats_sensors_cadence);
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingCadence() != null && sensorDataSet.getCyclingCadence().hasValue() && sensorDataSet.getCyclingCadence().isRecent()) {
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingCadence() != null && sensorDataSet.getCyclingCadence().hasValue()) {
|
||||
valueAndUnit = StringUtils.getCadenceParts(context, sensorDataSet.getCyclingCadence().getValue());
|
||||
description = sensorDataSet.getCyclingCadence().getSensorNameOrAddress();
|
||||
} else {
|
||||
@@ -117,7 +117,7 @@ public class StatisticDataBuilder {
|
||||
}
|
||||
} else if (fieldKey.equals(context.getString(R.string.stats_custom_layout_power_key))) {
|
||||
title = context.getString(R.string.stats_sensors_power);
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingPower() != null && sensorDataSet.getCyclingPower().hasValue() && sensorDataSet.getCyclingPower().isRecent()) {
|
||||
if (sensorDataSet != null && sensorDataSet.getCyclingPower() != null && sensorDataSet.getCyclingPower().hasValue()) {
|
||||
valueAndUnit = StringUtils.getPowerParts(context, sensorDataSet.getCyclingPower().getValue());
|
||||
description = sensorDataSet.getCyclingPower().getSensorNameOrAddress();
|
||||
} else {
|
||||
@@ -142,13 +142,13 @@ public class StatisticDataBuilder {
|
||||
if (sensorDataSet == null) {
|
||||
return sensorDataList;
|
||||
}
|
||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_heart_rate))) && sensorDataSet.getHeartRate() != null && sensorDataSet.getHeartRate().hasValue() && sensorDataSet.getHeartRate().isRecent()) {
|
||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_heart_rate))) && sensorDataSet.getHeartRate() != null && sensorDataSet.getHeartRate().hasValue()) {
|
||||
sensorDataList.add(build(context, recordingData, "heart_rate", true, metricUnits));
|
||||
}
|
||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_cadence))) && sensorDataSet.getCyclingCadence() != null && sensorDataSet.getCyclingCadence().hasValue() && sensorDataSet.getCyclingCadence().isRecent()) {
|
||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_cadence))) && sensorDataSet.getCyclingCadence() != null && sensorDataSet.getCyclingCadence().hasValue()) {
|
||||
sensorDataList.add(build(context, recordingData, "cadence", true, metricUnits));
|
||||
}
|
||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_power))) && sensorDataSet.getCyclingPower() != null && sensorDataSet.getCyclingPower().hasValue() && sensorDataSet.getCyclingPower().isRecent()) {
|
||||
if (statisticDataList.stream().noneMatch(i -> i.getField().getTitle().equals(context.getString(R.string.stats_sensors_power))) && sensorDataSet.getCyclingPower() != null && sensorDataSet.getCyclingPower().hasValue()) {
|
||||
sensorDataList.add(build(context, recordingData, "power", true, metricUnits));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user