From 89b7b9c24aaa9884edcb414f8c59be874023ea9c Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 14 Jan 2018 17:11:39 +0100 Subject: [PATCH 1/8] better log build verison to Fabric --- app/build.gradle | 5 +++++ .../main/java/info/nightscout/androidaps/Config.java | 1 + .../main/java/info/nightscout/androidaps/MainApp.java | 10 ++++++++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index e37c577e97..e27e82d15d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -91,6 +91,7 @@ android { buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "CLOSEDLOOP", "true" buildConfigField "boolean", "G5UPLOADER", "false" + buildConfigField "boolean", "PUMPCONTROL", "false" } openloop { dimension "standard" @@ -104,6 +105,7 @@ android { buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "false" + buildConfigField "boolean", "PUMPCONTROL", "false" } pumpcontrol { dimension "standard" @@ -117,6 +119,7 @@ android { buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "false" + buildConfigField "boolean", "PUMPCONTROL", "true" } nsclient { dimension "standard" @@ -130,6 +133,7 @@ android { buildConfigField "boolean", "NSCLIENTOLNY", "true" buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "false" + buildConfigField "boolean", "PUMPCONTROL", "false" } g5uploader { dimension "standard" @@ -143,6 +147,7 @@ android { buildConfigField "boolean", "NSCLIENTOLNY", "false" buildConfigField "boolean", "CLOSEDLOOP", "false" buildConfigField "boolean", "G5UPLOADER", "true" + buildConfigField "boolean", "PUMPCONTROL", "false" } } } diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 50d3b2e853..3c8d6095ed 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -11,6 +11,7 @@ public class Config { // PLUGINS public static final boolean NSCLIENT = BuildConfig.NSCLIENTOLNY; public static final boolean G5UPLOADER = BuildConfig.G5UPLOADER; + public static final boolean PUMPCONTROL = BuildConfig.PUMPCONTROL; public static final boolean DANAR = BuildConfig.PUMPDRIVERS; diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 4bba16080b..56c712f629 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -165,10 +165,16 @@ public class MainApp extends Application { MainApp.getConfigBuilder().initialize(); } NSUpload.uploadAppStart(); - if (MainApp.getConfigBuilder().isClosedModeEnabled()) + if (Config.NSCLIENT) + Answers.getInstance().logCustom(new CustomEvent("AppStart-NSClient")); + else if (Config.G5UPLOADER) + Answers.getInstance().logCustom(new CustomEvent("AppStart-G5Uploader")); + else if (Config.PUMPCONTROL) + Answers.getInstance().logCustom(new CustomEvent("AppStart-PumpControl")); + else if (MainApp.getConfigBuilder().isClosedModeEnabled()) Answers.getInstance().logCustom(new CustomEvent("AppStart-ClosedLoop")); else - Answers.getInstance().logCustom(new CustomEvent("AppStart")); + Answers.getInstance().logCustom(new CustomEvent("AppStart-OpenLoop")); new Thread(new Runnable() { @Override From 44381288f41629f95e920b2de38812e13d78679c Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 14 Jan 2018 17:12:18 +0100 Subject: [PATCH 2/8] bump 1.57-dev --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index e27e82d15d..6ecea2b3e1 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -56,7 +56,7 @@ android { targetSdkVersion 23 multiDexEnabled true versionCode 1500 - version "1.56-dev" + version "1.57-dev" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", generateGitBuild() From 5a00b68f68b56b92247b0623a78a59b820f20df1 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 14 Jan 2018 21:42:36 +0100 Subject: [PATCH 3/8] remove readstatus prior every command --- .../info/nightscout/androidaps/MainApp.java | 4 + .../nightscout/androidaps/data/Profile.java | 4 +- .../ConfigBuilder/ConfigBuilderPlugin.java | 17 --- .../PumpDanaRS/services/DanaRSService.java | 1 + .../services/DanaRv2ExecutionService.java | 1 + .../androidaps/queue/CommandQueue.java | 84 +++++----- .../androidaps/queue/commands/Command.java | 2 +- .../queue/commands/CommandReadStatus.java | 2 +- .../androidaps/queue/CommandQueueTest.java | 143 ++++++++++++++++++ 9 files changed, 203 insertions(+), 55 deletions(-) create mode 100644 app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 56c712f629..bad0f88d6a 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -229,6 +229,10 @@ public class MainApp extends Application { return sBus; } + public static String gs(int id) { + return sResources.getString(id); + } + public static MainApp instance() { return sInstance; } diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index b2e5d0d9dc..db34f9d692 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -120,7 +120,7 @@ public class Profile { } } catch (JSONException e) { log.error("Unhandled exception", e); - ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.invalidprofile)); + ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.gs(R.string.invalidprofile)); } } @@ -386,6 +386,8 @@ public class Profile { } public BasalValue[] getBasalValues() { + if (basal_v == null) + basal_v = convertToSparseArray(basal); BasalValue[] ret = new BasalValue[basal_v.size()]; for (Integer index = 0; index < basal_v.size(); index++) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index 62848b7e5e..9cbb0bef4c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -421,23 +421,6 @@ public class ConfigBuilderPlugin implements PluginBase, ConstraintsInterface, Tr } -/* - @Override - public PumpDescription getPumpDescription() { - if (activePump != null) - return activePump.getPumpDescription(); - else { - PumpDescription emptyDescription = new PumpDescription(); - emptyDescription.isBolusCapable = false; - emptyDescription.isExtendedBolusCapable = false; - emptyDescription.isSetBasalProfileCapable = false; - emptyDescription.isTempBasalCapable = true; // needs to be true before real driver is selected - emptyDescription.isRefillingCapable = false; - return emptyDescription; - } - } -*/ - /** * Constraints interface **/ diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java index bd6f5ca690..7790257640 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/DanaRSService.java @@ -258,6 +258,7 @@ public class DanaRSService extends Service { MainApp.bus().post(bolusingEvent); SystemClock.sleep(1000); } + // do not call loadEvents() directly, reconnection may be needed ConfigBuilderPlugin.getCommandQueue().loadEvents(new Callback() { @Override public void run() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java index 6d6ba34838..71a2f9ac79 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/services/DanaRv2ExecutionService.java @@ -424,6 +424,7 @@ public class DanaRv2ExecutionService extends Service { MainApp.bus().post(bolusingEvent); SystemClock.sleep(1000); } + // do not call loadEvents() directly, reconnection may be needed ConfigBuilderPlugin.getCommandQueue().loadEvents(new Callback() { @Override public void run() { diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java index 0e7e18ec7e..3e696e9857 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -1,5 +1,6 @@ package info.nightscout.androidaps.queue; +import android.content.Context; import android.content.Intent; import android.support.v7.app.AppCompatActivity; import android.text.Html; @@ -37,42 +38,41 @@ import info.nightscout.androidaps.queue.commands.CommandTempBasalPercent; /** * Created by mike on 08.11.2017. - * + *

* DATA FLOW: * --------- - * + *

* (request) - > ConfigBuilder.getCommandQueue().bolus(...) - * + *

* app no longer waits for result but passes Callback - * + *

* request is added to queue, if another request of the same type already exists in queue, it's removed prior adding * but if request of the same type is currently executed (probably important only for bolus which is running long time), new request is declined * new QueueThread is created and started if current if finished * CommandReadStatus is added automatically before command if queue is empty - * + *

* biggest change is we don't need exec pump commands in Handler because it's finished immediately * command queueing if not realized by stacking in different Handlers and threads anymore but by internal queue with better control - * + *

* QueueThread calls ConfigBuilder#connect which is passed to getActivePump().connect * connect should be executed on background and return immediately. afterwards isConnecting() is expected to be true - * + *

* while isConnecting() == true GUI is updated by posting connection progress - * + *

* if connect is successful: isConnected() becomes true, isConnecting() becomes false - * CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish). - * callback with result is called after finish automatically + * CommandQueue starts calling execute() of commands. execute() is expected to be blocking (return after finish). + * callback with result is called after finish automatically * if connect failed: isConnected() becomes false, isConnecting() becomes false - * connect() is called again - * + * connect() is called again + *

* when queue is empty, disconnect is called - * */ public class CommandQueue { private static Logger log = LoggerFactory.getLogger(CommandQueue.class); private LinkedList queue = new LinkedList<>(); - private Command performing; + protected Command performing; private QueueThread thread = null; @@ -94,10 +94,19 @@ public class CommandQueue { } } + private synchronized boolean isLastScheduled(Command.CommandType type) { + if (queue.size() > 0 && queue.get(queue.size() - 1).commandType == type) { + return true; + } + return false; + } + + private synchronized void inject(Command command) { + // inject as a first command + queue.addFirst(command); + } + private synchronized void add(Command command) { - // inject reading of status when adding first command to the queue - if (queue.size() == 0 && command.commandType != Command.CommandType.READSTATUS) - queue.add(new CommandReadStatus("Queue", null)); queue.add(command); } @@ -128,7 +137,7 @@ public class CommandQueue { // After new command added to the queue // start thread again if not already running - private synchronized void notifyAboutNewCommand() { + protected synchronized void notifyAboutNewCommand() { if (thread == null || thread.getState() == Thread.State.TERMINATED) { thread = new QueueThread(this); thread.start(); @@ -166,17 +175,7 @@ public class CommandQueue { MainApp.bus().post(new EventBolusRequested(detailedBolusInfo.insulin)); // Bring up bolus progress dialog - if (detailedBolusInfo.context != null) { - BolusProgressDialog bolusProgressDialog = new BolusProgressDialog(); - bolusProgressDialog.setInsulin(detailedBolusInfo.insulin); - bolusProgressDialog.show(((AppCompatActivity) detailedBolusInfo.context).getSupportFragmentManager(), "BolusProgress"); - } else { - Intent i = new Intent(); - i.putExtra("insulin", detailedBolusInfo.insulin); - i.setClass(MainApp.instance(), BolusProgressHelperActivity.class); - i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); - MainApp.instance().startActivity(i); - } + showBolusProgressDialog(detailedBolusInfo.insulin, detailedBolusInfo.context); return true; } @@ -231,7 +230,7 @@ public class CommandQueue { return false; } - Double rateAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); + Double rateAfterConstraints = MainApp.getConfigBuilder().applyBolusConstraints(insulin); // remove all unfinished removeAll(Command.CommandType.EXTENDEDBOLUS); @@ -326,11 +325,12 @@ public class CommandQueue { // returns true if command is queued public boolean readStatus(String reason, Callback callback) { - //if (isRunning(Command.CommandType.READSTATUS)) { - // if (callback != null) - // callback.result(executingNowError()).run(); - // return false; - //} + if (isLastScheduled(Command.CommandType.READSTATUS)) { + log.debug("QUEUE: READSTATUS " + reason + " ignored as duplicated"); + if (callback != null) + callback.result(executingNowError()).run(); + return false; + } // remove all unfinished //removeAll(Command.CommandType.READSTATUS); @@ -409,4 +409,18 @@ public class CommandQueue { } else return true; } + protected void showBolusProgressDialog(Double insulin, Context context) { + if (context != null) { + BolusProgressDialog bolusProgressDialog = new BolusProgressDialog(); + bolusProgressDialog.setInsulin(insulin); + bolusProgressDialog.show(((AppCompatActivity) context).getSupportFragmentManager(), "BolusProgress"); + } else { + Intent i = new Intent(); + i.putExtra("insulin", insulin); + i.setClass(MainApp.instance(), BolusProgressHelperActivity.class); + i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + MainApp.instance().startActivity(i); + } + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java index 4624e2385f..5129c7983f 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/Command.java @@ -29,7 +29,7 @@ public abstract class Command { public void cancel() { PumpEnactResult result = new PumpEnactResult(); result.success = false; - result.comment = MainApp.sResources.getString(R.string.connectiontimedout); + result.comment = MainApp.gs(R.string.connectiontimedout); if (callback != null) callback.result(result).run(); } diff --git a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java index 46c524fa29..44c778c5f7 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/queue/commands/CommandReadStatus.java @@ -27,6 +27,6 @@ public class CommandReadStatus extends Command { @Override public String status() { - return "READSTATUS"; + return "READSTATUS " + reason; } } diff --git a/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java new file mode 100644 index 0000000000..31d8636de2 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/queue/CommandQueueTest.java @@ -0,0 +1,143 @@ +package info.nightscout.androidaps.queue; + +import android.content.Context; +import android.text.Html; + +import com.squareup.otto.Bus; +import com.squareup.otto.ThreadEnforcer; + +import junit.framework.Assert; + +import org.json.JSONObject; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.Constants; +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.PumpMDI.MDIPlugin; +import info.nightscout.androidaps.queue.commands.Command; +import info.nightscout.utils.ToastUtils; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +/** + * Created by mike on 14.01.2018. + */ + +@RunWith(PowerMockRunner.class) +@PrepareForTest({MainApp.class, ConfigBuilderPlugin.class, ConfigBuilderPlugin.class, ToastUtils.class, Context.class}) +public class CommandQueueTest extends CommandQueue { + + String profileJson = "{\"dia\":\"3\",\"carbratio\":[{\"time\":\"00:00\",\"value\":\"30\"}],\"carbs_hr\":\"20\",\"delay\":\"20\",\"sens\":[{\"time\":\"00:00\",\"value\":\"100\"}],\"timezone\":\"UTC\",\"basal\":[{\"time\":\"00:00\",\"value\":\"0.1\"}],\"target_low\":[{\"time\":\"00:00\",\"value\":\"4\"}],\"target_high\":[{\"time\":\"00:00\",\"value\":\"5\"}],\"startDate\":\"1970-01-01T00:00:00.000Z\",\"units\":\"mmol\"}"; + + @Test + public void doTests() throws Exception { + prepareMock(0d, 0); + + // start with empty queue + Assert.assertEquals(0, size()); + + // add bolus command + bolus(new DetailedBolusInfo(), null); + Assert.assertEquals(1, size()); + + // add READSTATUS + readStatus("anyString", null); + Assert.assertEquals(2, size()); + + // adding another bolus should remove the first one (size still == 2) + bolus(new DetailedBolusInfo(), null); + Assert.assertEquals(2, size()); + + // clear the queue should reset size + clear(); + Assert.assertEquals(0, size()); + + // add tempbasal + tempBasalAbsolute(0, 30, true, null); + Assert.assertEquals(1, size()); + + // add tempbasal percent. it should replace previous TEMPBASAL + tempBasalPercent(0, 30, true, null); + Assert.assertEquals(1, size()); + + // add extended bolus + extendedBolus(1, 30, null); + Assert.assertEquals(2, size()); + + // add cancel temp basal should remove previous 2 temp basal setting + extendedBolus(1, 30, null); + Assert.assertEquals(2, size()); + + // cancel extended bolus should replace previous extended + extendedBolus(1, 30, null); + Assert.assertEquals(2, size()); + + // add setProfile + setProfile(new Profile(new JSONObject(profileJson), Constants.MGDL), null); + Assert.assertEquals(3, size()); + + // add loadHistory + loadHistory((byte) 0, null); + Assert.assertEquals(4, size()); + + // add loadEvents + loadEvents(null); + Assert.assertEquals(5, size()); + + clear(); + tempBasalAbsolute(0, 30, true, null); + pickup(); + Assert.assertEquals(0, size()); + Assert.assertNotNull(performing); + Assert.assertEquals(Command.CommandType.TEMPBASAL, performing.commandType); + resetPerforming(); + Assert.assertNull(performing); + } + + private void prepareMock(Double insulin, Integer carbs) throws Exception { + ConfigBuilderPlugin configBuilderPlugin = mock(ConfigBuilderPlugin.class); + when(configBuilderPlugin.applyBolusConstraints(insulin)).thenReturn(insulin); + when(configBuilderPlugin.applyCarbsConstraints(carbs)).thenReturn(carbs); + + PowerMockito.mockStatic(ConfigBuilderPlugin.class); + PumpInterface pump = MDIPlugin.getPlugin(); + when(ConfigBuilderPlugin.getActivePump()).thenReturn(pump); + + PowerMockito.mockStatic(MainApp.class); + MainApp mainApp = mock(MainApp.class); + when(MainApp.getConfigBuilder()).thenReturn(configBuilderPlugin); + when(MainApp.instance()).thenReturn(mainApp); + + PowerMockito.mockStatic(ToastUtils.class); + Context context = mock(Context.class); + String message = null; + PowerMockito.doNothing().when(ToastUtils.class, "showToastInUiThread", context, message); + + Bus bus = new Bus(ThreadEnforcer.ANY); + + when(MainApp.bus()).thenReturn(bus); + when(MainApp.gs(0)).thenReturn(""); + } + + @Override + protected synchronized void notifyAboutNewCommand() { + } + + @Override + protected void showBolusProgressDialog(Double insulin, Context context) { + } + + @Override + public boolean isThisProfileSet(Profile profile) { + return false; + } +} From 7fdc146b916141eab632d8b23deda3f532210000 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 16 Jan 2018 19:28:25 +0100 Subject: [PATCH 4/8] getLastAutosensData improvement and logging --- .../androidaps/data/QuickWizardEntry.java | 9 ++++-- .../IobCobCalculatorPlugin.java | 30 ++++++++++++++++--- .../Overview/Dialogs/WizardDialog.java | 15 +++++++++- .../plugins/Overview/OverviewFragment.java | 6 ++-- .../SensitivityAAPSPlugin.java | 2 +- .../SensitivityOref0Plugin.java | 2 +- .../SensitivityWeightedAveragePlugin.java | 2 +- .../plugins/Treatments/TreatmentsPlugin.java | 2 +- .../wearintegration/WatchUpdaterService.java | 2 +- 9 files changed, 55 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java index 08d1a7295a..35a7265f2a 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java +++ b/app/src/main/java/info/nightscout/androidaps/data/QuickWizardEntry.java @@ -69,7 +69,7 @@ public class QuickWizardEntry { return Profile.secondsFromMidnight() >= validFrom() && Profile.secondsFromMidnight() <= validTo(); } - public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG) { + public BolusWizard doCalc(Profile profile, TempTarget tempTarget, BgReading lastBG, boolean _synchronized) { BolusWizard wizard = new BolusWizard(); //BG @@ -80,7 +80,12 @@ public class QuickWizardEntry { // COB double cob = 0d; - AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData(); + AutosensData autosensData; + if (_synchronized) + autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("QuickWizard COB"); + else + autosensData = IobCobCalculatorPlugin.getLastAutosensData("QuickWizard COB"); + if (autosensData != null && useCOB() == YES) { cob = autosensData.cob; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java index a0a6ebc581..fbbbe43ccc 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/IobCobCalculator/IobCobCalculatorPlugin.java @@ -547,7 +547,7 @@ public class IobCobCalculatorPlugin implements PluginBase { } else { if (time > now) { // data may not be calculated yet, use last data - return getLastAutosensData(); + return getLastAutosensData("getAutosensData"); } //log.debug(">>> getAutosensData Cache miss " + new Date(time).toLocaleString()); return null; @@ -556,13 +556,35 @@ public class IobCobCalculatorPlugin implements PluginBase { } @Nullable - public static AutosensData getLastAutosensData() { - if (autosensDataTable.size() < 1) + public static AutosensData getLastAutosensDataSynchronized(String reason) { + synchronized (dataLock) { + return getLastAutosensData(reason); + } + } + + + @Nullable + public static AutosensData getLastAutosensData(String reason) { + if (autosensDataTable.size() < 1) { + log.debug("AUTOSENSDATA null: autosensDataTable empty (" + reason + ")"); return null; - AutosensData data = autosensDataTable.valueAt(autosensDataTable.size() - 1); + } + AutosensData data = null; + try { + data = autosensDataTable.valueAt(autosensDataTable.size() - 1); + } catch (Exception e) { + // data can be processed on the background + // in this rare case better return null and do not block UI + // APS plugin should use getLastAutosensDataSynchronized where the blocking is not an issue + log.debug("AUTOSENSDATA null: Exception catched (" + reason + ")"); + return null; + } if (data.time < System.currentTimeMillis() - 11 * 60 * 1000) { + log.debug("AUTOSENSDATA null: data is old (" + reason + ")"); return null; } else { + if (data == null) + log.debug("AUTOSENSDATA null: data == null (" + " " + reason + ")"); return data; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java index c8a00053b2..fd720e9499 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/Dialogs/WizardDialog.java @@ -55,6 +55,7 @@ import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.IobCobCalculator.AutosensData; import info.nightscout.androidaps.plugins.IobCobCalculator.IobCobCalculatorPlugin; +import info.nightscout.androidaps.plugins.IobCobCalculator.events.EventAutosensCalculationFinished; import info.nightscout.androidaps.plugins.Loop.LoopPlugin; import info.nightscout.androidaps.plugins.OpenAPSAMA.OpenAPSAMAPlugin; import info.nightscout.androidaps.plugins.OpenAPSMA.events.EventOpenAPSUpdateGui; @@ -151,6 +152,18 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com }); } + @Subscribe + public void onStatusEvent(final EventAutosensCalculationFinished e) { + Activity activity = getActivity(); + if (activity != null) + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + calculateInsulin(); + } + }); + } + final private TextWatcher textWatcher = new TextWatcher() { @Override public void afterTextChanged(Editable s) { @@ -459,7 +472,7 @@ public class WizardDialog extends DialogFragment implements OnClickListener, Com // COB Double c_cob = 0d; if (cobCheckbox.isChecked()) { - AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData(); + AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Wizard COB"); if(autosensData != null) { c_cob = autosensData.cob; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java index d18db85880..3228b16198 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Overview/OverviewFragment.java @@ -640,7 +640,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, final QuickWizardEntry quickWizardEntry = OverviewPlugin.getPlugin().quickWizard.getActive(); if (quickWizardEntry != null && actualBg != null) { quickWizardButton.setVisibility(View.VISIBLE); - final BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, actualBg); + final BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, actualBg, true); final JSONObject boluscalcJSON = new JSONObject(); try { @@ -1135,7 +1135,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, if (quickWizardEntry != null && lastBG != null && pump.isInitialized() && !pump.isSuspended()) { quickWizardButton.setVisibility(View.VISIBLE); String text = quickWizardEntry.buttonText() + "\n" + DecimalFormatter.to0Decimal(quickWizardEntry.carbs()) + "g"; - BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, lastBG); + BolusWizard wizard = quickWizardEntry.doCalc(profile, tempTarget, lastBG, false); text += " " + DecimalFormatter.to2Decimal(wizard.calculatedTotalInsulin) + "U"; quickWizardButton.setText(text); if (wizard.calculatedTotalInsulin <= 0) @@ -1201,7 +1201,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, // cob if (cobView != null) { // view must not exists String cobText = ""; - AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData(); + AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("Overview COB"); if (autosensData != null) cobText = (int) autosensData.cob + " g"; cobView.setText(cobText); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java index 39af16e0ee..f02cdd9371 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityAAPS/SensitivityAAPSPlugin.java @@ -118,7 +118,7 @@ public class SensitivityAAPSPlugin implements PluginBase, SensitivityInterface{ return new AutosensResult(); } - AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); + AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already if (current == null) { log.debug("No autosens data available"); return new AutosensResult(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java index 6817e17503..9aedf22d44 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityOref0/SensitivityOref0Plugin.java @@ -118,7 +118,7 @@ public class SensitivityOref0Plugin implements PluginBase, SensitivityInterface return new AutosensResult(); } - AutosensData current = IobCobCalculatorPlugin.getLastAutosensData(); + AutosensData current = IobCobCalculatorPlugin.getLastAutosensData("SensitivityOref0"); // this is running inside lock already if (current == null) { log.debug("No current autosens data available"); return new AutosensResult(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java index 596c2477f5..046cd056fa 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/SensitivityWeightedAverage/SensitivityWeightedAveragePlugin.java @@ -116,7 +116,7 @@ public class SensitivityWeightedAveragePlugin implements PluginBase, Sensitivity return new AutosensResult(); } - AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); + AutosensData current = IobCobCalculatorPlugin.getAutosensData(toTime); // this is running inside lock already if (current == null) { if (Config.logAutosensData) log.debug("No autosens data available"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java index 1cd45d9f03..900eba7a40 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsPlugin.java @@ -251,7 +251,7 @@ public class TreatmentsPlugin implements PluginBase, TreatmentsInterface { } } - AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData(); + AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensDataSynchronized("getMealData()"); if (autosensData != null) { result.mealCOB = autosensData.cob; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java index 6ea01692fe..65b5a2557d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/wearintegration/WatchUpdaterService.java @@ -654,7 +654,7 @@ public class WatchUpdaterService extends WearableListenerService implements private String generateCOBString() { String cobStringResult = "--"; - AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData(); + AutosensData autosensData = IobCobCalculatorPlugin.getLastAutosensData("WatcherUpdaterService"); if (autosensData != null) { cobStringResult = (int) autosensData.cob + "g"; } From 97e0aaa380e83fbe3b1447f45449416943c9f77d Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 16 Jan 2018 23:28:09 +0100 Subject: [PATCH 5/8] fix pump unreachable for virtual pump --- .../androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index cb05517cfc..1c9fdaaaf7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -212,6 +212,7 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { @Override public void getPumpStatus() { + lastDataTime = new Date(); } @Override From dfb78f5f89ea5ee3aeea71a70527b335ffaa6b04 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Fri, 19 Jan 2018 13:56:24 +0100 Subject: [PATCH 6/8] Commands: only check inputs for sanity, not therapy limits. Updated README to ask the user to configure the pump to enforce limits and only make sure inputs to the command are sane since there's no facility in place to report errors back, which is fine given this proactively guards against bugs, not a valid usage scenario. (cherry picked from commit 033ace4) --- README-Combo.md | 3 +++ .../java/de/jotomo/ruffyscripter/commands/BolusCommand.java | 4 ++-- .../java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java | 4 ---- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README-Combo.md b/README-Combo.md index a13f5af94c..aa3d4baf21 100644 --- a/README-Combo.md +++ b/README-Combo.md @@ -57,6 +57,9 @@ Setup: - Disable end of TBR alert - Set TBR duration step-size to 15 min - Set low cartridge alarm to your liking + - Configure a max bolus suited for your therapy to protect against bugs in the software + - Similarly, configure maximum TBR duration as a safeguard. Allow at least 3 hours, since + the option to disconnect the pump for 3 hours sets a 0% for 3 hours. - Enable keylock (can also be set on the pump directly, see usage section on reasoning) - Get Android Studio 3 https://developer.android.com/studio/index.html - Follow the link http://ruffy.AndroidAPS.org and clone via git (branch `combo-scripter-v2`) diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index a3ed3006e2..379e977bf8 100644 --- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -39,8 +39,8 @@ public class BolusCommand extends BaseCommand { public List validateArguments() { List violations = new ArrayList<>(); - if (bolus <= 0 || bolus > 25) { - violations.add("Requested bolus " + bolus + " out of limits (0-25)"); + if (bolus <= 0) { + violations.add("Requested bolus non-positive: " + bolus); } return violations; diff --git a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 975eb0f50d..f3bfb87313 100644 --- a/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/ruffyscripter/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -47,10 +47,6 @@ public class SetTbrCommand extends BaseCommand { } } - if (percentage == 0 && duration > 180) { - violations.add("Max allowed zero-temp duration is 3h"); - } - return violations; } From 316428c2901791a2965899ca03a3e0eac20bc9d5 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Fri, 19 Jan 2018 14:00:50 +0100 Subject: [PATCH 7/8] Add note on Android 8.1 issues. --- README-Combo.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README-Combo.md b/README-Combo.md index aa3d4baf21..9d3e52ddf7 100644 --- a/README-Combo.md +++ b/README-Combo.md @@ -12,6 +12,7 @@ Hardware requirements: Roche sends out Smartpix devices and the configuration software free of charge to their customers upon request. - A compatible phone: An Android phone with a phone running LineageOS 14.1 (formerly CyanogenMod) or Android 8.1 (Oreo). + Be aware that while Android 8.1 allows communicating with the Combo, there are still issues with AAPS on 8.1. For advanced users, it is possible to perform the pairing on a rooted phone and transfer it to another rooted phone to use with ruffy/AAPS, which must also be rooted. This allows using phones with Android < 8.1 but has not been widely tested: https://github.com/gregorybel/combo-pairing/blob/master/README.md From 8109900e9bafdd42a342c1059f9f568665103483 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Fri, 19 Jan 2018 20:11:51 +0100 Subject: [PATCH 8/8] Overview: move checkboxes before label. (cherry picked from commit 4825e16) --- app/src/main/res/layout/overview_fragment.xml | 47 ++++++++++--------- .../res/layout/overview_fragment_nsclient.xml | 47 ++++++++++--------- .../overview_fragment_nsclient_tablet.xml | 47 ++++++++++--------- .../layout/overview_fragment_smallheight.xml | 47 ++++++++++--------- 4 files changed, 96 insertions(+), 92 deletions(-) diff --git a/app/src/main/res/layout/overview_fragment.xml b/app/src/main/res/layout/overview_fragment.xml index 7369960ce4..158fd6b9b5 100644 --- a/app/src/main/res/layout/overview_fragment.xml +++ b/app/src/main/res/layout/overview_fragment.xml @@ -245,6 +245,13 @@ android:orientation="horizontal" android:paddingTop="5dp"> + + - - - - + + + + + - - - - + + + + + - - - - + + + + + - - - - + + +