mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge.git
synced 2025-01-10 09:01:55 +01:00
Moyoung: Implement syncing sleep data
This commit is contained in:
parent
938085b5fa
commit
0258905b4a
@ -56,7 +56,7 @@ public class GBDaoGenerator {
|
||||
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
final Schema schema = new Schema(93, MAIN_PACKAGE + ".entities");
|
||||
final Schema schema = new Schema(94, MAIN_PACKAGE + ".entities");
|
||||
|
||||
Entity userAttributes = addUserAttributes(schema);
|
||||
Entity user = addUserInfo(schema, userAttributes);
|
||||
@ -157,6 +157,7 @@ public class GBDaoGenerator {
|
||||
addMoyoungHeartRateSample(schema, user, device);
|
||||
addMoyoungSpo2Sample(schema, user, device);
|
||||
addMoyoungBloodPressureSample(schema, user, device);
|
||||
addMoyoungSleepStageSample(schema, user, device);
|
||||
|
||||
addHuaweiActivitySample(schema, user, device);
|
||||
|
||||
@ -1103,6 +1104,13 @@ public class GBDaoGenerator {
|
||||
return bpSample;
|
||||
}
|
||||
|
||||
private static Entity addMoyoungSleepStageSample(Schema schema, Entity user, Entity device) {
|
||||
Entity sleepStageSample = addEntity(schema, "MoyoungSleepStageSample");
|
||||
addCommonTimeSampleProperties("AbstractTimeSample", sleepStageSample, user, device);
|
||||
sleepStageSample.addIntProperty("stage").notNull();
|
||||
return sleepStageSample;
|
||||
}
|
||||
|
||||
private static void addCommonActivitySampleProperties(String superClass, Entity activitySample, Entity user, Entity device) {
|
||||
activitySample.setSuperclass(superClass);
|
||||
activitySample.addImport(MAIN_PACKAGE + ".devices.SampleProvider");
|
||||
|
@ -75,4 +75,9 @@ public class ColmiI28UltraCoordinator extends AbstractMoyoungDeviceCoordinator {
|
||||
public int getWorldClocksLabelLength() {
|
||||
return 30;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRemSleep() {
|
||||
return true;
|
||||
}
|
||||
}
|
@ -173,6 +173,7 @@ public class MoyoungConstants {
|
||||
public static final byte SLEEP_SOBER = 0;
|
||||
public static final byte SLEEP_LIGHT = 1;
|
||||
public static final byte SLEEP_RESTFUL = 2;
|
||||
public static final byte SLEEP_REM = 3;
|
||||
|
||||
public static final byte CMD_QUERY_SLEEP_ACTION = 58; // (*) {i} -> {hour, x[60]}
|
||||
|
||||
|
@ -24,6 +24,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
@ -41,6 +42,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungHeartRateSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSleepStageSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
|
||||
@ -74,6 +76,7 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
|
||||
public static final int ACTIVITY_SLEEP_RESTFUL = 17;
|
||||
public static final int ACTIVITY_SLEEP_START = 18;
|
||||
public static final int ACTIVITY_SLEEP_END = 19;
|
||||
public static final int ACTIVITY_SLEEP_REM = 20;
|
||||
|
||||
public MoyoungActivitySampleProvider(GBDevice device, DaoSession session) {
|
||||
super(device, session);
|
||||
@ -115,6 +118,8 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
|
||||
return ActivityKind.LIGHT_SLEEP;
|
||||
else if (rawType == ACTIVITY_SLEEP_RESTFUL)
|
||||
return ActivityKind.DEEP_SLEEP;
|
||||
else if (rawType == ACTIVITY_SLEEP_REM)
|
||||
return ActivityKind.REM_SLEEP;
|
||||
else if (rawType == ACTIVITY_SLEEP_START || rawType == ACTIVITY_SLEEP_END)
|
||||
return ActivityKind.NOT_MEASURED;
|
||||
else if (rawType == ACTIVITY_TRAINING_WALK)
|
||||
@ -142,12 +147,29 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
|
||||
return ACTIVITY_SLEEP_LIGHT;
|
||||
else if (activityKind == ActivityKind.DEEP_SLEEP)
|
||||
return ACTIVITY_SLEEP_RESTFUL;
|
||||
else if (activityKind == ActivityKind.REM_SLEEP)
|
||||
return ACTIVITY_SLEEP_REM;
|
||||
else if (activityKind == ActivityKind.ACTIVITY)
|
||||
return ACTIVITY_NOT_MEASURED; // TODO: ?
|
||||
else
|
||||
throw new IllegalArgumentException("Invalid Gadgetbridge activity kind: " + activityKind);
|
||||
}
|
||||
|
||||
final ActivityKind sleepStageToActivityKind(final int sleepStage) {
|
||||
switch (sleepStage) {
|
||||
case MoyoungConstants.SLEEP_LIGHT:
|
||||
return ActivityKind.LIGHT_SLEEP;
|
||||
case MoyoungConstants.SLEEP_RESTFUL:
|
||||
return ActivityKind.DEEP_SLEEP;
|
||||
case MoyoungConstants.SLEEP_REM:
|
||||
return ActivityKind.REM_SLEEP;
|
||||
case MoyoungConstants.SLEEP_SOBER:
|
||||
return ActivityKind.AWAKE_SLEEP;
|
||||
default:
|
||||
return ActivityKind.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public float normalizeIntensity(int rawIntensity) {
|
||||
if (rawIntensity == ActivitySample.NOT_MEASURED)
|
||||
@ -177,23 +199,10 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
|
||||
}
|
||||
|
||||
overlayHeartRate(sampleByTs, timestamp_from, timestamp_to);
|
||||
// overlaySleep(sampleByTs, timestamp_from, timestamp_to);
|
||||
|
||||
// Add empty dummy samples every 5 min to make sure the charts and stats aren't too malformed
|
||||
// This is necessary due to the Colmi rings just reporting steps/calories/distance aggregates per hour
|
||||
// for (int i=timestamp_from; i<=timestamp_to; i+=300) {
|
||||
// MoyoungActivitySample sample = sampleByTs.get(i);
|
||||
// if (sample == null) {
|
||||
// sample = new MoyoungActivitySample();
|
||||
// sample.setTimestamp(i);
|
||||
// sample.setProvider(this);
|
||||
// sample.setRawKind(ActivitySample.NOT_MEASURED);
|
||||
// sampleByTs.put(i, sample);
|
||||
// }
|
||||
// }
|
||||
overlaySleep(sampleByTs, timestamp_from, timestamp_to);
|
||||
|
||||
final List<MoyoungActivitySample> finalSamples = new ArrayList<>(sampleByTs.values());
|
||||
Collections.sort(finalSamples, (a, b) -> Integer.compare(a.getTimestamp(), b.getTimestamp()));
|
||||
Collections.sort(finalSamples, Comparator.comparingInt(MoyoungActivitySample::getTimestamp));
|
||||
|
||||
final long nanoEnd = System.nanoTime();
|
||||
final long executionTime = (nanoEnd - nanoStart) / 1000000;
|
||||
@ -221,6 +230,64 @@ public class MoyoungActivitySampleProvider extends AbstractSampleProvider<Moyoun
|
||||
}
|
||||
}
|
||||
|
||||
private void overlaySleep(final Map<Integer, MoyoungActivitySample> sampleByTs, final int timestamp_from, final int timestamp_to) {
|
||||
final MoyoungSleepStageSampleProvider sleepStageSampleProvider = new MoyoungSleepStageSampleProvider(getDevice(), getSession());
|
||||
final List<MoyoungSleepStageSample> sleepStageSamples = sleepStageSampleProvider.getAllSamples(timestamp_from * 1000L, timestamp_to * 1000L);
|
||||
|
||||
// Retrieve the last stage before this time range, as the user could have been asleep during
|
||||
// the range transition
|
||||
final MoyoungSleepStageSample lastSleepStageBeforeRange = sleepStageSampleProvider.getLastSampleBefore(timestamp_from * 1000L);
|
||||
if (lastSleepStageBeforeRange != null && lastSleepStageBeforeRange.getStage() != MoyoungConstants.SLEEP_SOBER) {
|
||||
LOG.debug("Last sleep stage before range: ts={}, stage={}", lastSleepStageBeforeRange.getTimestamp(), lastSleepStageBeforeRange.getStage());
|
||||
sleepStageSamples.add(0, lastSleepStageBeforeRange);
|
||||
}
|
||||
// Retrieve the next sample after the time range, as the last stage could exceed it
|
||||
final MoyoungSleepStageSample nextSleepStageAfterRange = sleepStageSampleProvider.getNextSampleAfter(timestamp_to * 1000L);
|
||||
if (nextSleepStageAfterRange != null) {
|
||||
LOG.debug("Next sleep stage after range: ts={}, stage={}", nextSleepStageAfterRange.getTimestamp(), nextSleepStageAfterRange.getStage());
|
||||
sleepStageSamples.add(nextSleepStageAfterRange);
|
||||
}
|
||||
|
||||
if (sleepStageSamples.size() > 1) {
|
||||
LOG.debug("Overlaying with data from {} sleep stage samples", sleepStageSamples.size());
|
||||
} else {
|
||||
LOG.warn("Not overlaying sleep data because more than 1 sleep stage sample is required");
|
||||
return;
|
||||
}
|
||||
|
||||
MoyoungSleepStageSample prevSample = null;
|
||||
for (final MoyoungSleepStageSample sleepStageSample : sleepStageSamples) {
|
||||
if (prevSample == null) {
|
||||
prevSample = sleepStageSample;
|
||||
continue;
|
||||
}
|
||||
final ActivityKind sleepRawKind = sleepStageToActivityKind(prevSample.getStage());
|
||||
if (sleepRawKind.equals(ActivityKind.AWAKE_SLEEP)) {
|
||||
prevSample = sleepStageSample;
|
||||
continue;
|
||||
}
|
||||
// round to the nearest minute, we don't need per-second granularity
|
||||
final int tsSecondsPrev = (int) ((prevSample.getTimestamp() / 1000) / 60) * 60;
|
||||
final int tsSecondsCur = (int) ((sleepStageSample.getTimestamp() / 1000) / 60) * 60;
|
||||
for (int i = tsSecondsPrev; i < tsSecondsCur; i += 60) {
|
||||
if (i < timestamp_from || i > timestamp_to) continue;
|
||||
MoyoungActivitySample sample = sampleByTs.get(i);
|
||||
if (sample == null) {
|
||||
sample = new MoyoungActivitySample();
|
||||
sample.setTimestamp(i);
|
||||
sample.setProvider(this);
|
||||
sampleByTs.put(i, sample);
|
||||
}
|
||||
sample.setRawKind(toRawActivityKind(sleepRawKind));
|
||||
sample.setRawIntensity(ActivitySample.NOT_MEASURED);
|
||||
}
|
||||
prevSample = sleepStageSample;
|
||||
}
|
||||
if (prevSample != null && !sleepStageToActivityKind(prevSample.getStage()).equals(ActivityKind.AWAKE_SLEEP)) {
|
||||
LOG.warn("Last sleep stage sample was not of type awake");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the activity kind from NOT_MEASURED to new_raw_activity_kind on the given range
|
||||
* @param timestamp_from the start timestamp
|
||||
|
@ -0,0 +1,56 @@
|
||||
/* Copyright (C) 2025 Arjan Schrijver
|
||||
|
||||
This file is part of Gadgetbridge.
|
||||
|
||||
Gadgetbridge is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
Gadgetbridge is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
package nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import de.greenrobot.dao.AbstractDao;
|
||||
import de.greenrobot.dao.Property;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractTimeSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSleepStageSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSleepStageSampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
|
||||
public class MoyoungSleepStageSampleProvider extends AbstractTimeSampleProvider<MoyoungSleepStageSample> {
|
||||
public MoyoungSleepStageSampleProvider(final GBDevice device, final DaoSession session) {
|
||||
super(device, session);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AbstractDao<MoyoungSleepStageSample, ?> getSampleDao() {
|
||||
return getSession().getMoyoungSleepStageSampleDao();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Property getTimestampSampleProperty() {
|
||||
return MoyoungSleepStageSampleDao.Properties.Timestamp;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
protected Property getDeviceIdentifierSampleProperty() {
|
||||
return MoyoungSleepStageSampleDao.Properties.DeviceId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoyoungSleepStageSample createSample() {
|
||||
return new MoyoungSleepStageSample();
|
||||
}
|
||||
}
|
@ -72,6 +72,7 @@ import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.MoyoungWeatherToday;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples.MoyoungActivitySampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples.MoyoungBloodPressureSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples.MoyoungHeartRateSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples.MoyoungSleepStageSampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.samples.MoyoungSpo2SampleProvider;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungEnumDeviceVersion;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.moyoung.settings.MoyoungEnumLanguage;
|
||||
@ -87,6 +88,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungActivitySample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungBloodPressureSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungHeartRateSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSleepStageSample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MoyoungSpo2Sample;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
|
||||
@ -1186,8 +1188,13 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
if (data.length % 3 != 0)
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
int prevActivityType = MoyoungActivitySampleProvider.ACTIVITY_SLEEP_START;
|
||||
int prevSampleTimestamp = -1;
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
MoyoungSleepStageSampleProvider provider = new MoyoungSleepStageSampleProvider(getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
User user = DBHelper.getUser(dbHandler.getDaoSession());
|
||||
Device device = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
List<MoyoungSleepStageSample> samples = new ArrayList<>();
|
||||
|
||||
for(int i = 0; i < data.length / 3; i++)
|
||||
{
|
||||
@ -1197,115 +1204,33 @@ public class MoyoungDeviceSupport extends AbstractBTLEDeviceSupport {
|
||||
|
||||
LOG.info("sleep[" + daysAgo + "][" + i + "] type=" + type + ", start_h=" + start_h + ", start_m=" + start_m);
|
||||
|
||||
// SleepAnalysis measures sleep fragment type by marking the END of the fragment.
|
||||
// The watch provides data by marking the START of the fragment.
|
||||
|
||||
// Additionally, ActivityAnalysis (used by the weekly view...) does AVERAGING when
|
||||
// adjacent samples are not of the same type..
|
||||
|
||||
// FIXME: The way Gadgetbridge does it seems kinda broken...
|
||||
|
||||
// This means that we have to convert the data when importing. Each sample gets
|
||||
// converted to two samples - one marking the beginning of the segment, and another
|
||||
// marking the end.
|
||||
|
||||
// Watch: SLEEP_LIGHT ... SLEEP_DEEP ... SLEEP_LIGHT ... SLEEP_SOBER
|
||||
// Gadgetbridge: ANYTHING,SLEEP_LIGHT ... SLEEP_LIGHT,SLEEP_DEEP ... SLEEP_DEEP,SLEEP_LIGHT ... SLEEP_LIGHT,ANYTHING
|
||||
// ^ ^- this is important, it MUST be sleep, to ensure proper detection
|
||||
// Time since the last -| of sleepStart, see SleepAnalysis.calculateSleepSessions
|
||||
// sample must be 0
|
||||
// (otherwise SleepAnalysis will include this fragment...)
|
||||
|
||||
// This means that when inserting samples:
|
||||
// * every sample is converted to (previous_sample_type, current_sample_type) happening
|
||||
// roughly at the same time (but in this order)
|
||||
// * the first sample is prefixed by unspecified activity
|
||||
// * the last sample (SOBER) is converted to unspecified activity
|
||||
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
User user = DBHelper.getUser(dbHandler.getDaoSession());
|
||||
Device device = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
MoyoungActivitySampleProvider provider = new MoyoungActivitySampleProvider(getDevice(), dbHandler.getDaoSession());
|
||||
|
||||
Calendar thisSample = Calendar.getInstance();
|
||||
thisSample.add(Calendar.HOUR_OF_DAY, 4); // the clock assumes the sleep day changes at 20:00, so move the time forward to make the day correct
|
||||
thisSample.set(Calendar.MINUTE, 0);
|
||||
thisSample.add(Calendar.DATE, -daysAgo);
|
||||
|
||||
thisSample.add(Calendar.DAY_OF_MONTH, -daysAgo);
|
||||
thisSample.set(Calendar.HOUR_OF_DAY, start_h);
|
||||
thisSample.set(Calendar.MINUTE, start_m);
|
||||
thisSample.set(Calendar.SECOND, 0);
|
||||
thisSample.set(Calendar.MILLISECOND, 0);
|
||||
int thisSampleTimestamp = (int) (thisSample.getTimeInMillis() / 1000);
|
||||
|
||||
int activityType;
|
||||
if (type == MoyoungConstants.SLEEP_SOBER)
|
||||
activityType = MoyoungActivitySampleProvider.ACTIVITY_SLEEP_END;
|
||||
else if (type == MoyoungConstants.SLEEP_LIGHT)
|
||||
activityType = MoyoungActivitySampleProvider.ACTIVITY_SLEEP_LIGHT;
|
||||
else if (type == MoyoungConstants.SLEEP_RESTFUL)
|
||||
activityType = MoyoungActivitySampleProvider.ACTIVITY_SLEEP_RESTFUL;
|
||||
else
|
||||
throw new IllegalArgumentException("Invalid sleep type");
|
||||
|
||||
// Insert the end of previous segment sample
|
||||
MoyoungActivitySample prevSegmentSample = new MoyoungActivitySample();
|
||||
prevSegmentSample.setDevice(device);
|
||||
prevSegmentSample.setUser(user);
|
||||
prevSegmentSample.setProvider(provider);
|
||||
prevSegmentSample.setTimestamp(thisSampleTimestamp - 1);
|
||||
|
||||
prevSegmentSample.setRawKind(prevActivityType);
|
||||
prevSegmentSample.setDataSource(MoyoungActivitySampleProvider.SOURCE_SLEEP_SUMMARY);
|
||||
|
||||
// prevSegmentSample.setBatteryLevel(ActivitySample.NOT_MEASURED);
|
||||
prevSegmentSample.setSteps(ActivitySample.NOT_MEASURED);
|
||||
prevSegmentSample.setDistanceMeters(ActivitySample.NOT_MEASURED);
|
||||
prevSegmentSample.setCaloriesBurnt(ActivitySample.NOT_MEASURED);
|
||||
|
||||
prevSegmentSample.setHeartRate(ActivitySample.NOT_MEASURED);
|
||||
// prevSegmentSample.setBloodPressureSystolic(ActivitySample.NOT_MEASURED);
|
||||
// prevSegmentSample.setBloodPressureDiastolic(ActivitySample.NOT_MEASURED);
|
||||
// prevSegmentSample.setBloodOxidation(ActivitySample.NOT_MEASURED);
|
||||
|
||||
// addGBActivitySampleIfNotExists(provider, prevSegmentSample);
|
||||
|
||||
// Insert the start of new segment sample
|
||||
MoyoungActivitySample nextSegmentSample = new MoyoungActivitySample();
|
||||
nextSegmentSample.setDevice(device);
|
||||
nextSegmentSample.setUser(user);
|
||||
nextSegmentSample.setProvider(provider);
|
||||
nextSegmentSample.setTimestamp(thisSampleTimestamp);
|
||||
|
||||
nextSegmentSample.setRawKind(activityType);
|
||||
nextSegmentSample.setDataSource(MoyoungActivitySampleProvider.SOURCE_SLEEP_SUMMARY);
|
||||
|
||||
// nextSegmentSample.setBatteryLevel(ActivitySample.NOT_MEASURED);
|
||||
nextSegmentSample.setSteps(ActivitySample.NOT_MEASURED);
|
||||
nextSegmentSample.setDistanceMeters(ActivitySample.NOT_MEASURED);
|
||||
nextSegmentSample.setCaloriesBurnt(ActivitySample.NOT_MEASURED);
|
||||
|
||||
nextSegmentSample.setHeartRate(ActivitySample.NOT_MEASURED);
|
||||
// nextSegmentSample.setBloodPressureSystolic(ActivitySample.NOT_MEASURED);
|
||||
// nextSegmentSample.setBloodPressureDiastolic(ActivitySample.NOT_MEASURED);
|
||||
// nextSegmentSample.setBloodOxidation(ActivitySample.NOT_MEASURED);
|
||||
|
||||
// addGBActivitySampleIfNotExists(provider, nextSegmentSample);
|
||||
|
||||
// Set the activity type on all samples in this time period
|
||||
if (prevActivityType != MoyoungActivitySampleProvider.ACTIVITY_SLEEP_START)
|
||||
// provider.updateActivityInRange(prevSampleTimestamp, thisSampleTimestamp, prevActivityType);
|
||||
|
||||
prevActivityType = activityType;
|
||||
if (prevActivityType == MoyoungActivitySampleProvider.ACTIVITY_SLEEP_END)
|
||||
prevActivityType = MoyoungActivitySampleProvider.ACTIVITY_SLEEP_START;
|
||||
prevSampleTimestamp = thisSampleTimestamp;
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Error saving samples: ", ex);
|
||||
GB.toast(getContext(), "Error saving samples: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
|
||||
GB.updateTransferNotification(null, "Data transfer failed", false, 0, getContext());
|
||||
if (start_h >= 20) {
|
||||
// Evening sleep is considered to be a day earlier
|
||||
thisSample.add(Calendar.MINUTE, -1440);
|
||||
}
|
||||
|
||||
MoyoungSleepStageSample currentSample = new MoyoungSleepStageSample();
|
||||
currentSample.setDevice(device);
|
||||
currentSample.setUser(user);
|
||||
currentSample.setStage(type);
|
||||
currentSample.setTimestamp(thisSample.getTimeInMillis());
|
||||
samples.add(currentSample);
|
||||
|
||||
LOG.debug("Adding sleep stage sample: ts={} stage={}", thisSample.getTime(), type);
|
||||
}
|
||||
|
||||
LOG.debug("Will persist {} sleep stage samples", samples.size());
|
||||
provider.addSamples(samples);
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Error saving sleep stage samples: ", ex);
|
||||
GB.toast(getContext(), "Error saving sleep stage samples: " + ex.getLocalizedMessage(), Toast.LENGTH_LONG, GB.ERROR);
|
||||
GB.updateTransferNotification(null, "Data transfer failed", false, 0, getContext());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user