Skip to content
Snippets Groups Projects
Commit 2f03c9a5 authored by Volker Richert's avatar Volker Richert
Browse files

- fixes to Realm update

- optimize Wakeup handling
- update to realm onChangeListener
parent 51903350
Branches
Tags
No related merge requests found
......@@ -52,8 +52,6 @@ import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
import com.github.mikephil.charting.listener.ChartTouchListener;
import com.github.mikephil.charting.listener.OnChartGestureListener;
import com.github.mikephil.charting.utils.ViewPortHandler;
import com.google.android.gms.appindexing.Action;
import com.google.android.gms.appindexing.Thing;
import com.mikepenz.google_material_typeface_library.GoogleMaterial;
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
import com.mikepenz.materialdrawer.Drawer;
......@@ -83,6 +81,7 @@ import info.nightscout.android.settings.SettingsActivity;
import info.nightscout.android.upload.nightscout.NightscoutUploadIntentService;
import io.realm.DynamicRealmObject;
import io.realm.Realm;
import io.realm.RealmChangeListener;
import io.realm.RealmResults;
import io.realm.Sort;
import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper;
......@@ -97,6 +96,7 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
private static long activePumpMac;
boolean mEnableCgmService = true;
SharedPreferences prefs = null;
private PumpInfo mActivePump;
......@@ -109,9 +109,20 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
private StatusMessageReceiver statusMessageReceiver = new StatusMessageReceiver();
private MedtronicCnlAlarmReceiver medtronicCnlAlarmReceiver = new MedtronicCnlAlarmReceiver();
public static long getNextPoll(PumpStatusEvent pumpStatusData) {
long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset()
+ MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
public static void setActivePumpMac(long pumpMac) {
activePumpMac = pumpMac;
if (pumpStatusData.getBatteryPercentage() > 25) {
// poll every 5 min
nextPoll += MainActivity.pollInterval;
} else {
// if pump battery seems to be empty reduce polling to save battery (every 15 min)
//TODO add message & document it
nextPoll += MainActivity.lowBatteryPollInterval;
}
return nextPoll;
}
@Override
......@@ -162,8 +173,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
statusMessageReceiver,
new IntentFilter(MedtronicCnlIntentService.Constants.ACTION_STATUS_MESSAGE));
LocalBroadcastManager.getInstance(this).registerReceiver(
new RefreshDataReceiver(),
new IntentFilter(MedtronicCnlIntentService.Constants.ACTION_REFRESH_DATA));
new UpdatePumpReceiver(),
new IntentFilter(MedtronicCnlIntentService.Constants.ACTION_UPDATE_PUMP));
mEnableCgmService = Eula.show(this, prefs);
......@@ -533,9 +544,17 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
}
}
public static void setActivePumpMac(long pumpMac) {
activePumpMac = pumpMac;
}
private PumpInfo getActivePump() {
if (activePumpMac != 0L && (mActivePump == null || !mActivePump.isValid() || mActivePump.getPumpMac() != activePumpMac)) {
if (mActivePump != null) {
// remove listener on old pump
mActivePump.removeChangeListeners();
mActivePump = null;
}
PumpInfo pump = mRealm
.where(PumpInfo.class)
......@@ -544,28 +563,51 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
if (pump != null && pump.isValid()) {
mActivePump = pump;
}
mActivePump.addChangeListener(new RealmChangeListener<PumpInfo>() {
long lastQueryTS = 0;
@Override
public void onChange(PumpInfo pump) {
// prevent double updating after deleting old events below
if (pump.getLastQueryTS() == lastQueryTS || !pump.isValid()) {
return;
}
return mActivePump;
PumpStatusEvent pumpStatusData = pump.getPumpHistory().last();;
lastQueryTS = pump.getLastQueryTS();
startCgmService(MainActivity.getNextPoll(pumpStatusData));
// Delete invalid or old records from Realm
// TODO - show an error message if the valid records haven't been uploaded
final RealmResults<PumpStatusEvent> results =
mRealm.where(PumpStatusEvent.class)
.equalTo("sgv", 0)
.or()
.lessThan("eventDate", new Date(System.currentTimeMillis() - (24 * 60 * 60 * 1000)))
.findAll();
if (results.size() > 0) {
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// Delete all matches
Log.d(TAG, "Deleting " + results.size() + " records from realm");
results.deleteAllFromRealm();
}
});
}
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
public Action getIndexApiAction() {
Thing object = new Thing.Builder()
.setName("Main Page") // TODO: Define a title for the content shown.
// TODO: Make sure this auto-generated URL is correct.
.setUrl(Uri.parse("http://[ENTER-YOUR-URL-HERE]"))
.build();
return new Action.Builder(Action.TYPE_VIEW)
.setObject(object)
.setActionStatus(Action.STATUS_TYPE_COMPLETED)
.build();
// TODO - handle isOffline in NightscoutUploadIntentService?
uploadCgmData();
refreshDisplay();
}
});
}
}
return mActivePump;
}
private class StatusMessageReceiver extends BroadcastReceiver {
private class StatusMessage {
......@@ -656,6 +698,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
PumpInfo pump = getActivePump();
if (pump != null && pump.isValid()) {
Log.d(TAG, "history display refresh size: " + pump.getPumpHistory().size());
Log.d(TAG, "history display refresh date: " + pump.getPumpHistory().last().getEventDate());
pumpStatusData = pump.getPumpHistory().last();
}
......@@ -796,7 +840,10 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
}
}
private class RefreshDataReceiver extends BroadcastReceiver {
/**
* has to be done in MainActivity thread
*/
private class UpdatePumpReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
......@@ -805,54 +852,8 @@ public class MainActivity extends AppCompatActivity implements OnSharedPreferenc
if (mRealm.isClosed()) {
return;
}
PumpStatusEvent pumpStatusData = null;
PumpInfo pump = getActivePump();
if (pump != null && pump.isValid()) {
pumpStatusData = pump.getPumpHistory().last();
} else {
return;
}
long nextPoll = pumpStatusData.getEventDate().getTime() + pumpStatusData.getPumpTimeOffset()
+ MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS;
if (pumpStatusData.getBatteryPercentage() > 25) {
// poll every 5 min
nextPoll += MainActivity.pollInterval;
} else {
// if pump battery seems to be empty reduce polling to save battery (every 15 min)
//TODO add message & document it
nextPoll += MainActivity.lowBatteryPollInterval;
}
startCgmService(nextPoll);
// Delete invalid or old records from Realm
// TODO - show an error message if the valid records haven't been uploaded
final RealmResults<PumpStatusEvent> results =
mRealm.where(PumpStatusEvent.class)
.equalTo("sgv", 0)
.or()
.lessThan("eventDate", new Date(System.currentTimeMillis() - (24 * 60 * 60 * 1000)))
.findAll();
if (results.size() > 0) {
mRealm.executeTransaction(new Realm.Transaction() {
@Override
public void execute(Realm realm) {
// Delete all matches
Log.d(TAG, "Deleting " + results.size() + " records from realm");
results.deleteAllFromRealm();
}
});
}
// TODO - handle isOffline in NightscoutUploadIntentService?
uploadCgmData();
refreshDisplay();
//init local pump listener
getActivePump();
}
}
......
......@@ -125,6 +125,7 @@ public class PumpStatusResponseMessage extends MedtronicSendMessageResponseMessa
// TODO - this should go in the sgvDate, and eventDate should be the time of this poll.
sgvDate = MessageUtils.decodeDateTime(rtc, offset);
Log.d(TAG, "original sgv date: " + sgvDate);
// Predictive low suspend
// TODO - there is more status info in this byte other than just a boolean yes/no
......
......@@ -50,6 +50,8 @@ public class MedtronicCnlAlarmManager {
if (alarmManager == null || pendingIntent == null)
return;
Log.d(TAG, "request to set Alarm at " + new Date(millis));
long now = System.currentTimeMillis();
// don't trigger the past
if (millis < now)
......
......@@ -38,6 +38,8 @@ import info.nightscout.android.xdrip_plus.XDripPlusUploadReceiver;
import io.realm.Realm;
import io.realm.RealmResults;
import static info.nightscout.android.medtronic.MainActivity.setActivePumpMac;
public class MedtronicCnlIntentService extends IntentService {
public final static int USB_VID = 0x1a79;
public final static int USB_PID = 0x6210;
......@@ -154,10 +156,11 @@ public class MedtronicCnlIntentService extends IntentService {
if (info == null) {
// TODO - use realm.createObject()?
info = new ContourNextLinkInfo();
info.setSerialNumber(cnlReader.getStickSerial());
info = realm.createObject(ContourNextLinkInfo.class, cnlReader.getStickSerial());
//info = new ContourNextLinkInfo();
///info.setSerialNumber(cnlReader.getStickSerial());
info = realm.copyToRealm(info);
//info = realm.copyToRealm(info);
}
cnlReader.getPumpSession().setStickSerial(info.getSerialNumber());
......@@ -182,17 +185,19 @@ public class MedtronicCnlIntentService extends IntentService {
long pumpMAC = cnlReader.getPumpSession().getPumpMAC();
Log.i(TAG, "PumpInfo MAC: " + (pumpMAC & 0xffffff));
MainActivity.setActivePumpMac(pumpMAC);
PumpInfo activePump = realm
.where(PumpInfo.class)
.equalTo("pumpMac", pumpMAC)
.findFirst();
if (activePump == null) {
activePump = realm.createObject(PumpInfo.class);
activePump.setPumpMac(pumpMAC);
activePump = realm.createObject(PumpInfo.class, pumpMAC);
//activePump.setPumpMac(pumpMAC);
}
activePump.updateLastQueryTS();
byte radioChannel = cnlReader.negotiateChannel(activePump.getLastRadioChannel());
if (radioChannel == 0) {
sendStatus("Could not communicate with the 640g. Are you near the pump?");
......@@ -204,6 +209,7 @@ public class MedtronicCnlIntentService extends IntentService {
(MainActivity.pollInterval + MedtronicCnlIntentService.POLL_GRACE_PERIOD_MS) / (MainActivity.reducePollOnPumpAway?2L:1L)
);
} else {
setActivePumpMac(pumpMAC);
activePump.setLastRadioChannel(radioChannel);
sendStatus(String.format(Locale.getDefault(), "Connected to Contour Next Link on channel %d.", (int) radioChannel));
Log.d(TAG, String.format("Connected to Contour Next Link on channel %d.", (int) radioChannel));
......@@ -226,21 +232,9 @@ public class MedtronicCnlIntentService extends IntentService {
pumpRecord.setPumpTimeOffset(pumpOffset);
pumpRecord.setPumpDate(new Date(pumpTime - pumpOffset));
cnlReader.updatePumpStatus(pumpRecord);
activePump.getPumpHistory().add(pumpRecord);
// start reading other data in debug only
if (BuildConfig.DEBUG) {
// read basal pattern
//cnlReader.getBasalPatterns();
// Read history
//cnlReader.getHistory();
}
cnlReader.endEHSMSession();
boolean cancelTransaction = true;
if (pumpRecord.getSgv() != 0) {
// Check that the record doesn't already exist before committing
RealmResults<PumpStatusEvent> checkExistingRecords = activePump.getPumpHistory()
......@@ -250,18 +244,17 @@ public class MedtronicCnlIntentService extends IntentService {
.findAll();
// There should be the 1 record we've already added in this transaction.
if (checkExistingRecords.size() <= 1) {
realm.commitTransaction();
cancelTransaction = false;
if (checkExistingRecords.size() == 0) {
activePump.getPumpHistory().add(pumpRecord);
}
// Tell the Main Activity we have new data
sendMessage(Constants.ACTION_REFRESH_DATA);
Log.d(TAG, "history reading size: " + activePump.getPumpHistory().size());
Log.d(TAG, "history reading date: " + activePump.getPumpHistory().last().getEventDate());
}
if (cancelTransaction) {
realm.cancelTransaction();
}
realm.commitTransaction();
// Tell the Main Activity we have new data
sendMessage(Constants.ACTION_UPDATE_PUMP);
}
} catch (UnexpectedMessageException e) {
Log.e(TAG, "Unexpected Message", e);
......@@ -308,6 +301,10 @@ public class MedtronicCnlIntentService extends IntentService {
}
}
private void setActivePumpMac(long pumpMAC) {
MainActivity.setActivePumpMac(pumpMAC);
}
// reliable wake alarm manager wake up for all android versions
public static void wakeUpIntent(Context context, long wakeTime, PendingIntent pendingIntent) {
final AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
......@@ -347,6 +344,7 @@ public class MedtronicCnlIntentService extends IntentService {
public static final String ACTION_USB_PERMISSION = "info.nightscout.android.medtronic.USB_PERMISSION";
public static final String ACTION_REFRESH_DATA = "info.nightscout.android.medtronic.service.CGM_DATA";
public static final String ACTION_USB_REGISTER = "info.nightscout.android.medtronic.USB_REGISTER";
public static final String ACTION_UPDATE_PUMP = "info.nightscout.android.medtronic.UPDATE_PUMP";
public static final String EXTENDED_DATA = "info.nightscout.android.medtronic.service.DATA";
}
......
......@@ -2,6 +2,8 @@ package info.nightscout.android.model.medtronicNg;
import io.realm.RealmList;
import io.realm.RealmObject;
import io.realm.Sort;
import io.realm.annotations.Ignore;
import io.realm.annotations.PrimaryKey;
/**
......@@ -12,6 +14,7 @@ public class PumpInfo extends RealmObject {
private long pumpMac;
private String deviceName;
private byte lastRadioChannel;
private long lastQueryTS = 0;
private RealmList<ContourNextLinkInfo> associatedCnls;
private RealmList<PumpStatusEvent> pumpHistory;
......@@ -19,7 +22,7 @@ public class PumpInfo extends RealmObject {
return pumpMac;
}
public void setPumpMac(long pumpMac) {
private void setPumpMac(long pumpMac) {
this.pumpMac = pumpMac;
}
......@@ -58,4 +61,12 @@ public class PumpInfo extends RealmObject {
public long getPumpSerial() {
return pumpMac & 0xffffff;
}
public long getLastQueryTS() {
return lastQueryTS;
}
public void updateLastQueryTS() {
lastQueryTS = System.currentTimeMillis();
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment