mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-25 16:15:55 +01:00
Fix normal activity samples being inserted into workout samples in HuaweiSampleProvider (#4126)
Co-authored-by: BrunoWallner <b.lucab1211@gmail.com> Co-committed-by: BrunoWallner <b.lucab1211@gmail.com>
This commit is contained in:
parent
409a296666
commit
9f566fb7d9
@ -47,7 +47,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
|||||||
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData;
|
import nodomain.freeyourgadget.gadgetbridge.devices.huawei.packets.FitnessData;
|
||||||
|
|
||||||
public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivitySample> {
|
public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivitySample> {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We save all data by saving a marker at the begin and end.
|
* We save all data by saving a marker at the begin and end.
|
||||||
* Meaning of fields that are not self-explanatory:
|
* Meaning of fields that are not self-explanatory:
|
||||||
@ -302,7 +301,7 @@ public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivityS
|
|||||||
* that is necessary for proper displaying of data.
|
* that is necessary for proper displaying of data.
|
||||||
*
|
*
|
||||||
* This essentially boils down to four things:
|
* This essentially boils down to four things:
|
||||||
* - It adds in the workout heart rate data
|
* - It adds in the workout heart rate data without activity data in between
|
||||||
* - It adds a sample with intensity zero before start markers (start of block)
|
* - It adds a sample with intensity zero before start markers (start of block)
|
||||||
* - It adds a sample with intensity zero after end markers (end of block)
|
* - It adds a sample with intensity zero after end markers (end of block)
|
||||||
* - It modifies some blocks so the sleep data gets handled correctly
|
* - It modifies some blocks so the sleep data gets handled correctly
|
||||||
@ -314,10 +313,10 @@ public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivityS
|
|||||||
@Override
|
@Override
|
||||||
protected List<HuaweiActivitySample> getGBActivitySamples(int timestamp_from, int timestamp_to) {
|
protected List<HuaweiActivitySample> getGBActivitySamples(int timestamp_from, int timestamp_to) {
|
||||||
// Note that the result of this function has to be sorted by timestamp!
|
// Note that the result of this function has to be sorted by timestamp!
|
||||||
|
|
||||||
List<HuaweiActivitySample> rawSamples = getRawOrderedActivitySamples(timestamp_from, timestamp_to);
|
List<HuaweiActivitySample> rawSamples = getRawOrderedActivitySamples(timestamp_from, timestamp_to);
|
||||||
List<HuaweiWorkoutDataSample> workoutSamples = getRawOrderedWorkoutSamplesWithHeartRate(timestamp_from, timestamp_to);
|
List<HuaweiWorkoutDataSample> workoutSamples = getRawOrderedWorkoutSamplesWithHeartRate(timestamp_from, timestamp_to);
|
||||||
|
|
||||||
|
List<int[]> workoutSpans = getWorkoutSpans(rawSamples, workoutSamples, 5);
|
||||||
List<HuaweiActivitySample> processedSamples = new ArrayList<>();
|
List<HuaweiActivitySample> processedSamples = new ArrayList<>();
|
||||||
|
|
||||||
Iterator<HuaweiActivitySample> itRawSamples = rawSamples.iterator();
|
Iterator<HuaweiActivitySample> itRawSamples = rawSamples.iterator();
|
||||||
@ -337,38 +336,83 @@ public class HuaweiSampleProvider extends AbstractSampleProvider<HuaweiActivityS
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (nextRawSample != null || nextWorkoutSample != null) {
|
while (nextRawSample != null || nextWorkoutSample != null) {
|
||||||
if (nextRawSample == null) {
|
if (nextRawSample == null || (nextWorkoutSample != null && nextWorkoutSample.getTimestamp() < nextRawSample.getTimestamp())) {
|
||||||
processWorkoutSample(processedSamples, state, nextWorkoutSample);
|
processWorkoutSample(processedSamples, state, nextWorkoutSample);
|
||||||
|
nextWorkoutSample = itWorkoutSamples.hasNext() ? itWorkoutSamples.next() : null;
|
||||||
nextWorkoutSample = null;
|
|
||||||
if (itWorkoutSamples.hasNext())
|
|
||||||
nextWorkoutSample = itWorkoutSamples.next();
|
|
||||||
} else if (nextWorkoutSample == null) {
|
|
||||||
processRawSample(processedSamples, state, nextRawSample);
|
|
||||||
|
|
||||||
nextRawSample = null;
|
|
||||||
if (itRawSamples.hasNext())
|
|
||||||
nextRawSample = itRawSamples.next();
|
|
||||||
} else if (nextRawSample.getTimestamp() > nextWorkoutSample.getTimestamp()) {
|
|
||||||
processWorkoutSample(processedSamples, state, nextWorkoutSample);
|
|
||||||
|
|
||||||
nextWorkoutSample = null;
|
|
||||||
if (itWorkoutSamples.hasNext())
|
|
||||||
nextWorkoutSample = itWorkoutSamples.next();
|
|
||||||
} else {
|
} else {
|
||||||
|
boolean sampleInWorkout = isInWorkout(workoutSpans, nextRawSample.getTimestamp());
|
||||||
|
if (sampleInWorkout) {
|
||||||
|
nextRawSample.setHeartRate(ActivitySample.NOT_MEASURED);
|
||||||
|
nextRawSample.setRawIntensity(0);
|
||||||
|
}
|
||||||
processRawSample(processedSamples, state, nextRawSample);
|
processRawSample(processedSamples, state, nextRawSample);
|
||||||
|
nextRawSample = itRawSamples.hasNext() ? itRawSamples.next() : null;
|
||||||
nextRawSample = null;
|
|
||||||
if (itRawSamples.hasNext())
|
|
||||||
nextRawSample = itRawSamples.next();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
processedSamples = interpolate(processedSamples);
|
processedSamples = interpolate(processedSamples);
|
||||||
|
|
||||||
return processedSamples;
|
return processedSamples;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculates the timespans: [start, end] of workouts
|
||||||
|
* Normal activities should not be processed when in middle of workout
|
||||||
|
**/
|
||||||
|
private List<int[]> getWorkoutSpans(List<HuaweiActivitySample> activity, List<HuaweiWorkoutDataSample> workout, int threshold) {
|
||||||
|
List<int[]> validActivitySpans = new ArrayList<>();
|
||||||
|
|
||||||
|
Iterator<HuaweiActivitySample> activityIterator = activity.iterator();
|
||||||
|
Iterator<HuaweiWorkoutDataSample> workoutIterator = workout.iterator();
|
||||||
|
|
||||||
|
HuaweiActivitySample currentActivity = activityIterator.hasNext() ? activityIterator.next() : null;
|
||||||
|
HuaweiWorkoutDataSample currentWorkout = workoutIterator.hasNext() ? workoutIterator.next() : null;
|
||||||
|
|
||||||
|
int consecutiveActivityCount = 0;
|
||||||
|
Integer spanStart = null;
|
||||||
|
|
||||||
|
int workoutEnd = 0;
|
||||||
|
while (currentActivity != null || currentWorkout != null) {
|
||||||
|
if (currentWorkout == null || (currentActivity != null && currentActivity.getTimestamp() < currentWorkout.getTimestamp())) {
|
||||||
|
// handle activity
|
||||||
|
if (spanStart != null) {
|
||||||
|
// We're in workout, check for activity interruption
|
||||||
|
consecutiveActivityCount++;
|
||||||
|
if (consecutiveActivityCount > threshold) {
|
||||||
|
// Enough activity samples to interrupt the workout
|
||||||
|
validActivitySpans.add(new int[]{spanStart, workoutEnd});
|
||||||
|
spanStart = null;
|
||||||
|
consecutiveActivityCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
currentActivity = activityIterator.hasNext() ? activityIterator.next() : null;
|
||||||
|
} else {
|
||||||
|
// handle workout
|
||||||
|
if (spanStart == null) {
|
||||||
|
spanStart = currentWorkout.getTimestamp();
|
||||||
|
}
|
||||||
|
workoutEnd = currentWorkout.getTimestamp();
|
||||||
|
consecutiveActivityCount = 0;
|
||||||
|
currentWorkout = workoutIterator.hasNext() ? workoutIterator.next() : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there's an open valid span at the end, close it
|
||||||
|
if (spanStart != null) {
|
||||||
|
validActivitySpans.add(new int[]{spanStart, workoutEnd});
|
||||||
|
}
|
||||||
|
|
||||||
|
return validActivitySpans;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isInWorkout(List<int[]> validSpans, int timestamp) {
|
||||||
|
for (int[] span : validSpans) {
|
||||||
|
if (timestamp > span[0] && timestamp < span[1]) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private List<HuaweiActivitySample> interpolate(List<HuaweiActivitySample> processedSamples) {
|
private List<HuaweiActivitySample> interpolate(List<HuaweiActivitySample> processedSamples) {
|
||||||
List<HuaweiActivitySample> retv = new ArrayList<>();
|
List<HuaweiActivitySample> retv = new ArrayList<>();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user