1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-30 22:12:55 +01:00

Garmin: Fix edge case in sleep overlay

If the sleep session ends outside the queried time range, we need to
fetch the next sleep stage outside the range so that we can overlay it
properly.
This commit is contained in:
José Rebelo 2024-05-19 23:35:26 +01:00 committed by Daniele Gobbetti
parent 8e1511bd6e
commit 5224244f74
3 changed files with 73 additions and 25 deletions

View File

@ -119,6 +119,25 @@ public abstract class AbstractTimeSampleProvider<T extends AbstractTimeSample> i
return !samples.isEmpty() ? samples.get(0) : null; return !samples.isEmpty() ? samples.get(0) : null;
} }
public T getNextSampleAfter(final long timestampFrom) {
final Device dbDevice = DBHelper.findDevice(getDevice(), getSession());
if (dbDevice == null) {
// no device, no sample
return null;
}
final Property deviceIdSampleProp = getDeviceIdentifierSampleProperty();
final Property timestampSampleProp = getTimestampSampleProperty();
final List<T> samples = getSampleDao().queryBuilder()
.where(deviceIdSampleProp.eq(dbDevice.getId()),
timestampSampleProp.ge(timestampFrom))
.orderAsc(getTimestampSampleProperty())
.limit(1)
.list();
return !samples.isEmpty() ? samples.get(0) : null;
}
@Nullable @Nullable
@Override @Override
public T getFirstSample() { public T getFirstSample() {

View File

@ -121,7 +121,7 @@ public class GarminActivitySampleProvider extends AbstractSampleProvider<GarminA
final GarminEventSampleProvider eventSampleProvider = new GarminEventSampleProvider(getDevice(), getSession()); final GarminEventSampleProvider eventSampleProvider = new GarminEventSampleProvider(getDevice(), getSession());
final List<GarminEventSample> sleepEventSamples = eventSampleProvider.getSleepEvents( final List<GarminEventSample> sleepEventSamples = eventSampleProvider.getSleepEvents(
timestamp_from * 1000L - 86400000L, timestamp_from * 1000L,
timestamp_to * 1000L timestamp_to * 1000L
); );
if (!sleepEventSamples.isEmpty()) { if (!sleepEventSamples.isEmpty()) {
@ -138,8 +138,19 @@ public class GarminActivitySampleProvider extends AbstractSampleProvider<GarminA
} }
final GarminSleepStageSampleProvider sleepStagesSampleProvider = new GarminSleepStageSampleProvider(getDevice(), getSession()); final GarminSleepStageSampleProvider sleepStagesSampleProvider = new GarminSleepStageSampleProvider(getDevice(), getSession());
// Retrieve the next stage after this time range
final GarminEventSample nextSleepStageAfterRange = eventSampleProvider.getNextSleepEventAfter(timestamp_to * 1000L);
if (nextSleepStageAfterRange != null && nextSleepStageAfterRange.getEventType() == 1) {
// Sleep session actually ends outside of this range, we need to fetch the next sleep stage
final GarminSleepStageSample nextStage = sleepStagesSampleProvider.getNextSampleAfter(timestamp_to * 1000L);
if (nextStage != null) {
stagesMap.put(nextStage.getTimestamp(), toActivityKind(nextStage));
}
}
final List<GarminSleepStageSample> stageSamples = sleepStagesSampleProvider.getAllSamples( final List<GarminSleepStageSample> stageSamples = sleepStagesSampleProvider.getAllSamples(
timestamp_from * 1000L - 86400000L, timestamp_from * 1000L,
timestamp_to * 1000L timestamp_to * 1000L
); );
@ -148,29 +159,7 @@ public class GarminActivitySampleProvider extends AbstractSampleProvider<GarminA
LOG.debug("Found {} sleep stage samples between {} and {}", stageSamples.size(), timestamp_from, timestamp_to); LOG.debug("Found {} sleep stage samples between {} and {}", stageSamples.size(), timestamp_from, timestamp_to);
for (final GarminSleepStageSample stageSample : stageSamples) { for (final GarminSleepStageSample stageSample : stageSamples) {
final int activityKind; stagesMap.put(stageSample.getTimestamp(), toActivityKind(stageSample));
final FieldDefinitionSleepStage.SleepStage sleepStage = FieldDefinitionSleepStage.SleepStage.fromId(stageSample.getStage());
if (sleepStage == null) {
LOG.error("Unknown sleep stage for {}", stageSample.getStage());
continue;
}
switch (sleepStage) {
case LIGHT:
activityKind = ActivityKind.TYPE_LIGHT_SLEEP;
break;
case DEEP:
activityKind = ActivityKind.TYPE_DEEP_SLEEP;
break;
case REM:
activityKind = ActivityKind.TYPE_REM_SLEEP;
break;
default:
activityKind = ActivityKind.TYPE_UNKNOWN;
break;
}
stagesMap.put(stageSample.getTimestamp(), activityKind);
} }
} }
@ -196,4 +185,23 @@ public class GarminActivitySampleProvider extends AbstractSampleProvider<GarminA
} }
} }
} }
private int toActivityKind(final GarminSleepStageSample stageSample) {
final FieldDefinitionSleepStage.SleepStage sleepStage = FieldDefinitionSleepStage.SleepStage.fromId(stageSample.getStage());
if (sleepStage == null) {
LOG.error("Unknown sleep stage for {}", stageSample.getStage());
return ActivityKind.TYPE_UNKNOWN;
}
switch (sleepStage) {
case LIGHT:
return ActivityKind.TYPE_LIGHT_SLEEP;
case DEEP:
return ActivityKind.TYPE_DEEP_SLEEP;
case REM:
return ActivityKind.TYPE_REM_SLEEP;
}
return ActivityKind.TYPE_UNKNOWN;
}
} }

View File

@ -77,4 +77,25 @@ public class GarminEventSampleProvider extends AbstractTimeSampleProvider<Garmin
detachFromSession(); detachFromSession();
return samples; return samples;
} }
public GarminEventSample getNextSleepEventAfter(final long timestampFrom) {
final Device dbDevice = DBHelper.findDevice(getDevice(), getSession());
if (dbDevice == null) {
// no device, no sample
return null;
}
final Property deviceIdSampleProp = getDeviceIdentifierSampleProperty();
final Property timestampSampleProp = getTimestampSampleProperty();
final List<GarminEventSample> samples = getSampleDao().queryBuilder()
.where(
deviceIdSampleProp.eq(dbDevice.getId()),
timestampSampleProp.ge(timestampFrom),
GarminEventSampleDao.Properties.Event.eq(74)
).orderAsc(getTimestampSampleProperty())
.limit(1)
.list();
return !samples.isEmpty() ? samples.get(0) : null;
}
} }