diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractSampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractSampleProvider.java index 4748ea47..cd375c52 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractSampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/AbstractSampleProvider.java @@ -74,6 +74,24 @@ public abstract class AbstractSampleProvider i getSampleDao().insertOrReplaceInTx(activitySamples); } + @Nullable + @Override + public T getLatestActivitySample() { + QueryBuilder qb = getSampleDao().queryBuilder(); + Device dbDevice = DBHelper.findDevice(getDevice(), getSession()); + if (dbDevice == null) { + // no device, no sample + return null; + } + Property deviceProperty = getDeviceIdentifierSampleProperty(); + qb.where(deviceProperty.eq(dbDevice.getId())).orderDesc(getTimestampSampleProperty()).limit(1); + List samples = qb.build().list(); + if (samples.isEmpty()) { + return null; + } + return samples.get(0); + } + protected List getGBActivitySamples(int timestamp_from, int timestamp_to, int activityType) { if (getRawKindSampleProperty() == null && activityType != ActivityKind.TYPE_ALL) { // if we do not have a raw kind property we cannot query anything else then TYPE_ALL diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/SampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/SampleProvider.java index 54f809dd..fca1710e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/SampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/SampleProvider.java @@ -1,6 +1,7 @@ package nodomain.freeyourgadget.gadgetbridge.devices; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import java.util.List; @@ -88,4 +89,11 @@ public interface SampleProvider { * @return the newly created "empty" sample */ T createActivitySample(); + + /** + * Returns the activity sample with the highest timestamp. or null if none + * @return the latest sample or null + */ + @Nullable + T getLatestActivitySample(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java index 06fc3d4a..d7379c45 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/UnknownDeviceCoordinator.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.content.Context; import android.net.Uri; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import java.util.List; @@ -64,6 +65,12 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator { return null; } + @Nullable + @Override + public AbstractActivitySample getLatestActivitySample() { + return null; + } + @Override public int getID() { return PROVIDER_UNKNOWN; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java index 9b7b2c66..d68f6d46 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/devices/miband/MiBand2SampleProvider.java @@ -13,6 +13,9 @@ public class MiBand2SampleProvider extends AbstractMiBandSampleProvider { public static final int TYPE_UNKNOWN = -1; public static final int TYPE_NONWEAR = 3; public static final int TYPE_CHARGING = 6; + // appears to be a measurement problem resulting in type = 10 and intensity = 20, at least + // with fw 1.0.0.39 + public static final int TYPE_IGNORE = 10; // observed the following values so far: // 00 01 02 09 0a 0b 0c 10 11 @@ -29,16 +32,17 @@ public class MiBand2SampleProvider extends AbstractMiBandSampleProvider { @Override public int normalizeType(int rawType) { switch (rawType) { - case TYPE_DEEP_SLEEP: - return ActivityKind.TYPE_DEEP_SLEEP; - case TYPE_LIGHT_SLEEP: - return ActivityKind.TYPE_LIGHT_SLEEP; - case TYPE_ACTIVITY: - return ActivityKind.TYPE_ACTIVITY; - case TYPE_NONWEAR: - return ActivityKind.TYPE_NOT_WORN; - case TYPE_CHARGING: - return ActivityKind.TYPE_NOT_WORN; //I believe it's a safe assumption +// case TYPE_DEEP_SLEEP: +// return ActivityKind.TYPE_DEEP_SLEEP; +// case TYPE_LIGHT_SLEEP: +// return ActivityKind.TYPE_LIGHT_SLEEP; +// case TYPE_ACTIVITY: +// return ActivityKind.TYPE_ACTIVITY; +// case TYPE_NONWEAR: +// return ActivityKind.TYPE_NOT_WORN; +// case TYPE_CHARGING: +// return ActivityKind.TYPE_NOT_WORN; //I believe it's a safe assumption +// case TYPE_IGNORE: default: // case TYPE_UNKNOWN: // fall through return ActivityKind.TYPE_UNKNOWN; @@ -47,18 +51,18 @@ public class MiBand2SampleProvider extends AbstractMiBandSampleProvider { @Override public int toRawActivityKind(int activityKind) { - switch (activityKind) { - case ActivityKind.TYPE_ACTIVITY: - return TYPE_ACTIVITY; - case ActivityKind.TYPE_DEEP_SLEEP: - return TYPE_DEEP_SLEEP; - case ActivityKind.TYPE_LIGHT_SLEEP: - return TYPE_LIGHT_SLEEP; - case ActivityKind.TYPE_NOT_WORN: - return TYPE_NONWEAR; - case ActivityKind.TYPE_UNKNOWN: // fall through - default: +// switch (activityKind) { +// case ActivityKind.TYPE_ACTIVITY: +// return TYPE_ACTIVITY; +// case ActivityKind.TYPE_DEEP_SLEEP: +// return TYPE_DEEP_SLEEP; +// case ActivityKind.TYPE_LIGHT_SLEEP: +// return TYPE_LIGHT_SLEEP; +// case ActivityKind.TYPE_NOT_WORN: +// return TYPE_NONWEAR; +// case ActivityKind.TYPE_UNKNOWN: // fall through +// default: return TYPE_UNKNOWN; - } +// } } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java index 08f09c11..03f9e442 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java @@ -74,12 +74,14 @@ public abstract class AbstractActivitySample implements ActivitySample { @Override public String toString() { + int kind = getProvider() != null ? getKind() : ActivitySample.NOT_MEASURED; + float intensity = getProvider() != null ? getIntensity() : ActivitySample.NOT_MEASURED; return getClass().getSimpleName() + "{" + "timestamp=" + DateTimeUtils.formatDateTime(DateTimeUtils.parseTimeStamp(getTimestamp())) + - ", intensity=" + getIntensity() + + ", intensity=" + intensity + ", steps=" + getSteps() + ", heartrate=" + getHeartRate() + - ", type=" + getKind() + + ", type=" + kind + ", userId=" + getUserId() + ", deviceId=" + getDeviceId() + '}'; diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java index fa5facb7..5d8c2dba 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/miband2/operations/FetchActivityOperation.java @@ -12,21 +12,26 @@ import java.text.DateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; +import java.util.Date; import java.util.GregorianCalendar; import java.util.List; import java.util.UUID; +import de.greenrobot.dao.query.QueryBuilder; import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.Logging; import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2SampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBand2Service; import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandSampleProvider; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.Device; import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySample; +import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySampleDao; import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.service.btle.BLETypeConversions; import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder; @@ -79,12 +84,23 @@ public class FetchActivityOperation extends AbstractMiBand2Operation { builder.queue(getQueue()); } - // TODO: use last synchronized sample for the timestamp! - // and what do we do if there was no sync? timestamp from first connectionn? - // or just now - 20d? private GregorianCalendar getLastSuccessfulSynchronizedTime() { + try (DBHandler dbHandler = GBApplication.acquireDB()) { + DaoSession session = dbHandler.getDaoSession(); + SampleProvider sampleProvider = new MiBand2SampleProvider(getDevice(), session); + MiBandActivitySample sample = sampleProvider.getLatestActivitySample(); + if (sample != null) { + int timestamp = sample.getTimestamp(); + GregorianCalendar calendar = BLETypeConversions.createCalendar(); + calendar.setTimeInMillis(timestamp * 1000); + return calendar; + } + } catch (Exception ex) { + LOG.error("Error querying for latest activity sample, synchronizing the last 10 days", ex); + } + GregorianCalendar calendar = BLETypeConversions.createCalendar(); - calendar.add(Calendar.DAY_OF_MONTH, -4); + calendar.add(Calendar.DAY_OF_MONTH, -10); return calendar; } diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/Tryout.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/Tryout.java new file mode 100644 index 00000000..0f36f268 --- /dev/null +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/Tryout.java @@ -0,0 +1,36 @@ +package nodomain.freeyourgadget.gadgetbridge.test; + +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.GregorianCalendar; + +import nodomain.freeyourgadget.gadgetbridge.Logging; +import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandDateConverter; +import nodomain.freeyourgadget.gadgetbridge.service.devices.miband.MiBand2Support; +import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; + +/** + * A simple class for trying out things, not actually testing something. + */ +public class Tryout extends TestBase { + private static final Logger LOG = LoggerFactory.getLogger(MiBand2Support.class); + + @Test + public void blah() { + int v = 1 << 7 | 1 << 2; + byte b = (byte) v; + LOG.info("v: " + v); + Logging.logBytes(LOG, new byte[] { b }); + } + + @Test + public void testCalendarBytes() { + GregorianCalendar calendar = MiBandDateConverter.createCalendar(); + byte[] bytes = MiBandDateConverter.calendarToRawBytes(calendar); + LOG.info("Calender: " + DateTimeUtils.formatDateTime(calendar.getTime())); + Logging.logBytes(LOG, bytes); + } + +}