NO.1 F1: Fetch steps data.

master
protomors 2017-09-03 21:08:31 +03:00 committed by Carsten Pfeiffer
parent f5934dfb3b
commit ecd9964c5b
5 changed files with 157 additions and 12 deletions

View File

@ -64,6 +64,7 @@ public class GBDaoGenerator {
addPebbleMorpheuzActivitySample(schema, user, device);
addHPlusHealthActivityKindOverlay(schema, user, device);
addHPlusHealthActivitySample(schema, user, device);
addNo1F1ActivitySample(schema, user, device);
addCalendarSyncState(schema, device);
@ -257,6 +258,15 @@ public class GBDaoGenerator {
return activityOverlay;
}
private static Entity addNo1F1ActivitySample(Schema schema, Entity user, Entity device) {
Entity activitySample = addEntity(schema, "No1F1ActivitySample");
activitySample.implementsSerializable();
addCommonActivitySampleProperties("AbstractActivitySample", activitySample, user, device);
activitySample.addIntProperty(SAMPLE_STEPS).notNull().codeBeforeGetterAndSetter(OVERRIDE);
activitySample.addIntProperty(SAMPLE_RAW_KIND).notNull().codeBeforeGetterAndSetter(OVERRIDE);
return activitySample;
}
private static void addCommonActivitySampleProperties(String superClass, Entity activitySample, Entity user, Entity device) {
activitySample.setSuperclass(superClass);
activitySample.addImport(MAIN_PACKAGE + ".devices.SampleProvider");

View File

@ -15,6 +15,9 @@ public final class No1F1Constants {
public static final byte CMD_USER_DATA = (byte) 0xa9;
public static final byte CMD_ALARM = (byte) 0xab;
public static final byte CMD_FACTORY_RESET = (byte) 0xad;
public static final byte CMD_REALTIME_STEPS = (byte) 0xb1;
public static final byte CMD_FETCH_STEPS = (byte) 0xb2;
public static final byte CMD_FETCH_SLEEP = (byte) 0xb3;
public static final byte CMD_NOTIFICATION = (byte) 0xc1;
public static final byte CMD_ICON = (byte) 0xc3;
public static final byte CMD_DEVICE_SETTINGS = (byte) 0xd3;

View File

@ -13,12 +13,15 @@ import android.support.annotation.Nullable;
import java.util.Collection;
import java.util.Collections;
import de.greenrobot.dao.query.QueryBuilder;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.No1F1ActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
@ -65,22 +68,22 @@ public class No1F1Coordinator extends AbstractDeviceCoordinator {
@Nullable
@Override
public Class<? extends Activity> getPrimaryActivity() {
return null;
return ChartsActivity.class;
}
@Override
public boolean supportsActivityDataFetching() {
return false;
return true;
}
@Override
public boolean supportsActivityTracking() {
return false;
return true;
}
@Override
public SampleProvider<? extends ActivitySample> getSampleProvider(GBDevice device, DaoSession session) {
return null;
return new No1F1SampleProvider(device, session);
}
@Override
@ -135,6 +138,8 @@ public class No1F1Coordinator extends AbstractDeviceCoordinator {
@Override
protected void deleteDevice(@NonNull GBDevice gbDevice, @NonNull Device device, @NonNull DaoSession session) throws GBException {
Long deviceId = device.getId();
QueryBuilder<?> qb = session.getNo1F1ActivitySampleDao().queryBuilder();
qb.where(No1F1ActivitySampleDao.Properties.DeviceId.eq(deviceId)).buildDelete().executeDeleteWithoutDetachingEntities();
}
}

View File

@ -0,0 +1,68 @@
package nodomain.freeyourgadget.gadgetbridge.devices.no1f1;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.Property;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.No1F1ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.No1F1ActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class No1F1SampleProvider extends AbstractSampleProvider<No1F1ActivitySample> {
private GBDevice mDevice;
private DaoSession mSession;
public No1F1SampleProvider(GBDevice device, DaoSession session) {
super(device, session);
mSession = session;
mDevice = device;
}
@Override
public int normalizeType(int rawType) {
return rawType;
}
@Override
public int toRawActivityKind(int activityKind) {
return activityKind;
}
@Override
public float normalizeIntensity(int rawIntensity) {
return rawIntensity;
}
@Override
public No1F1ActivitySample createActivitySample() {
return new No1F1ActivitySample();
}
@Override
public AbstractDao<No1F1ActivitySample, ?> getSampleDao() {
return getSession().getNo1F1ActivitySampleDao();
}
@Nullable
@Override
protected Property getRawKindSampleProperty() {
return No1F1ActivitySampleDao.Properties.RawKind;
}
@NonNull
@Override
protected Property getTimestampSampleProperty() {
return No1F1ActivitySampleDao.Properties.Timestamp;
}
@NonNull
@Override
protected Property getDeviceIdentifierSampleProperty() {
return No1F1ActivitySampleDao.Properties.DeviceId;
}
}

View File

@ -12,12 +12,20 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventBatteryInfo;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1Constants;
import nodomain.freeyourgadget.gadgetbridge.devices.no1f1.No1F1SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.No1F1ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
@ -29,6 +37,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
import nodomain.freeyourgadget.gadgetbridge.model.WeatherSpec;
import nodomain.freeyourgadget.gadgetbridge.service.btle.AbstractBTLEDeviceSupport;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
import nodomain.freeyourgadget.gadgetbridge.service.btle.actions.SetDeviceBusyAction;
import static org.apache.commons.lang3.math.NumberUtils.min;
@ -38,6 +47,7 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
private final GBDeviceEventBatteryInfo batteryCmd = new GBDeviceEventBatteryInfo();
public BluetoothGattCharacteristic ctrlCharacteristic = null;
public BluetoothGattCharacteristic measureCharacteristic = null;
private List<No1F1ActivitySample> samples = new ArrayList<>();
public No1F1Support() {
super(LOG);
@ -99,6 +109,9 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
case No1F1Constants.CMD_USER_DATA:
LOG.info("User data updated");
return true;
case No1F1Constants.CMD_FETCH_STEPS:
handleStepData(data);
return true;
case No1F1Constants.CMD_NOTIFICATION:
case No1F1Constants.CMD_ICON:
case No1F1Constants.CMD_DEVICE_SETTINGS:
@ -201,15 +214,13 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
@Override
public void onFetchActivityData() {
}
@Override
public void onReboot() {
try {
TransactionBuilder builder = performInitialized("clearNotification");
samples.clear();
TransactionBuilder builder = performInitialized("fetchSteps");
builder.add(new SetDeviceBusyAction(getDevice(), getContext().getString(R.string.busy_task_fetch_activity_data), getContext()));
byte[] msg = new byte[]{
(byte) 0xad
No1F1Constants.CMD_FETCH_STEPS,
(byte) 0xfa
};
builder.write(ctrlCharacteristic, msg);
performConnected(builder.getTransaction());
@ -217,6 +228,10 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
}
}
@Override
public void onReboot() {
}
@Override
public void onHeartRateTest() {
@ -430,4 +445,48 @@ public class No1F1Support extends AbstractBTLEDeviceSupport {
} catch (IOException e) {
}
}
private void handleStepData(byte[] data) {
if (data[1] == (byte) 0xfd) {
// TODO Check CRC
if (samples.size() > 0) {
try (DBHandler dbHandler = GBApplication.acquireDB()) {
Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId();
Long deviceId = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()).getId();
No1F1SampleProvider provider = new No1F1SampleProvider(getDevice(), dbHandler.getDaoSession());
for (int i = 0; i < samples.size(); i++) {
samples.get(i).setDeviceId(deviceId);
samples.get(i).setUserId(userId);
samples.get(i).setRawKind(ActivityKind.TYPE_ACTIVITY);
provider.addGBActivitySample(samples.get(i));
}
samples.clear();
LOG.info("Steps data saved");
if (getDevice().isBusy()) {
getDevice().unsetBusyTask();
getDevice().sendDeviceUpdateIntent(getContext());
}
} catch (Exception ex) {
}
}
} else {
No1F1ActivitySample sample = new No1F1ActivitySample();
Calendar timestamp = GregorianCalendar.getInstance();
timestamp.set(Calendar.YEAR, data[1] * 256 + (data[2] & 0xff));
timestamp.set(Calendar.MONTH, (data[3] - 1) & 0xff);
timestamp.set(Calendar.DAY_OF_MONTH, data[4] & 0xff);
timestamp.set(Calendar.HOUR_OF_DAY, data[5] & 0xff);
timestamp.set(Calendar.MINUTE, 0);
timestamp.set(Calendar.SECOND, 0);
sample.setTimestamp((int) (timestamp.getTimeInMillis() / 1000L));
sample.setSteps(data[6] * 256 + (data[7] & 0xff));
samples.add(sample);
LOG.info("Received steps data for " + String.format("%1$TD %1$TT", timestamp) + ": " +
sample.getSteps() + " steps"
);
}
}
}