More WIP, but we're getting closer

current state:
- storing samples works (tested only mi band)
- charts work
master
cpfeiffer 2016-05-16 23:00:04 +02:00
parent 6e44ddaee6
commit 3e0bc16741
25 changed files with 319 additions and 281 deletions

View File

@ -57,10 +57,10 @@ public class GBApplication extends Application {
//if preferences have to be migrated, increment the following and add the migration logic in migratePrefs below; see http://stackoverflow.com/questions/16397848/how-can-i-migrate-android-preferences-with-a-new-version
private static final int CURRENT_PREFS_VERSION = 2;
private static LimitedQueue mIDSenderLookup = new LimitedQueue(16);
private static DaoSession daoSession;
private static Appender<ILoggingEvent> fileLogger;
private static Prefs prefs;
private static GBPrefs gbPrefs;
private static DBHandler lockHandler;
public static final String ACTION_QUIT
= "nodomain.freeyourgadget.gadgetbridge.gbapplication.action.quit";
@ -206,11 +206,7 @@ public class GBApplication extends Application {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "test-db", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
public static DaoSession getDaoSession() {
return daoSession;
lockHandler = new LockHandler(daoMaster.newSession());
}
public static Context getContext() {
@ -238,10 +234,10 @@ public class GBApplication extends Application {
* @see #releaseDB()
*/
public static DBHandler acquireDB() throws GBException {
// TODO: implement locking with greendao?
try {
if (dbLock.tryLock(30, TimeUnit.SECONDS)) {
return mActivityDatabaseHandler;
return lockHandler;
// return mActivityDatabaseHandler;
}
} catch (InterruptedException ex) {
Log.i(TAG, "Interrupted while waiting for DB lock");

View File

@ -1,12 +1,15 @@
package nodomain.freeyourgadget.gadgetbridge.database;
package nodomain.freeyourgadget.gadgetbridge;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
/**
@ -15,13 +18,19 @@ import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
*/
public class LockHandler implements DBHandler {
@Override
public void release() {
private final DaoSession session;
public LockHandler(DaoSession daoSession) {
session = daoSession;
}
@Override
public void close() {
GBApplication.releaseDB();
}
@Override
public void closeDb() {
}
@ -32,22 +41,31 @@ public class LockHandler implements DBHandler {
@Override
public List<ActivitySample> getAllActivitySamples(int tsFrom, int tsTo, SampleProvider provider) {
return null;
return provider.getAllActivitySamples(tsFrom, tsTo);
}
@Override
public List<ActivitySample> getActivitySamples(int tsFrom, int tsTo, SampleProvider provider) {
return null;
return provider.getActivitySamples(tsFrom, tsTo);
}
@Override
public List<ActivitySample> getSleepSamples(int tsFrom, int tsTo, SampleProvider provider) {
return null;
return provider.getSleepSamples(tsFrom, tsTo);
}
@Override
public int fetchLatestTimestamp(SampleProvider provider) {
return provider.fetchLatestTimestamp();
}
@Override
public DaoSession getDaoSession() {
return session;
}
@Override
public void addGBActivitySample(AbstractActivitySample sample) {
}
@Override
@ -69,9 +87,4 @@ public class LockHandler implements DBHandler {
public void changeStoredSamplesType(int timestampFrom, int timestampTo, int fromKind, int toKind, SampleProvider provider) {
}
@Override
public int fetchLatestTimestamp(SampleProvider provider) {
return 0;
}
}

View File

@ -237,19 +237,13 @@ public class DebugActivity extends GBActivity {
}
private void exportDB() {
DBHandler dbHandler = null;
try {
dbHandler = GBApplication.acquireDB();
try (DBHandler dbHandler = GBApplication.acquireDB()) {
DBHelper helper = new DBHelper(this);
File dir = FileUtils.getExternalFilesDir();
File destFile = helper.exportDB(dbHandler.getHelper(), dir);
GB.toast(this, "Exported to: " + destFile.getAbsolutePath(), Toast.LENGTH_LONG, GB.INFO);
} catch (Exception ex) {
GB.toast(this, "Error exporting DB: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
} finally {
if (dbHandler != null) {
dbHandler.release();
}
}
}
@ -261,9 +255,7 @@ public class DebugActivity extends GBActivity {
.setPositiveButton("Overwrite", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
DBHandler dbHandler = null;
try {
dbHandler = GBApplication.acquireDB();
try (DBHandler dbHandler = GBApplication.acquireDB()) {
DBHelper helper = new DBHelper(DebugActivity.this);
File dir = FileUtils.getExternalFilesDir();
SQLiteOpenHelper sqLiteOpenHelper = dbHandler.getHelper();
@ -273,10 +265,6 @@ public class DebugActivity extends GBActivity {
GB.toast(DebugActivity.this, "Import successful.", Toast.LENGTH_LONG, GB.INFO);
} catch (Exception ex) {
GB.toast(DebugActivity.this, "Error importing DB: " + ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
} finally {
if (dbHandler != null) {
dbHandler.release();
}
}
}
})

View File

@ -20,8 +20,4 @@ public class GBActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
}
protected DaoSession getDAOSession() {
return GBApplication.getDaoSession();
}
}

View File

@ -293,9 +293,9 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
return akActivity.color;
}
protected SampleProvider getProvider(GBDevice device) {
protected SampleProvider getProvider(DBHandler db, GBDevice device) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(device);
return coordinator.getSampleProvider();
return coordinator.getSampleProvider(db);
}
/**
@ -307,7 +307,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
* @param tsTo
*/
protected List<ActivitySample> getAllSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
SampleProvider provider = getProvider(device);
SampleProvider provider = getProvider(db, device);
return db.getAllActivitySamples(tsFrom, tsTo, provider);
}
@ -316,13 +316,13 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
}
protected List<ActivitySample> getActivitySamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
SampleProvider provider = getProvider(device);
SampleProvider provider = getProvider(db, device);
return db.getActivitySamples(tsFrom, tsTo, provider);
}
protected List<ActivitySample> getSleepSamples(DBHandler db, GBDevice device, int tsFrom, int tsTo) {
SampleProvider provider = getProvider(device);
SampleProvider provider = getProvider(db, device);
return db.getSleepSamples(tsFrom, tsTo, provider);
}
@ -334,7 +334,7 @@ public abstract class AbstractChartFragment extends AbstractGBFragment {
tsTo = (int) ((cal.getTimeInMillis() / 1000));
tsFrom = tsTo - (24 * 60 * 60);
SampleProvider provider = getProvider(device);
SampleProvider provider = getProvider(db, device);
return db.getAllActivitySamples(tsFrom, tsTo, provider);
}

View File

@ -18,6 +18,7 @@ import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationSc
import nodomain.freeyourgadget.gadgetbridge.database.schema.SchemaMigration;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.impl.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
@ -155,13 +156,13 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
}
@Override
public SQLiteOpenHelper getHelper() {
return this;
public void closeDb() {
GBApplication.releaseDB();
}
@Override
public void release() {
GBApplication.releaseDB();
public SQLiteOpenHelper getHelper() {
return this;
}
public ArrayList<ActivitySample> getAllActivitySamples(int timestamp_from, int timestamp_to, SampleProvider provider) {
@ -275,4 +276,9 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl
}
return -1;
}
@Override
public DaoSession getDaoSession() {
return null;
}
}

View File

@ -26,16 +26,10 @@ public abstract class DBAccess extends AsyncTask {
@Override
protected Object doInBackground(Object[] params) {
DBHandler handler = null;
try {
handler = GBApplication.acquireDB();
doInBackground(handler);
try (DBHandler db = GBApplication.acquireDB()) {
doInBackground(db);
} catch (Exception e) {
mError = e;
} finally {
if (handler != null) {
handler.release();
}
}
return null;
}

View File

@ -8,13 +8,14 @@ import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public interface DBHandler {
public interface DBHandler extends AutoCloseable {
/**
* Closes the database.
*/
void close();
void closeDb();
SQLiteOpenHelper getHelper();
@ -22,7 +23,7 @@ public interface DBHandler {
* Releases the DB handler. No access may be performed after calling this method.
* Same as calling {@link GBApplication#releaseDB()}
*/
void release();
void close() throws Exception;
List<ActivitySample> getAllActivitySamples(int tsFrom, int tsTo, SampleProvider provider);
@ -42,4 +43,5 @@ public interface DBHandler {
int fetchLatestTimestamp(SampleProvider provider);
DaoSession getDaoSession();
}

View File

@ -116,8 +116,7 @@ public class DBHelper {
return "";
}
public static User getUser() {
DaoSession session = GBApplication.getDaoSession();
public static User getUser(DaoSession session) {
UserDao userDao = session.getUserDao();
List<User> users = userDao.loadAll();
if (users.isEmpty()) {
@ -148,8 +147,7 @@ public class DBHelper {
return user;
}
public static Device getDevice(GBDevice gbDevice) {
DaoSession session = GBApplication.getDaoSession();
public static Device getDevice(GBDevice gbDevice, DaoSession session) {
DeviceDao deviceDao = session.getDeviceDao();
Query<Device> query = deviceDao.queryBuilder().where(DeviceDao.Properties.Identifier.eq(gbDevice.getAddress())).build();
List<Device> devices = query.list();

View File

@ -16,7 +16,7 @@ import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySampleDao;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public abstract class AbstractSampleProvider<T extends ActivitySample> implements SampleProvider, DBHandler {
public abstract class AbstractSampleProvider<T extends ActivitySample> implements SampleProvider {
private static final WhereCondition[] NO_CONDITIONS = new WhereCondition[0];
private final DaoSession mSession;
@ -28,47 +28,31 @@ public abstract class AbstractSampleProvider<T extends ActivitySample> implement
return mSession;
}
@Override
public List<T> getAllActivitySamples(int timestamp_from, int timestamp_to) {
return getGBActivitySamples(timestamp_from, timestamp_to, ActivityKind.TYPE_ALL);
}
@Override
public List<T> getActivitySamples(int timestamp_from, int timestamp_to) {
return getGBActivitySamples(timestamp_from, timestamp_to, ActivityKind.TYPE_ACTIVITY);
}
@Override
public List<T> getSleepSamples(int timestamp_from, int timestamp_to) {
return getGBActivitySamples(timestamp_from, timestamp_to, ActivityKind.TYPE_SLEEP);
}
@Override
public void close() {
// TESTING: NOOP
}
@Override
public SQLiteOpenHelper getHelper() {
// TESTING: NOOP
return null;
}
@Override
public void release() {
// TESTING: NOOP
}
@Override
public List<ActivitySample> getAllActivitySamples(int tsFrom, int tsTo, SampleProvider provider) {
return (List<ActivitySample>) getGBActivitySamples(tsFrom, tsTo, ActivityKind.TYPE_ALL);
}
@Override
public List<ActivitySample> getActivitySamples(int tsFrom, int tsTo, SampleProvider provider) {
return (List<ActivitySample>) getGBActivitySamples(tsFrom, tsTo, ActivityKind.TYPE_ACTIVITY);
}
@Override
public List<ActivitySample> getSleepSamples(int tsFrom, int tsTo, SampleProvider provider) {
return (List<ActivitySample>) getGBActivitySamples(tsFrom, tsTo, ActivityKind.TYPE_SLEEP);
public int fetchLatestTimestamp() {
QueryBuilder<T> qb = getSampleDao().queryBuilder();
qb.orderDesc(MiBandActivitySampleDao.Properties.Timestamp);
qb.limit(1);
List<T> list = qb.build().list();
if (list.size() >= 1) {
return list.get(0).getTimestamp();
}
return -1;
}
@Override
@ -81,42 +65,77 @@ public abstract class AbstractSampleProvider<T extends ActivitySample> implement
getSampleDao().insertInTx((T[]) activitySamples);
}
@Override
public SQLiteDatabase getWritableDatabase() {
// TESTING: NOOP
return null;
}
@Override
public void changeStoredSamplesType(int timestampFrom, int timestampTo, int kind, SampleProvider provider) {
}
@Override
public void changeStoredSamplesType(int timestampFrom, int timestampTo, int fromKind, int toKind, SampleProvider provider) {
}
@Override
public int fetchLatestTimestamp(SampleProvider provider) {
return 0;
}
// SQLiteDatabase getWritableDatabase();
public void changeStoredSamplesType(int timestampFrom, int timestampTo, int kind) {
// TODO: implement
}
public void changeStoredSamplesType(int timestampFrom, int timestampTo, int fromKind, int toKind) {
// TODO: implement
}
// @Override
// public void close() {
// // TESTING: NOOP
// }
//
// @Override
// public SQLiteOpenHelper getHelper() {
// // TESTING: NOOP
// return null;
// }
//
// @Override
// public void release() {
// // TESTING: NOOP
// }
//
// @Override
// public List<ActivitySample> getAllActivitySamples(int tsFrom, int tsTo, SampleProvider provider) {
// return (List<ActivitySample>) getGBActivitySamples(tsFrom, tsTo, ActivityKind.TYPE_ALL);
// }
//
// @Override
// public List<ActivitySample> getActivitySamples(int tsFrom, int tsTo, SampleProvider provider) {
// return (List<ActivitySample>) getGBActivitySamples(tsFrom, tsTo, ActivityKind.TYPE_ACTIVITY);
// }
//
// @Override
// public List<ActivitySample> getSleepSamples(int tsFrom, int tsTo, SampleProvider provider) {
// return (List<ActivitySample>) getGBActivitySamples(tsFrom, tsTo, ActivityKind.TYPE_SLEEP);
// }
//
// @Override
// public SQLiteDatabase getWritableDatabase() {
// // TESTING: NOOP
// return null;
// }
//
// @Override
// public void changeStoredSamplesType(int timestampFrom, int timestampTo, int kind, SampleProvider provider) {
//
// }
//
// @Override
// public void changeStoredSamplesType(int timestampFrom, int timestampTo, int fromKind, int toKind, SampleProvider provider) {
//
// }
//
// @Override
// public int fetchLatestTimestamp(SampleProvider provider) {
// return 0;
// }
//
//// SQLiteDatabase getWritableDatabase();
//
// public void changeStoredSamplesType(int timestampFrom, int timestampTo, int kind) {
// // TODO: implement
// }
//
// public void changeStoredSamplesType(int timestampFrom, int timestampTo, int fromKind, int toKind) {
// // TODO: implement
// }
protected List<T> getGBActivitySamples(int timestamp_from, int timestamp_to, int activityType) {
QueryBuilder<T> qb = getSampleDao().queryBuilder();
qb.where(MiBandActivitySampleDao.Properties.Timestamp.ge(timestamp_from))
.where(MiBandActivitySampleDao.Properties.Timestamp.le(timestamp_to), getClauseForActivityType(qb, activityType));
return qb.build().list();
List<T> samples = qb.build().list();
for (T sample : samples) {
((AbstractActivitySample) sample).setProvider(this);
}
return samples;
}
private WhereCondition[] getClauseForActivityType(QueryBuilder qb, int activityTypes) {
@ -153,16 +172,5 @@ public abstract class AbstractSampleProvider<T extends ActivitySample> implement
trailingConditions);
}
public int fetchLatestTimestamp() {
QueryBuilder<T> qb = getSampleDao().queryBuilder();
qb.orderDesc(MiBandActivitySampleDao.Properties.Timestamp);
qb.limit(1);
List<T> list = qb.build().list();
if (list.size() >= 1) {
return list.get(0).getTimestamp();
}
return -1;
}
protected abstract AbstractDao<T,?> getSampleDao();
}

View File

@ -4,6 +4,7 @@ import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
@ -82,7 +83,7 @@ public interface DeviceCoordinator {
*
* @return
*/
SampleProvider getSampleProvider();
SampleProvider getSampleProvider(DBHandler db);
/**
* Finds an install handler for the given uri that can install the given

View File

@ -1,6 +1,11 @@
package nodomain.freeyourgadget.gadgetbridge.devices;
public interface SampleProvider {
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public interface SampleProvider<T extends ActivitySample> {
int PROVIDER_MIBAND = 0;
int PROVIDER_PEBBLE_MORPHEUZ = 1;
int PROVIDER_PEBBLE_GADGETBRIDGE = 2;
@ -15,5 +20,17 @@ public interface SampleProvider {
float normalizeIntensity(int rawIntensity);
List<T> getAllActivitySamples(int timestamp_from, int timestamp_to);
List<T> getActivitySamples(int timestamp_from, int timestamp_to);
List<T> getSleepSamples(int timestamp_from, int timestamp_to);
int fetchLatestTimestamp();
void addGBActivitySample(AbstractActivitySample activitySample);
void addGBActivitySamples(AbstractActivitySample[] activitySamples);
int getID();
}

View File

@ -4,14 +4,17 @@ import android.app.Activity;
import android.content.Context;
import android.net.Uri;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceCandidate;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
private final UnknownSampleProvider sampleProvider;
private static final class UnknownSampleProvider implements SampleProvider {
@Override
@ -29,6 +32,34 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
return 0;
}
@Override
public List getAllActivitySamples(int timestamp_from, int timestamp_to) {
return null;
}
@Override
public List getActivitySamples(int timestamp_from, int timestamp_to) {
return null;
}
@Override
public List getSleepSamples(int timestamp_from, int timestamp_to) {
return null;
}
@Override
public int fetchLatestTimestamp() {
return 0;
}
@Override
public void addGBActivitySample(AbstractActivitySample activitySample) {
}
@Override
public void addGBActivitySamples(AbstractActivitySample[] activitySamples) {
}
@Override
public int getID() {
return PROVIDER_UNKNOWN;
@ -36,7 +67,6 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
}
public UnknownDeviceCoordinator() {
sampleProvider = new UnknownSampleProvider();
}
@Override
@ -65,8 +95,8 @@ public class UnknownDeviceCoordinator extends AbstractDeviceCoordinator {
}
@Override
public SampleProvider getSampleProvider() {
return sampleProvider;
public SampleProvider getSampleProvider(DBHandler db) {
return new UnknownSampleProvider();
}
@Override

View File

@ -10,6 +10,7 @@ import org.slf4j.LoggerFactory;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
@ -21,10 +22,8 @@ import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class MiBandCoordinator extends AbstractDeviceCoordinator {
private static final Logger LOG = LoggerFactory.getLogger(MiBandCoordinator.class);
private final MiBandSampleProvider sampleProvider;
public MiBandCoordinator() {
sampleProvider = new MiBandSampleProvider(GBApplication.getDaoSession());
}
@Override
@ -54,8 +53,8 @@ public class MiBandCoordinator extends AbstractDeviceCoordinator {
}
@Override
public SampleProvider getSampleProvider() {
return sampleProvider;
public SampleProvider getSampleProvider(DBHandler db) {
return new MiBandSampleProvider(db.getDaoSession());
}
@Override

View File

@ -7,6 +7,7 @@ import android.net.Uri;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AppManagerActivity;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.InstallHandler;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
@ -45,9 +46,9 @@ public class PebbleCoordinator extends AbstractDeviceCoordinator {
}
@Override
public SampleProvider getSampleProvider() {
public SampleProvider getSampleProvider(DBHandler db) {
Prefs prefs = GBApplication.getPrefs();
DaoSession session = GBApplication.getDaoSession();
DaoSession session = db.getDaoSession();
int activityTracker = prefs.getInt("pebble_activitytracker", SampleProvider.PROVIDER_PEBBLE_HEALTH);
switch (activityTracker) {
case SampleProvider.PROVIDER_PEBBLE_HEALTH:

View File

@ -18,6 +18,7 @@ import java.util.concurrent.TimeUnit;
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.devices.AbstractSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
@ -26,8 +27,10 @@ import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandService;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
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.impl.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.service.btle.TransactionBuilder;
@ -311,10 +314,10 @@ public class FetchActivityOperation extends AbstractMiBandOperation {
LOG.debug("flushing activity data samples: " + activityStruct.activityDataHolderProgress / bpm);
byte category, intensity, steps, heartrate = 0;
DBHandler dbHandler = null;
try {
// dbHandler = GBApplication.acquireDB();
dbHandler = new MiBandSampleProvider(GBApplication.getDaoSession());
try (DBHandler dbHandler = GBApplication.acquireDB()){
MiBandSampleProvider provider = new MiBandSampleProvider(dbHandler.getDaoSession());
Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId();
Long deviceId = DBHelper.getDevice(getDevice(), dbHandler.getDaoSession()).getId();
int minutes = 0;
try (SQLiteDatabase db = dbHandler.getWritableDatabase()) { // explicitly keep the db open while looping over the samples
int timestampInSeconds = (int) (activityStruct.activityDataTimestampProgress.getTimeInMillis() / 1000);
@ -333,10 +336,6 @@ public class FetchActivityOperation extends AbstractMiBandOperation {
LOG.debug("heartrate received: " + (heartrate & 0xff));
}
// TODO: user and device id
Long userId = null;
Long deviceId = null;
samples[minutes] = new MiBandActivitySample(
null,
timestampInSeconds,
@ -352,16 +351,12 @@ public class FetchActivityOperation extends AbstractMiBandOperation {
minutes++;
timestampInSeconds += 60;
}
dbHandler.addGBActivitySamples(samples);
provider.addGBActivitySamples(samples);
} finally {
activityStruct.bufferFlushed(minutes);
}
} catch (Exception ex) {
GB.toast(getContext(), ex.getMessage(), Toast.LENGTH_LONG, GB.ERROR, ex);
} finally {
if (dbHandler != null) {
dbHandler.release();
}
}
}

View File

@ -6,8 +6,13 @@ import android.util.Pair;
import java.util.ArrayList;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.PebbleActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class AppMessageHandler {
protected final PebbleProtocol mPebbleProtocol;
@ -30,10 +35,11 @@ public class AppMessageHandler {
return null;
}
protected PebbleActivitySample createSample(int timestamp, int intensity, int steps, int type) {
// TODO: user and device id
Long userId = null;
Long deviceId = null;
return new PebbleActivitySample(null, timestamp, intensity, steps, type, userId, deviceId);
protected PebbleActivitySample createSample(int timestamp, int intensity, int steps, int type, User user, Device device) {
return new PebbleActivitySample(null, timestamp, intensity, steps, type, user.getId(), device.getId());
}
protected GBDevice getDevice() {
return mPebbleProtocol.getDevice();
}
}

View File

@ -15,11 +15,15 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleGadgetBridgeSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
public class AppMessageHandlerGBPebble extends AppMessageHandler {
@ -50,10 +54,10 @@ public class AppMessageHandlerGBPebble extends AppMessageHandler {
int samples_remaining = samples.length / 2;
LOG.info("got " + samples_remaining + " samples");
int offset_seconds = 0;
DBHandler db = null;
try {
// db = GBApplication.acquireDB();
db = new PebbleGadgetBridgeSampleProvider(GBApplication.getDaoSession());
try (DBHandler db = GBApplication.acquireDB()) {
User user = DBHelper.getUser(db.getDaoSession());
Device device = DBHelper.getDevice(getDevice(), db.getDaoSession());
PebbleGadgetBridgeSampleProvider sampleProvider = new PebbleGadgetBridgeSampleProvider(db.getDaoSession());
AbstractActivitySample[] activitySamples = new AbstractActivitySample[samples_remaining];
int i = 0;
while (samples_remaining-- > 0) {
@ -61,16 +65,12 @@ public class AppMessageHandlerGBPebble extends AppMessageHandler {
int type = ((sample & 0xe000) >>> 13);
int intensity = ((sample & 0x1f80) >>> 7);
int steps = (sample & 0x007f);
activitySamples[i++] = createSample(timestamp + offset_seconds, intensity, steps, type);
activitySamples[i++] = createSample(timestamp + offset_seconds, intensity, steps, type, user, device);
offset_seconds += 60;
}
db.addGBActivitySamples(activitySamples);
// } catch (GBException e) {
// LOG.error("Error acquiring database", e);
} finally {
if (db != null) {
db.release();
}
sampleProvider.addGBActivitySamples(activitySamples);
} catch (Exception e) {
LOG.error("Error acquiring database", e);
}
break;
default:

View File

@ -15,6 +15,7 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.MisfitSampleProvider;
@ -41,8 +42,6 @@ public class AppMessageHandlerMisfit extends AppMessageHandler {
super(uuid, pebbleProtocol);
}
private final MisfitSampleProvider sampleProvider = new MisfitSampleProvider(GBApplication.getDaoSession());
@Override
public GBDeviceEvent[] handleMessage(ArrayList<Pair<Integer, Object>> pairs) {
for (Pair<Integer, Object> pair : pairs) {
@ -73,55 +72,48 @@ public class AppMessageHandlerMisfit extends AppMessageHandler {
int totalSteps = 0;
AbstractActivitySample[] activitySamples = new AbstractActivitySample[samples];
// TODO: user and device id
Long userId = null;
Long deviceId = null;
for (int i = 0; i < samples; i++) {
short sample = buf.getShort();
int steps = 0;
int intensity = 0;
int activityKind = ActivityKind.TYPE_UNKNOWN;
try (DBHandler db = GBApplication.acquireDB()) {
Long userId = DBHelper.getUser(db.getDaoSession()).getId();
Long deviceId = DBHelper.getDevice(getDevice(), db.getDaoSession()).getId();
for (int i = 0; i < samples; i++) {
short sample = buf.getShort();
int steps = 0;
int intensity = 0;
int activityKind = ActivityKind.TYPE_UNKNOWN;
if (((sample & 0x83ff) == 0x0001) && ((sample & 0xff00) <= 0x4800)) {
// sleep seems to be from 0x2401 to 0x4801 (0b0IIIII0000000001) where I = intensity ?
intensity = (sample & 0x7c00) >>> 10;
// 9-18 decimal after shift
if (intensity <= 13) {
activityKind = ActivityKind.TYPE_DEEP_SLEEP;
if (((sample & 0x83ff) == 0x0001) && ((sample & 0xff00) <= 0x4800)) {
// sleep seems to be from 0x2401 to 0x4801 (0b0IIIII0000000001) where I = intensity ?
intensity = (sample & 0x7c00) >>> 10;
// 9-18 decimal after shift
if (intensity <= 13) {
activityKind = ActivityKind.TYPE_DEEP_SLEEP;
} else {
// FIXME: this leads to too much false positives, ignore for now
//activityKind = ActivityKind.TYPE_LIGHT_SLEEP;
//intensity *= 2; // better visual distinction
}
} else {
// FIXME: this leads to too much false positives, ignore for now
//activityKind = ActivityKind.TYPE_LIGHT_SLEEP;
//intensity *= 2; // better visual distinction
if ((sample & 0x0001) == 0) { // 16-??? steps encoded in bits 1-7
steps = (sample & 0x00fe);
} else { // 0-14 steps encoded in bits 1-3, most of the time fc71 bits are set in that case
steps = (sample & 0x000e);
}
intensity = steps;
activityKind = ActivityKind.TYPE_ACTIVITY;
}
} else {
if ((sample & 0x0001) == 0) { // 16-??? steps encoded in bits 1-7
steps = (sample & 0x00fe);
} else { // 0-14 steps encoded in bits 1-3, most of the time fc71 bits are set in that case
steps = (sample & 0x000e);
}
intensity = steps;
activityKind = ActivityKind.TYPE_ACTIVITY;
totalSteps += steps;
LOG.info("got steps for sample " + i + " : " + steps + "(" + Integer.toHexString(sample & 0xffff) + ")");
activitySamples[i] = new PebbleActivitySample(null, timestamp + i * 60, intensity, steps, activityKind, userId, deviceId);
}
LOG.info("total steps for above period: " + totalSteps);
totalSteps += steps;
LOG.info("got steps for sample " + i + " : " + steps + "(" + Integer.toHexString(sample & 0xffff) + ")");
activitySamples[i] = new PebbleActivitySample(null, timestamp + i * 60, intensity, steps, activityKind, userId, deviceId);
}
LOG.info("total steps for above period: " + totalSteps);
DBHandler db = null;
try {
// db = GBApplication.acquireDB();
db = sampleProvider;
db.addGBActivitySamples(activitySamples);
// } catch (GBException e) {
// LOG.error("Error acquiring database", e);
// return null;
} finally {
if (db != null) {
db.release();
}
MisfitSampleProvider sampleProvider = new MisfitSampleProvider(db.getDaoSession());
sampleProvider.addGBActivitySamples(activitySamples);
} catch (Exception e) {
LOG.error("Error acquiring database", e);
return null;
}
break;
default:

View File

@ -13,11 +13,15 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.GBException;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSleepMonitorResult;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.MorpheuzSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
public class AppMessageHandlerMorpheuz extends AppMessageHandler {
@ -90,17 +94,13 @@ public class AppMessageHandlerMorpheuz extends AppMessageHandler {
type = MorpheuzSampleProvider.TYPE_LIGHT_SLEEP;
}
if (index >= 0) {
DBHandler db = null;
try {
// db = GBApplication.acquireDB();
db = new MorpheuzSampleProvider(GBApplication.getDaoSession());
db.addGBActivitySample(createSample(recording_base_timestamp + index * 600, intensity, 0, type));
// } catch (GBException e) {
// LOG.error("Error acquiring database", e);
} finally {
if (db != null) {
db.release();
}
try (DBHandler db = GBApplication.acquireDB()) {
User user = DBHelper.getUser(db.getDaoSession());
Device device = DBHelper.getDevice(getDevice(), db.getDaoSession());
MorpheuzSampleProvider sampleProvider = new MorpheuzSampleProvider(db.getDaoSession());
sampleProvider.addGBActivitySample(createSample(recording_base_timestamp + index * 600, intensity, 0, type, user, device));
} catch (Exception e) {
LOG.error("Error acquiring database", e);
}
}

View File

@ -66,10 +66,8 @@ class DatalogSessionHealthSleep extends DatalogSession {
}
private boolean store84(SleepRecord84[] sleepRecords) {
DBHandler dbHandler = null;
SampleProvider sampleProvider = new HealthSampleProvider(GBApplication.getDaoSession());
try {
dbHandler = GBApplication.acquireDB();
try (DBHandler dbHandler = GBApplication.acquireDB()) {
SampleProvider sampleProvider = new HealthSampleProvider(dbHandler.getDaoSession());
int latestTimestamp = dbHandler.fetchLatestTimestamp(sampleProvider);
for (SleepRecord84 sleepRecord : sleepRecords) {
if (latestTimestamp < (sleepRecord.timestampStart + sleepRecord.durationSeconds))
@ -83,10 +81,6 @@ class DatalogSessionHealthSleep extends DatalogSession {
}
} catch (Exception ex) {
LOG.debug(ex.getMessage());
} finally {
if (dbHandler != null) {
dbHandler.release();
}
}
return true;
}
@ -119,11 +113,9 @@ class DatalogSessionHealthSleep extends DatalogSession {
}
private boolean store83(SleepRecord83[] sleepRecords) {
DBHandler dbHandler = null;
SampleProvider sampleProvider = new HealthSampleProvider(GBApplication.getDaoSession());
GB.toast("Deep sleep is supported only from firmware 3.11 onwards.", Toast.LENGTH_LONG, GB.INFO);
try {
dbHandler = GBApplication.acquireDB();
try (DBHandler dbHandler = GBApplication.acquireDB()) {
SampleProvider sampleProvider = new HealthSampleProvider(dbHandler.getDaoSession());
GB.toast("Deep sleep is supported only from firmware 3.11 onwards.", Toast.LENGTH_LONG, GB.INFO);
int latestTimestamp = dbHandler.fetchLatestTimestamp(sampleProvider);
for (SleepRecord83 sleepRecord : sleepRecords) {
if (latestTimestamp < sleepRecord.bedTimeEnd)
@ -132,10 +124,6 @@ class DatalogSessionHealthSleep extends DatalogSession {
}
} catch (Exception ex) {
LOG.debug(ex.getMessage());
} finally {
if (dbHandler != null) {
dbHandler.release();
}
}
return true;
}

View File

@ -9,11 +9,13 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.HealthSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.PebbleActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBActivitySample;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -21,10 +23,12 @@ import nodomain.freeyourgadget.gadgetbridge.util.GB;
public class DatalogSessionHealthSteps extends DatalogSession {
private static final Logger LOG = LoggerFactory.getLogger(DatalogSessionHealthSteps.class);
private final GBDevice device;
public DatalogSessionHealthSteps(byte id, UUID uuid, int tag, byte item_type, short item_size) {
public DatalogSessionHealthSteps(byte id, UUID uuid, int tag, byte item_type, short item_size, GBDevice device) {
super(id, uuid, tag, item_type, item_size);
taginfo = "(health - steps)";
this.device = device;
}
@Override
@ -72,34 +76,26 @@ public class DatalogSessionHealthSteps extends DatalogSession {
private void store(StepsRecord[] stepsRecords) {
HealthSampleProvider sampleProvider = new HealthSampleProvider(GBApplication.getDaoSession());
DBHandler dbHandler = sampleProvider;
try (DBHandler dbHandler = GBApplication.acquireDB()) {
HealthSampleProvider sampleProvider = new HealthSampleProvider(dbHandler.getDaoSession());
AbstractActivitySample[] samples = new AbstractActivitySample[stepsRecords.length];
// TODO: user and device
Long userId = DBHelper.getUser(dbHandler.getDaoSession()).getId();
Long deviceId = DBHelper.getDevice(device, dbHandler.getDaoSession()).getId();
for (int j = 0; j < stepsRecords.length; j++) {
StepsRecord stepsRecord = stepsRecords[j];
samples[j] = new PebbleActivitySample(
null,
stepsRecord.timestamp,
stepsRecord.intensity,
stepsRecord.steps,
sampleProvider.toRawActivityKind(ActivityKind.TYPE_ACTIVITY),
userId, deviceId);
}
AbstractActivitySample[] samples = new AbstractActivitySample[stepsRecords.length];
// TODO: user and device
Long userId = null;
Long deviceId = null;
for (int j = 0; j < stepsRecords.length; j++) {
StepsRecord stepsRecord = stepsRecords[j];
samples[j] = new PebbleActivitySample(
null,
stepsRecord.timestamp,
stepsRecord.intensity,
stepsRecord.steps,
sampleProvider.toRawActivityKind(ActivityKind.TYPE_ACTIVITY),
userId, deviceId);
}
try {
// dbHandler = GBApplication.acquireDB();
dbHandler = sampleProvider;
dbHandler.addGBActivitySamples(samples);
sampleProvider.addGBActivitySamples(samples);
} catch (Exception ex) {
LOG.debug(ex.getMessage());
} finally {
if (dbHandler != null) {
dbHandler.release();
}
}
}

View File

@ -31,6 +31,7 @@ import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventSendBytes;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEventVersionInfo;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleColor;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleIconID;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceApp;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
@ -361,16 +362,16 @@ public class PebbleProtocol extends GBDeviceProtocol {
private static final UUID UUID_PEBSTYLE = UUID.fromString("da05e84d-e2a2-4020-a2dc-9cdcf265fcdd");
private static final UUID UUID_ZERO = new UUID(0, 0);
private static final Map<UUID, AppMessageHandler> mAppMessageHandlers = new HashMap<>();
private final Map<UUID, AppMessageHandler> mAppMessageHandlers = new HashMap<>();
{
public PebbleProtocol(GBDevice device) {
super(device);
mAppMessageHandlers.put(UUID_GBPEBBLE, new AppMessageHandlerGBPebble(UUID_GBPEBBLE, PebbleProtocol.this));
mAppMessageHandlers.put(UUID_MORPHEUZ, new AppMessageHandlerMorpheuz(UUID_MORPHEUZ, PebbleProtocol.this));
mAppMessageHandlers.put(UUID_WHETHERNEAT, new AppMessageHandlerWeatherNeat(UUID_WHETHERNEAT, PebbleProtocol.this));
mAppMessageHandlers.put(UUID_MISFIT, new AppMessageHandlerMisfit(UUID_MISFIT, PebbleProtocol.this));
mAppMessageHandlers.put(UUID_PEBBLE_TIMESTYLE, new AppMessageHandlerTimeStylePebble(UUID_PEBBLE_TIMESTYLE, PebbleProtocol.this));
mAppMessageHandlers.put(UUID_PEBSTYLE, new AppMessageHandlerPebStyle(UUID_PEBSTYLE, PebbleProtocol.this));
}
private final HashMap<Byte, DatalogSession> mDatalogSessions = new HashMap<>();
@ -1880,7 +1881,7 @@ public class PebbleProtocol extends GBDeviceProtocol {
LOG.info("DATALOG OPENSESSION. id=" + (id & 0xff) + ", App UUID=" + uuid.toString() + ", log_tag=" + log_tag + ", item_type=" + item_type + ", itemSize=" + item_size);
if (!mDatalogSessions.containsKey(id)) {
if (uuid.equals(UUID_ZERO) && log_tag == 81) {
mDatalogSessions.put(id, new DatalogSessionHealthSteps(id, uuid, log_tag, item_type, item_size));
mDatalogSessions.put(id, new DatalogSessionHealthSteps(id, uuid, log_tag, item_type, item_size, getDevice()));
} else if (uuid.equals(UUID_ZERO) && (log_tag == 83 || log_tag == 84)) {
mDatalogSessions.put(id, new DatalogSessionHealthSleep(id, uuid, log_tag, item_type, item_size));
} else {

View File

@ -29,7 +29,7 @@ public class PebbleSupport extends AbstractSerialDeviceSupport {
@Override
protected GBDeviceProtocol createDeviceProtocol() {
return new PebbleProtocol();
return new PebbleProtocol(getDevice());
}
@Override

View File

@ -3,10 +3,17 @@ package nodomain.freeyourgadget.gadgetbridge.service.serial;
import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.deviceevents.GBDeviceEvent;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
public abstract class GBDeviceProtocol {
private GBDevice mDevice;
protected GBDeviceProtocol(GBDevice device) {
mDevice = device;
}
public byte[] encodeNotification(NotificationSpec notificationSpec) {
return null;
}
@ -68,4 +75,8 @@ public abstract class GBDeviceProtocol {
public GBDeviceEvent[] decodeResponse(byte[] responseData) {
return null;
}
public GBDevice getDevice() {
return mDevice;
}
}