diff --git a/README-Combo.md b/README-Combo.md index b4c42f30aa..096d94e697 100644 --- a/README-Combo.md +++ b/README-Combo.md @@ -39,6 +39,9 @@ Limitations: pump solely through AAPS. Checking history, reservoir level etc on the pump causes no issues but should be avoided when the Bluetooth icon is displayed on the display, indicating that AAPS is communicating with the pump. +- Currently only basal rates in the range of 0.05 to 10 U/h are supported (this also applies when modifying + a profile, e.g. when increasing to 200%, the highest basal rate must not exceed 5 U/h since it will be + doubled. Similarly, when reducing to 50%, the lowest basal rate must be at least 0.10 U/h). Setup: - Configure pump using 360 config software. diff --git a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java index c8d8dbe808..3fec202ae0 100644 --- a/app/src/main/java/info/nightscout/androidaps/Services/DataService.java +++ b/app/src/main/java/info/nightscout/androidaps/Services/DataService.java @@ -117,10 +117,8 @@ public class DataService extends IntentService { handleNewDataFromDexcomG5(intent); } } else if (Intents.ACTION_NEW_SGV.equals(action)) { - // always handle SGV if NS-Client is the source - if (nsClientEnabled) { - handleNewDataFromNSClient(intent); - } + // always backfill SGV from NS + handleNewDataFromNSClient(intent); // Objectives 0 ObjectivesPlugin.bgIsAvailableInNS = true; ObjectivesPlugin.saveProgress(); @@ -301,7 +299,7 @@ public class DataService extends IntentService { log.error("Unhandled exception", e); } if (ConfigBuilderPlugin.nightscoutVersionCode < Config.SUPPORTEDNSVERSION) { - Notification notification = new Notification(Notification.OLD_NS, MainApp.sResources.getString(R.string.unsupportednsversion), Notification.URGENT); + Notification notification = new Notification(Notification.OLD_NS, MainApp.sResources.getString(R.string.unsupportednsversion), Notification.NORMAL); MainApp.bus().post(new EventNewNotification(notification)); } else { MainApp.bus().post(new EventDismissNotification(Notification.OLD_NS)); diff --git a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java index 4d43f942e3..c8d5295811 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/BgReading.java +++ b/app/src/main/java/info/nightscout/androidaps/db/BgReading.java @@ -53,6 +53,7 @@ public class BgReading implements DataPointWithLabelInterface { value = sgv.getMgdl(); raw = sgv.getFiltered() != null ? sgv.getFiltered() : value; direction = sgv.getDirection(); + _id = sgv.getId(); } public Double valueToUnits(String units) { diff --git a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java index 0dcbc62c64..b9a34ddb58 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java +++ b/app/src/main/java/info/nightscout/androidaps/db/DatabaseHelper.java @@ -367,6 +367,15 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { return false; } + public void update(BgReading bgReading) { + bgReading.date = roundDateToSec(bgReading.date); + try { + getDaoBgReadings().update(bgReading); + } catch (SQLException e) { + e.printStackTrace(); + } + } + private static void scheduleBgChange() { class PostRunnable implements Runnable { public void run() { @@ -397,7 +406,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { QueryBuilder queryBuilder = daoBgReadings.queryBuilder(); queryBuilder.orderBy("date", false); queryBuilder.limit(1L); - queryBuilder.where().gt("value", 38); + queryBuilder.where().gt("value", 38).and().eq("isValid", true); PreparedQuery preparedQuery = queryBuilder.prepare(); bgList = daoBgReadings.query(preparedQuery); @@ -435,7 +444,24 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper { QueryBuilder queryBuilder = daoBgreadings.queryBuilder(); queryBuilder.orderBy("date", ascending); Where where = queryBuilder.where(); - where.ge("date", mills).and().gt("value", 38); + where.ge("date", mills).and().gt("value", 38).and().eq("isValid", true); + PreparedQuery preparedQuery = queryBuilder.prepare(); + bgReadings = daoBgreadings.query(preparedQuery); + return bgReadings; + } catch (SQLException e) { + log.error("Unhandled exception", e); + } + return new ArrayList(); + } + + public List getAllBgreadingsDataFromTime(long mills, boolean ascending) { + try { + Dao daoBgreadings = getDaoBgReadings(); + List bgReadings; + QueryBuilder queryBuilder = daoBgreadings.queryBuilder(); + queryBuilder.orderBy("date", ascending); + Where where = queryBuilder.where(); + where.ge("date", mills); PreparedQuery preparedQuery = queryBuilder.prepare(); bgReadings = daoBgreadings.query(preparedQuery); return bgReadings; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java index 18f092966e..910f032fc5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Actions/ActionsFragment.java @@ -127,8 +127,7 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL return; } final PumpInterface pump = ConfigBuilderPlugin.getActivePump(); - boolean allowProfileSwitch = MainApp.getConfigBuilder().getActiveProfileInterface().getProfile().getProfileList().size() > 1; - if (!pump.getPumpDescription().isSetBasalProfileCapable || !pump.isInitialized() || pump.isSuspended() || !allowProfileSwitch) + if (!pump.getPumpDescription().isSetBasalProfileCapable || !pump.isInitialized() || pump.isSuspended()) profileSwitch.setVisibility(View.GONE); else profileSwitch.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java index 114ace4c30..889128abdc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/UploadQueue.java @@ -96,6 +96,8 @@ public class UploadQueue { } public static void removeID(final String action, final String _id) { + if (_id == null || _id.equals("")) + return; startService(); if (NSClientService.handler != null) { NSClientService.handler.post(new Runnable() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java index c6158be296..43c46bf072 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/broadcasts/BroadcastTreatment.java @@ -1,10 +1,7 @@ package info.nightscout.androidaps.plugins.NSClientInternal.broadcasts; -import android.content.Context; import android.content.Intent; -import android.content.pm.ResolveInfo; import android.os.Bundle; -import android.os.TransactionTooLargeException; import android.support.v4.content.LocalBroadcastManager; import org.json.JSONArray; @@ -19,9 +16,7 @@ import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.Services.Intents; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; import info.nightscout.utils.SP; -import info.nightscout.utils.ToastUtils; /** * Created by mike on 20.02.2016. @@ -29,31 +24,31 @@ import info.nightscout.utils.ToastUtils; public class BroadcastTreatment { private static Logger log = LoggerFactory.getLogger(BroadcastTreatment.class); - public static void handleNewTreatment(NSTreatment treatment, Context context, boolean isDelta) { + public static void handleNewTreatment(JSONObject treatment, boolean isDelta) { Bundle bundle = new Bundle(); - bundle.putString("treatment", treatment.getData().toString()); + bundle.putString("treatment", treatment.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { bundle = new Bundle(); - bundle.putString("treatment", treatment.getData().toString()); + bundle.putString("treatment", treatment.toString()); bundle.putBoolean("delta", isDelta); intent = new Intent(Intents.ACTION_NEW_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); + MainApp.instance().getApplicationContext().sendBroadcast(intent); } } - public static void handleNewTreatment(JSONArray treatments, Context context, boolean isDelta) { + public static void handleNewTreatment(JSONArray treatments, boolean isDelta) { List splitted = splitArray(treatments); - for (JSONArray part: splitted) { + for (JSONArray part : splitted) { Bundle bundle = new Bundle(); bundle.putString("treatments", part.toString()); bundle.putBoolean("delta", isDelta); @@ -63,21 +58,21 @@ public class BroadcastTreatment { LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); } - if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)){ + if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { splitted = splitArray(treatments); - for (JSONArray part: splitted) { + for (JSONArray part : splitted) { Bundle bundle = new Bundle(); bundle.putString("treatments", part.toString()); bundle.putBoolean("delta", isDelta); Intent intent = new Intent(Intents.ACTION_NEW_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); + MainApp.instance().getApplicationContext().sendBroadcast(intent); } } } - public void handleChangedTreatment(JSONObject treatment, Context context, boolean isDelta) { + public void handleChangedTreatment(JSONObject treatment, boolean isDelta) { Bundle bundle = new Bundle(); bundle.putString("treatment", treatment.toString()); @@ -88,18 +83,18 @@ public class BroadcastTreatment { LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { bundle = new Bundle(); bundle.putString("treatment", treatment.toString()); bundle.putBoolean("delta", isDelta); intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); + MainApp.instance().getApplicationContext().sendBroadcast(intent); } } - public static void handleChangedTreatment(JSONArray treatments, Context context, boolean isDelta) { + public static void handleChangedTreatment(JSONArray treatments, boolean isDelta) { List splitted = splitArray(treatments); for (JSONArray part : splitted) { @@ -112,7 +107,7 @@ public class BroadcastTreatment { LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); } - if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { splitted = splitArray(treatments); for (JSONArray part : splitted) { Bundle bundle = new Bundle(); @@ -121,12 +116,12 @@ public class BroadcastTreatment { Intent intent = new Intent(Intents.ACTION_CHANGED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); + MainApp.instance().getApplicationContext().sendBroadcast(intent); } } } - public static void handleRemovedTreatment(JSONObject treatment, Context context, boolean isDelta) { + public static void handleRemovedTreatment(JSONObject treatment, boolean isDelta) { Bundle bundle = new Bundle(); bundle.putString("treatment", treatment.toString()); @@ -137,18 +132,18 @@ public class BroadcastTreatment { LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { bundle = new Bundle(); bundle.putString("treatment", treatment.toString()); bundle.putBoolean("delta", isDelta); intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); + MainApp.instance().getApplicationContext().sendBroadcast(intent); } } - public static void handleRemovedTreatment(JSONArray treatments, Context context, boolean isDelta) { + public static void handleRemovedTreatment(JSONArray treatments, boolean isDelta) { Bundle bundle = new Bundle(); bundle.putString("treatments", treatments.toString()); @@ -159,14 +154,14 @@ public class BroadcastTreatment { LocalBroadcastManager.getInstance(MainApp.instance()).sendBroadcast(intent); - if(SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { + if (SP.getBoolean(R.string.key_nsclient_localbroadcasts, true)) { bundle = new Bundle(); bundle.putString("treatments", treatments.toString()); bundle.putBoolean("delta", isDelta); intent = new Intent(Intents.ACTION_REMOVED_TREATMENT); intent.putExtras(bundle); intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES); - context.sendBroadcast(intent); + MainApp.instance().getApplicationContext().sendBroadcast(intent); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java index af134ea50d..50336a5f52 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/data/NSSgv.java @@ -63,5 +63,6 @@ public class NSSgv { public Long getMills () { return getLongOrNull("mills"); } public String getDevice () { return getStringOrNull("device"); } public String getDirection () { return getStringOrNull("direction"); } + public String getId () { return getStringOrNull("_id"); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java index a9f3509213..3411659d0d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/receivers/DBAccessReceiver.java @@ -11,16 +11,14 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Date; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DbRequest; import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.plugins.NSClientInternal.NSClientInternalPlugin; import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; -import info.nightscout.androidaps.db.DbRequest; -import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; -import info.nightscout.androidaps.plugins.NSClientInternal.services.NSClientService; +import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment; +import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; public class DBAccessReceiver extends BroadcastReceiver { @@ -89,7 +87,12 @@ public class DBAccessReceiver extends BroadcastReceiver { UploadQueue.add(dbr); } else { DbRequest dbr = new DbRequest(action, collection, nsclientid.toString(), data); + // this is not used as mongo _id but only for searching in UploadQueue database + // if record has to be removed from queue before upload + dbr._id = nsclientid.toString(); UploadQueue.add(dbr); + if (collection.equals("treatments")) + genereateTreatmentOfflineBroadcast(dbr); } } finally { @@ -98,6 +101,19 @@ public class DBAccessReceiver extends BroadcastReceiver { } + public void genereateTreatmentOfflineBroadcast(DbRequest request) { + if (request.action.equals("dbAdd")) { + try { + JSONObject data = new JSONObject(request.data); + data.put("mills", DateUtil.fromISODateString(data.getString("created_at")).getTime()); + data.put("_id", data.get("NSCLIENT_ID")); // this is only fake id + BroadcastTreatment.handleNewTreatment(data, false); + } catch (Exception e) { + log.error("Unhadled exception", e); + } + } + } + private boolean isAllowedCollection(String collection) { // "treatments" || "entries" || "devicestatus" || "profile" || "food" if (collection.equals("treatments")) return true; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java index 3aa8acb17e..abd0f2b26b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/NSClientInternal/services/NSClientService.java @@ -52,15 +52,15 @@ import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastS import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.broadcasts.BroadcastUrgentAlarm; import info.nightscout.androidaps.plugins.NSClientInternal.data.AlarmAck; -import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSettingsStatus; +import info.nightscout.androidaps.plugins.NSClientInternal.data.NSSgv; import info.nightscout.androidaps.plugins.NSClientInternal.data.NSTreatment; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientNewLog; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientRestart; import info.nightscout.androidaps.plugins.NSClientInternal.events.EventNSClientStatus; -import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; +import info.nightscout.androidaps.plugins.Overview.notifications.Notification; import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; import io.socket.client.IO; @@ -310,17 +310,17 @@ public class NSClientService extends Service { }; private Emitter.Listener onAnnouncement = new Emitter.Listener() { -/* -{ -"level":0, -"title":"Announcement", -"message":"test", -"plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true}, -"group":"Announcement", -"isAnnouncement":true, -"key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da" -} - */ + /* + { + "level":0, + "title":"Announcement", + "message":"test", + "plugin":{"name":"treatmentnotify","label":"Treatment Notifications","pluginType":"notification","enabled":true}, + "group":"Announcement", + "isAnnouncement":true, + "key":"9ac46ad9a1dcda79dd87dae418fce0e7955c68da" + } + */ @Override public void call(final Object... args) { JSONObject data; @@ -342,19 +342,19 @@ public class NSClientService extends Service { }; private Emitter.Listener onAlarm = new Emitter.Listener() { -/* -{ -"level":1, -"title":"Warning HIGH", -"message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g", -"eventName":"high", -"plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, -"pushoverSound":"climb", -"debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, -"group":"default", -"key":"simplealarms_1" -} - */ + /* + { + "level":1, + "title":"Warning HIGH", + "message":"BG Now: 5 -0.2 → mmol\/L\nRaw BG: 4.8 mmol\/L Čistý\nBG 15m: 4.8 mmol\/L\nIOB: -0.02U\nCOB: 0g", + "eventName":"high", + "plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, + "pushoverSound":"climb", + "debug":{"lastSGV":5,"thresholds":{"bgHigh":180,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, + "group":"default", + "key":"simplealarms_1" + } + */ @Override public void call(final Object... args) { if (Config.detailedLog) @@ -372,19 +372,19 @@ public class NSClientService extends Service { }; private Emitter.Listener onUrgentAlarm = new Emitter.Listener() { -/* -{ -"level":2, -"title":"Urgent HIGH", -"message":"BG Now: 5.2 -0.1 → mmol\/L\nRaw BG: 5 mmol\/L Čistý\nBG 15m: 5 mmol\/L\nIOB: 0.00U\nCOB: 0g", -"eventName":"high", -"plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, -"pushoverSound":"persistent", -"debug":{"lastSGV":5.2,"thresholds":{"bgHigh":80,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, -"group":"default", -"key":"simplealarms_2" -} - */ + /* + { + "level":2, + "title":"Urgent HIGH", + "message":"BG Now: 5.2 -0.1 → mmol\/L\nRaw BG: 5 mmol\/L Čistý\nBG 15m: 5 mmol\/L\nIOB: 0.00U\nCOB: 0g", + "eventName":"high", + "plugin":{"name":"simplealarms","label":"Simple Alarms","pluginType":"notification","enabled":true}, + "pushoverSound":"persistent", + "debug":{"lastSGV":5.2,"thresholds":{"bgHigh":80,"bgTargetTop":75,"bgTargetBottom":72,"bgLow":70}}, + "group":"default", + "key":"simplealarms_2" + } + */ @Override public void call(final Object... args) { JSONObject data; @@ -402,14 +402,14 @@ public class NSClientService extends Service { }; private Emitter.Listener onClearAlarm = new Emitter.Listener() { -/* -{ -"clear":true, -"title":"All Clear", -"message":"default - Urgent was ack'd", -"group":"default" -} - */ + /* + { + "clear":true, + "title":"All Clear", + "message":"default - Urgent was ack'd", + "group":"default" + } + */ @Override public void call(final Object... args) { JSONObject data; @@ -520,17 +520,17 @@ public class NSClientService extends Service { updatedTreatments.put(jsonTreatment); } else if (treatment.getAction().equals("remove")) { if (treatment.getMills() != null && treatment.getMills() > System.currentTimeMillis() - 24 * 60 * 60 * 1000L) // handle 1 day old deletions only - removedTreatments.put(jsonTreatment); + removedTreatments.put(jsonTreatment); } } if (removedTreatments.length() > 0) { - BroadcastTreatment.handleRemovedTreatment(removedTreatments, MainApp.instance().getApplicationContext(), isDelta); + BroadcastTreatment.handleRemovedTreatment(removedTreatments, isDelta); } if (updatedTreatments.length() > 0) { - BroadcastTreatment.handleChangedTreatment(updatedTreatments, MainApp.instance().getApplicationContext(), isDelta); + BroadcastTreatment.handleChangedTreatment(updatedTreatments, isDelta); } if (addedTreatments.length() > 0) { - BroadcastTreatment.handleNewTreatment(addedTreatments, MainApp.instance().getApplicationContext(), isDelta); + BroadcastTreatment.handleNewTreatment(addedTreatments, isDelta); } } if (data.has("devicestatus")) { @@ -634,12 +634,12 @@ public class NSClientService extends Service { } // Was that sgv more less 15 mins ago ? boolean lessThan15MinAgo = false; - if((System.currentTimeMillis()-latestDateInReceivedData)/(60 * 1000L) < 15L ) + if ((System.currentTimeMillis() - latestDateInReceivedData) / (60 * 1000L) < 15L) lessThan15MinAgo = true; - if(Notification.isAlarmForStaleData() && lessThan15MinAgo){ + if (Notification.isAlarmForStaleData() && lessThan15MinAgo) { MainApp.bus().post(new EventDismissNotification(Notification.NSALARM)); - } - BroadcastSgvs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta); + } + BroadcastSgvs.handleNewSgv(sgvs, MainApp.instance().getApplicationContext(), isDelta); } MainApp.bus().post(new EventNSClientNewLog("LAST", DateUtil.dateAndTimeString(latestDateInReceivedData))); } catch (JSONException e) { @@ -757,7 +757,7 @@ public class NSClientService extends Service { public void run() { if (mSocket == null || !mSocket.connected()) return; - if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) { + if (lastResendTime > System.currentTimeMillis() - 10 * 1000L) { log.debug("Skipping resend by lastResendTime: " + ((System.currentTimeMillis() - lastResendTime) / 1000L) + " sec"); return; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java index ddb27c2148..d3fedfd9c8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java @@ -120,19 +120,17 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { profile = new ProfileStore(newProfile.getData()); storeNSProfile(); MainApp.bus().post(new EventNSProfileUpdateGUI()); - if (SP.getBoolean(R.string.key_sync_profile_to_pump, false)) { - ConfigBuilderPlugin.getCommandQueue().setProfile(MainApp.getConfigBuilder().getProfile(), new Callback() { - @Override - public void run() { - if (result.enacted) { - SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); - if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { - smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); - } + ConfigBuilderPlugin.getCommandQueue().setProfile(MainApp.getConfigBuilder().getProfile(), new Callback() { + @Override + public void run() { + if (result.enacted) { + SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); + if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { + smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); } } - }); - } + } + }); } private static void storeNSProfile() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java index c38d7d7827..3df159b876 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java @@ -242,6 +242,8 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public synchronized PumpEnactResult setNewBasalProfile(Profile profile) { if (!isInitialized()) { + // note that this should not happen anymore since the queue is present, which + // issues a READSTATE when starting to issue commands which initializes the pump log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); @@ -283,9 +285,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public boolean isThisProfileSet(Profile profile) { if (!isInitialized()) { - // This is called too soon (for the Combo) on startup, so ignore this. - // The Combo init (refreshDataFromPump) will read the profile and update the pump's - // profile if the pref is set; + /* This might be called too soon during boot. Return true to prevent a request + to update the profile. KeepAlive is called every Constants.keepalivems + and will detect the need for a profile update and apply it. + */ return true; } return pump.basalProfile.equals(convertProfileToComboProfile(profile)); @@ -353,11 +356,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf return; } pump.basalProfile = readBasalResult.basalProfile; - - Profile profile = MainApp.getConfigBuilder().getProfile(); - if (!pump.basalProfile.equals(convertProfileToComboProfile(profile))) { - setNewBasalProfile(profile); - } } if (!pump.initialized) { @@ -801,6 +799,8 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } private void checkForUnsafeUsage(CommandResult commandResult) { + if (commandResult == null) return; + long lastViolation = 0; if (commandResult.state.unsafeUsageDetected) { lastViolation = System.currentTimeMillis(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java index 8e973903f9..2a113b3c8d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/activities/BLEScanActivity.java @@ -7,8 +7,10 @@ import android.bluetooth.le.BluetoothLeScanner; import android.bluetooth.le.ScanCallback; import android.bluetooth.le.ScanResult; import android.content.Context; +import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; +import android.support.v7.app.AlertDialog; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.ViewGroup; @@ -31,7 +33,6 @@ import info.nightscout.utils.SP; public class BLEScanActivity extends AppCompatActivity { private static Logger log = LoggerFactory.getLogger(BLEScanActivity.class); - private Context mContext = null; private ListView listView = null; private ListAdapter mListAdapter = null; @@ -53,26 +54,20 @@ public class BLEScanActivity extends AppCompatActivity { listView.setEmptyView(findViewById(R.id.danars_blescanner_nodevice)); listView.setAdapter(mListAdapter); - initView(); - } - - private void initView() { - mContext = getApplicationContext(); - - BluetoothManager bluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); - mBluetoothAdapter = bluetoothManager.getAdapter(); - mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); - - // MIKE: test mBluetoothLeScanner for null (bt disabled) - mListAdapter.notifyDataSetChanged(); - } @Override protected void onResume() { super.onResume(); + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); + + if (mBluetoothLeScanner == null) { + mBluetoothAdapter.enable(); + mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner(); + } startScan(); } @@ -138,7 +133,7 @@ public class BLEScanActivity extends AppCompatActivity { ViewHolder holder; if (v == null) { - v = View.inflate(mContext, R.layout.danars_blescanner_item, null); + v = View.inflate(getApplicationContext(), R.layout.danars_blescanner_item, null); holder = new ViewHolder(v); v.setTag(holder); } else { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/BGSourceFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/BGSourceFragment.java new file mode 100644 index 0000000000..bd686ec96c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/BGSourceFragment.java @@ -0,0 +1,172 @@ +package info.nightscout.androidaps.plugins.SourceDexcomG5; + +import android.app.Activity; +import android.content.DialogInterface; +import android.graphics.Paint; +import android.os.Bundle; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import com.crashlytics.android.Crashlytics; +import com.squareup.otto.Subscribe; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.db.BgReading; +import info.nightscout.androidaps.events.EventNewBG; +import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; +import info.nightscout.utils.DateUtil; +import info.nightscout.utils.NSUpload; + +/** + * Created by mike on 16.10.2017. + */ + +public class BGSourceFragment extends SubscriberFragment { + private static Logger log = LoggerFactory.getLogger(BGSourceFragment.class); + + RecyclerView recyclerView; + + Profile profile; + + final long MILLS_TO_THE_PAST = 12 * 60 * 60 * 1000L; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + try { + View view = inflater.inflate(R.layout.bgsource_fragment, container, false); + + recyclerView = (RecyclerView) view.findViewById(R.id.bgsource_recyclerview); + recyclerView.setHasFixedSize(true); + LinearLayoutManager llm = new LinearLayoutManager(view.getContext()); + recyclerView.setLayoutManager(llm); + + long now = System.currentTimeMillis(); + RecyclerViewAdapter adapter = new RecyclerViewAdapter(MainApp.getDbHelper().getAllBgreadingsDataFromTime(now - MILLS_TO_THE_PAST, false)); + recyclerView.setAdapter(adapter); + + profile = ConfigBuilderPlugin.getActiveProfileInterface().getProfile().getDefaultProfile(); + + return view; + } catch (Exception e) { + Crashlytics.logException(e); + } + + return null; + } + + @Subscribe + @SuppressWarnings("unused") + public void onStatusEvent(final EventNewBG ev) { + updateGUI(); + } + + @Override + protected void updateGUI() { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + long now = System.currentTimeMillis(); + recyclerView.swapAdapter(new BGSourceFragment.RecyclerViewAdapter(MainApp.getDbHelper().getAllBgreadingsDataFromTime(now - MILLS_TO_THE_PAST, false)), true); + } + }); + } + + public class RecyclerViewAdapter extends RecyclerView.Adapter { + + List bgReadings; + + RecyclerViewAdapter(List bgReadings) { + this.bgReadings = bgReadings; + } + + @Override + public BgReadingsViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.bgsource_item, viewGroup, false); + return new BgReadingsViewHolder(v); + } + + @Override + public void onBindViewHolder(BgReadingsViewHolder holder, int position) { + BgReading bgReading = bgReadings.get(position); + holder.ns.setVisibility(NSUpload.isIdValid(bgReading._id) ? View.VISIBLE : View.GONE); + holder.invalid.setVisibility(!bgReading.isValid ? View.VISIBLE : View.GONE); + holder.date.setText(DateUtil.dateAndTimeString(bgReading.date)); + holder.value.setText(bgReading.valueToUnitsToString(profile.getUnits())); + holder.direction.setText(bgReading.directionToSymbol()); + holder.remove.setTag(bgReading); + } + + @Override + public int getItemCount() { + return bgReadings.size(); + } + + class BgReadingsViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView date; + TextView value; + TextView direction; + TextView invalid; + TextView ns; + TextView remove; + + BgReadingsViewHolder(View itemView) { + super(itemView); + date = (TextView) itemView.findViewById(R.id.bgsource_date); + value = (TextView) itemView.findViewById(R.id.bgsource_value); + direction = (TextView) itemView.findViewById(R.id.bgsource_direction); + invalid = (TextView) itemView.findViewById(R.id.invalid_sign); + ns = (TextView) itemView.findViewById(R.id.ns_sign); + remove = (TextView) itemView.findViewById(R.id.bgsource_remove); + remove.setOnClickListener(this); + remove.setPaintFlags(remove.getPaintFlags() | Paint.UNDERLINE_TEXT_FLAG); + } + + @Override + public void onClick(View v) { + final BgReading bgReading = (BgReading) v.getTag(); + switch (v.getId()) { + + case R.id.bgsource_remove: + AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); + builder.setTitle(MainApp.sResources.getString(R.string.confirmation)); + builder.setMessage(MainApp.sResources.getString(R.string.removerecord) + "\n" + DateUtil.dateAndTimeString(bgReading.date) + "\n" + bgReading.valueToUnitsToString(profile.getUnits())); + builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int id) { + final String _id = bgReading._id; + if (NSUpload.isIdValid(_id)) { + NSUpload.removeFoodFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); + } + bgReading.isValid = false; + MainApp.getDbHelper().update(bgReading); + updateGUI(); + } + }); + builder.setNegativeButton(MainApp.sResources.getString(R.string.cancel), null); + builder.show(); + break; + + } + } + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java index 56934d0081..04f5700dae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceDexcomG5/SourceDexcomG5Plugin.java @@ -12,6 +12,7 @@ import info.nightscout.androidaps.interfaces.PluginBase; public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface { private boolean fragmentEnabled = false; + private boolean fragmentVisible = false; private static SourceDexcomG5Plugin plugin = null; @@ -23,7 +24,7 @@ public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface { @Override public String getFragmentClass() { - return null; + return BGSourceFragment.class.getName(); } @Override @@ -49,7 +50,7 @@ public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface { @Override public boolean isVisibleInTabs(int type) { - return false; + return Config.G5UPLOADER || type == BGSOURCE && fragmentVisible; } @Override @@ -59,7 +60,7 @@ public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface { @Override public boolean hasFragment() { - return false; + return true; } @Override @@ -74,7 +75,7 @@ public class SourceDexcomG5Plugin implements PluginBase, BgSourceInterface { @Override public void setFragmentVisible(int type, boolean fragmentVisible) { - + if (type == BGSOURCE) this.fragmentVisible = fragmentVisible; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java index 934635f03b..51fd755b07 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceGlimp/SourceGlimpPlugin.java @@ -4,12 +4,14 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.SourceDexcomG5.BGSourceFragment; /** * Created by mike on 05.08.2016. */ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { private boolean fragmentEnabled = false; + private boolean fragmentVisible = false; private static SourceGlimpPlugin plugin = null; @@ -21,7 +23,7 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { @Override public String getFragmentClass() { - return null; + return BGSourceFragment.class.getName(); } @Override @@ -47,7 +49,7 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { @Override public boolean isVisibleInTabs(int type) { - return false; + return type == BGSOURCE && fragmentVisible; } @Override @@ -57,7 +59,7 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { @Override public boolean hasFragment() { - return false; + return true; } @Override @@ -72,7 +74,7 @@ public class SourceGlimpPlugin implements PluginBase, BgSourceInterface { @Override public void setFragmentVisible(int type, boolean fragmentVisible) { - + if (type == BGSOURCE) this.fragmentVisible = fragmentVisible; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java index aba07ffe05..e530dd563b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceMM640g/SourceMM640gPlugin.java @@ -4,12 +4,14 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.SourceDexcomG5.BGSourceFragment; /** * Created by mike on 05.08.2016. */ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { private boolean fragmentEnabled = false; + private boolean fragmentVisible = false; private static SourceMM640gPlugin plugin = null; @@ -21,7 +23,7 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { @Override public String getFragmentClass() { - return null; + return BGSourceFragment.class.getName(); } @Override @@ -47,7 +49,7 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { @Override public boolean isVisibleInTabs(int type) { - return false; + return type == BGSOURCE && fragmentVisible; } @Override @@ -57,7 +59,7 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { @Override public boolean hasFragment() { - return false; + return true; } @Override @@ -72,7 +74,7 @@ public class SourceMM640gPlugin implements PluginBase, BgSourceInterface { @Override public void setFragmentVisible(int type, boolean fragmentVisible) { - + if (type == BGSOURCE) this.fragmentVisible = fragmentVisible; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java index 0e85793850..1928448f0e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceNSClient/SourceNSClientPlugin.java @@ -5,12 +5,14 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.SourceDexcomG5.BGSourceFragment; /** * Created by mike on 05.08.2016. */ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { private boolean fragmentEnabled = true; + private boolean fragmentVisible = false; private static SourceNSClientPlugin plugin = null; @@ -22,7 +24,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public String getFragmentClass() { - return null; + return BGSourceFragment.class.getName(); } @Override @@ -32,7 +34,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public String getName() { - return MainApp.instance().getString(R.string.nsclient); + return MainApp.instance().getString(R.string.nsclientbg); } @Override @@ -49,7 +51,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public boolean isVisibleInTabs(int type) { - return false; + return type == BGSOURCE && fragmentVisible; } @Override @@ -59,7 +61,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public boolean hasFragment() { - return false; + return true; } @Override @@ -74,7 +76,7 @@ public class SourceNSClientPlugin implements PluginBase, BgSourceInterface { @Override public void setFragmentVisible(int type, boolean fragmentVisible) { - + if (type == BGSOURCE) this.fragmentVisible = fragmentVisible; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java index 8363f13566..7f73d457e7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SourceXdrip/SourceXdripPlugin.java @@ -4,12 +4,16 @@ import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.BgSourceInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.plugins.SourceDexcomG5.BGSourceFragment; /** * Created by mike on 05.08.2016. */ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { + private boolean fragmentEnabled = false; + private boolean fragmentVisible = false; + private static SourceXdripPlugin plugin = null; public static SourceXdripPlugin getPlugin() { @@ -20,11 +24,9 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { @Override public String getFragmentClass() { - return null; + return BGSourceFragment.class.getName(); } - private boolean fragmentEnabled = false; - @Override public int getType() { return PluginBase.BGSOURCE; @@ -48,7 +50,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { @Override public boolean isVisibleInTabs(int type) { - return false; + return type == BGSOURCE && fragmentVisible; } @Override @@ -58,7 +60,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { @Override public boolean hasFragment() { - return false; + return true; } @Override @@ -73,6 +75,7 @@ public class SourceXdripPlugin implements PluginBase, BgSourceInterface { @Override public void setFragmentVisible(int type, boolean fragmentVisible) { + if (type == BGSOURCE) this.fragmentVisible = fragmentVisible; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java index efe3f200aa..d096fd8549 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsBolusFragment.java @@ -36,6 +36,7 @@ import info.nightscout.androidaps.db.Treatment; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTreatmentChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.androidaps.plugins.Treatments.TreatmentsPlugin; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; @@ -82,7 +83,7 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. holder.activity.setText(DecimalFormatter.to3Decimal(iob.activityContrib) + " U"); holder.mealOrCorrection.setText(t.mealBolus ? MainApp.sResources.getString(R.string.mealbolus) : MainApp.sResources.getString(R.string.correctionbous)); holder.ph.setVisibility(t.source == Source.PUMP ? View.VISIBLE : View.GONE); - holder.ns.setVisibility(t._id != null ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(NSUpload.isIdValid(t._id) ? View.VISIBLE : View.GONE); holder.invalid.setVisibility(t.isValid ? View.GONE : View.VISIBLE); if (iob.iobContrib != 0) holder.iob.setTextColor(ContextCompat.getColor(MainApp.instance(), R.color.colorActive)); @@ -146,8 +147,10 @@ public class TreatmentsBolusFragment extends SubscriberFragment implements View. treatment.isValid = false; MainApp.getDbHelper().update(treatment); } else { - if (_id != null && !_id.equals("")) { + if (NSUpload.isIdValid(_id)) { NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(treatment); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java index eb3bd49d89..4e21259dae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsExtendedBolusesFragment.java @@ -31,6 +31,7 @@ import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventExtendedBolusChange; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; @@ -63,7 +64,7 @@ public class TreatmentsExtendedBolusesFragment extends SubscriberFragment { public void onBindViewHolder(ExtendedBolusesViewHolder holder, int position) { ExtendedBolus extendedBolus = extendedBolusList.getReversed(position); holder.ph.setVisibility(extendedBolus.source == Source.PUMP ? View.VISIBLE : View.GONE); - holder.ns.setVisibility(extendedBolus._id != null ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(NSUpload.isIdValid(extendedBolus._id) ? View.VISIBLE : View.GONE); if (extendedBolus.isEndingEvent()) { holder.date.setText(DateUtil.dateAndTimeString(extendedBolus.date)); holder.duration.setText(MainApp.sResources.getString(R.string.cancel)); @@ -148,8 +149,10 @@ public class TreatmentsExtendedBolusesFragment extends SubscriberFragment { builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { final String _id = extendedBolus._id; - if (_id != null && !_id.equals("")) { + if (NSUpload.isIdValid(_id)) { NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(extendedBolus); Answers.getInstance().logCustom(new CustomEvent("RemoveExtendedBolus")); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java index e5655cdb18..591a8a6964 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsProfileSwitchFragment.java @@ -29,6 +29,7 @@ import info.nightscout.androidaps.db.ProfileSwitch; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.events.EventProfileSwitchChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; @@ -66,7 +67,7 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen if (profile == null) return; ProfileSwitch profileSwitch = profileSwitchList.getReversed(position); holder.ph.setVisibility(profileSwitch.source == Source.PUMP ? View.VISIBLE : View.GONE); - holder.ns.setVisibility(profileSwitch._id != null ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(NSUpload.isIdValid(profileSwitch._id) ? View.VISIBLE : View.GONE); holder.date.setText(DateUtil.dateAndTimeString(profileSwitch.date)); if (!profileSwitch.isEndingEvent()) { @@ -131,8 +132,10 @@ public class TreatmentsProfileSwitchFragment extends SubscriberFragment implemen builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { final String _id = profileSwitch._id; - if (_id != null && !_id.equals("")) { + if (NSUpload.isIdValid(_id)) { NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(profileSwitch); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java index 9e3836e118..61b6c05199 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTempTargetFragment.java @@ -27,6 +27,7 @@ import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TempTarget; import info.nightscout.androidaps.events.EventTempTargetChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; @@ -67,7 +68,7 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements String units = MainApp.getConfigBuilder().getProfileUnits(); TempTarget tempTarget = tempTargetList.getReversed(position); holder.ph.setVisibility(tempTarget.source == Source.PUMP ? View.VISIBLE : View.GONE); - holder.ns.setVisibility(tempTarget._id != null ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(NSUpload.isIdValid(tempTarget._id) ? View.VISIBLE : View.GONE); if (!tempTarget.isEndingEvent()) { holder.date.setText(DateUtil.dateAndTimeString(tempTarget.date) + " - " + DateUtil.timeString(tempTarget.originalEnd())); holder.duration.setText(DecimalFormatter.to0Decimal(tempTarget.durationInMinutes) + " min"); @@ -149,8 +150,10 @@ public class TreatmentsTempTargetFragment extends SubscriberFragment implements builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { final String _id = tempTarget._id; - if (_id != null && !_id.equals("")) { + if (NSUpload.isIdValid(_id)) { NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(tempTarget); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java index 9127bf1e7a..bd6269e871 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/fragments/TreatmentsTemporaryBasalsFragment.java @@ -31,6 +31,7 @@ import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventNewBG; import info.nightscout.androidaps.events.EventTempBasalChange; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.NSClientInternal.UploadQueue; import info.nightscout.utils.DateUtil; import info.nightscout.utils.DecimalFormatter; import info.nightscout.utils.NSUpload; @@ -65,7 +66,7 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { public void onBindViewHolder(TempBasalsViewHolder holder, int position) { TemporaryBasal tempBasal = tempBasalList.getReversed(position); holder.ph.setVisibility(tempBasal.source == Source.PUMP ? View.VISIBLE : View.GONE); - holder.ns.setVisibility(tempBasal._id != null ? View.VISIBLE : View.GONE); + holder.ns.setVisibility(NSUpload.isIdValid(tempBasal._id) ? View.VISIBLE : View.GONE); if (tempBasal.isEndingEvent()) { holder.date.setText(DateUtil.dateAndTimeString(tempBasal.date)); holder.duration.setText(MainApp.sResources.getString(R.string.cancel)); @@ -165,8 +166,10 @@ public class TreatmentsTemporaryBasalsFragment extends SubscriberFragment { builder.setPositiveButton(MainApp.sResources.getString(R.string.ok), new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { final String _id = tempBasal._id; - if (_id != null && !_id.equals("")) { + if (NSUpload.isIdValid(_id)) { NSUpload.removeCareportalEntryFromNS(_id); + } else { + UploadQueue.removeID("dbAdd", _id); } MainApp.getDbHelper().delete(tempBasal); Answers.getInstance().logCustom(new CustomEvent("RemoveTempBasal")); diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java index e752c28b2a..e89af3a7db 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -28,6 +28,7 @@ public class QueueThread extends Thread { private CommandQueue queue; + private long lastCommandTime = 0; private boolean connectLogged = false; private PowerManager.WakeLock mWakeLock; @@ -44,7 +45,7 @@ public class QueueThread extends Thread { public final void run() { mWakeLock.acquire(); MainApp.bus().post(new EventQueueChanged()); - long connectionStartTime = System.currentTimeMillis(); + long connectionStartTime = lastCommandTime = System.currentTimeMillis(); try { while (true) { @@ -106,17 +107,24 @@ public class QueueThread extends Thread { queue.performing().execute(); queue.resetPerforming(); MainApp.bus().post(new EventQueueChanged()); + lastCommandTime = System.currentTimeMillis(); SystemClock.sleep(100); continue; } } if (queue.size() == 0 && queue.performing() == null) { - log.debug("QUEUE: queue empty. disconnect"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); - pump.disconnect("Queue empty"); - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); - return; + long secondsFromLastCommand = (System.currentTimeMillis() - lastCommandTime) / 1000; + if (secondsFromLastCommand >= 5) { + log.debug("QUEUE: queue empty. disconnect"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTING)); + pump.disconnect("Queue empty"); + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); + return; + } else { + log.debug("QUEUE: waiting for disconnect"); + SystemClock.sleep(1000); + } } } } finally { diff --git a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java index 6ce75e3720..3d3258c614 100644 --- a/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/receivers/KeepAliveReceiver.java @@ -22,6 +22,7 @@ import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.utils.LocalAlertUtils; +import info.nightscout.utils.SP; public class KeepAliveReceiver extends BroadcastReceiver { private static Logger log = LoggerFactory.getLogger(KeepAliveReceiver.class); diff --git a/app/src/main/java/info/nightscout/utils/NSUpload.java b/app/src/main/java/info/nightscout/utils/NSUpload.java index f115358703..cee8e6e9b5 100644 --- a/app/src/main/java/info/nightscout/utils/NSUpload.java +++ b/app/src/main/java/info/nightscout/utils/NSUpload.java @@ -493,4 +493,11 @@ public class NSUpload { } + public static boolean isIdValid(String _id) { + if (_id == null) + return false; + if (_id.length() == 24) + return true; + return false; + } } diff --git a/app/src/main/res/layout/bgsource_fragment.xml b/app/src/main/res/layout/bgsource_fragment.xml new file mode 100644 index 0000000000..dbd0ea4e67 --- /dev/null +++ b/app/src/main/res/layout/bgsource_fragment.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + diff --git a/app/src/main/res/layout/bgsource_item.xml b/app/src/main/res/layout/bgsource_item.xml new file mode 100644 index 0000000000..acd0454327 --- /dev/null +++ b/app/src/main/res/layout/bgsource_item.xml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a25ef122b7..aaa4c2cb17 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -790,6 +790,7 @@ Send BG data to xDrip+ dexcomg5_xdripupload In xDrip+ select 640g/Eversense data source + NSClient BG Stopping bolus delivery Bolus delivery stopped Programming pump for bolusing diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 73258f931c..44deb879e8 100644 --- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -187,10 +187,10 @@ public class RuffyScripter implements RuffyCommands { if (!ruffyService.isConnected()) { return false; } - if (System.currentTimeMillis() - menuLastUpdated >= 500) { + if (System.currentTimeMillis() - menuLastUpdated >= 1500) { waitForScreenUpdate(); } - return System.currentTimeMillis() - menuLastUpdated < 500; + return System.currentTimeMillis() - menuLastUpdated < 1500; } catch (RemoteException e) { return false; } @@ -241,7 +241,7 @@ public class RuffyScripter implements RuffyCommands { List violations = cmd.validateArguments(); if (!violations.isEmpty()) { log.error("Command argument violations: " + Joiner.on(", ").join(violations)); - return new CommandResult().success(false).state(readPumpStateInternal()); + return new CommandResult().success(false).state(new PumpState()); } synchronized (RuffyScripter.class) { @@ -282,7 +282,9 @@ public class RuffyScripter implements RuffyCommands { // on connection loss try to reconnect, confirm warning alerts caused by // the disconnected and then return the command as failed (the caller // can retry if needed). - log.debug("Connection unusable, aborting command and attempting reconnect ..."); + log.debug("Connection unusable (ruffy connection: " + ruffyService.isConnected() + ", " + + "time since last menu update: " + (System.currentTimeMillis() - menuLastUpdated) + " ms, " + + "aborting command and attempting reconnect ..."); cmdThread.interrupt(); activeCmd.getResult().success = false; @@ -324,12 +326,12 @@ public class RuffyScripter implements RuffyCommands { return result; } catch (CommandException e) { log.error("CommandException while executing command", e); - recoverFromCommandFailure(); - return activeCmd.getResult().success(false).state(readPumpStateInternal()); + PumpState pumpState = recoverFromCommandFailure(); + return activeCmd.getResult().success(false).state(pumpState); } catch (Exception e) { log.error("Unexpected exception communication with ruffy", e); - recoverFromCommandFailure(); - return activeCmd.getResult().success(false).state(readPumpStateInternal()); + PumpState pumpState = recoverFromCommandFailure(); + return activeCmd.getResult().success(false).state(pumpState); } finally { Menu menu = this.currentMenu; if (activeCmd.getResult().success && menu != null && menu.getType() != MenuType.MAIN_MENU) { @@ -416,12 +418,12 @@ public class RuffyScripter implements RuffyCommands { /** * Returns to the main menu (if possible) after a command failure, so that subsequent commands - * reusing the connection won't fail. + * reusing the connection won't fail and returns the current PumpState (empty if unreadable). */ - private void recoverFromCommandFailure() { + private PumpState recoverFromCommandFailure() { Menu menu = this.currentMenu; if (menu == null) { - return; + return new PumpState(); } MenuType type = menu.getType(); if (type != MenuType.WARNING_OR_ERROR && type != MenuType.MAIN_MENU) { @@ -432,6 +434,12 @@ public class RuffyScripter implements RuffyCommands { log.warn("Error returning to main menu, when trying to recover from command failure", e); } } + try { + return readPumpStateInternal(); + } catch (Exception e) { + log.debug("Reading pump state during recovery failed", e); + return new PumpState(); + } } /** @@ -480,6 +488,7 @@ public class RuffyScripter implements RuffyCommands { state.timestamp = System.currentTimeMillis(); Menu menu = currentMenu; if (menu == null) { + log.debug("Returning empty PumpState, menu is unavailable"); return state; }