mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-28 21:06:50 +01:00
parent
0c51f86afc
commit
a8a7d8db31
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
@ -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() +
|
||||
'}';
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user