Mi2: WIP synchronize only new data since last sync

(#323)
here
cpfeiffer 2016-11-22 00:03:23 +01:00
parent 0c51f86afc
commit a8a7d8db31
7 changed files with 119 additions and 28 deletions

View File

@ -74,6 +74,24 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
getSampleDao().insertOrReplaceInTx(activitySamples);
}
@Nullable
@Override
public T getLatestActivitySample() {
QueryBuilder<T> 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<T> samples = qb.build().list();
if (samples.isEmpty()) {
return null;
}
return samples.get(0);
}
protected List<T> 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

View File

@ -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<T extends AbstractActivitySample> {
* @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();
}

View File

@ -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;

View File

@ -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;
}
// }
}
}

View File

@ -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() +
'}';

View File

@ -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<MiBandActivitySample> 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;
}

View File

@ -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);
}
}