From f41d597c0706de3a8987e009e0bb5c28a58db959 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 17 Aug 2017 10:56:33 +0200 Subject: [PATCH 01/50] Formatting. --- .../java/de/jotomo/ruffyscripter/History.java | 4 +++- .../ruffyscripter/PumpCapabilities.java | 2 +- .../de/jotomo/ruffyscripter/PumpState.java | 11 +++++----- .../ruffyscripter/commands/Command.java | 3 ++- .../commands/CommandException.java | 3 ++- .../ruffyscripter/commands/CommandResult.java | 6 +++--- .../DetermineCapabilitiesCommand.java | 21 ++++++++----------- .../commands/GetBasalCommand.java | 16 +++++++------- .../plugins/PumpCombo/ComboPlugin.java | 15 ++++++------- 9 files changed, 42 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/History.java b/app/src/main/java/de/jotomo/ruffyscripter/History.java index 49e34d438f..cfe514565b 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/History.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/History.java @@ -1,5 +1,7 @@ package de.jotomo.ruffyscripter; -/** The history data read from "My data" */ +/** + * The history data read from "My data" + */ public class History { } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java b/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java index 1270851ea0..50016db80e 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java @@ -2,7 +2,7 @@ package de.jotomo.ruffyscripter; /** * Created by adrian on 26/07/17. - * + *

* Contains the capabilities of the current pump model. */ diff --git a/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java b/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java index 4d519b4669..51ffafe40f 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java @@ -11,11 +11,12 @@ public class PumpState { public int tbrPercent = -1; public double tbrRate = -1; public int tbrRemainingDuration = -1; - /** This is the error message (if any) displayed by the pump if there is an alarm, - e.g. if a "TBR cancelled alarm" is active, the value will be "TBR CANCELLED". - Generally, an error code is also displayed, but it flashes and it might take - longer to read that and the pump connection gets interrupted if we're not - reacting quickly. + /** + * This is the error message (if any) displayed by the pump if there is an alarm, + * e.g. if a "TBR cancelled alarm" is active, the value will be "TBR CANCELLED". + * Generally, an error code is also displayed, but it flashes and it might take + * longer to read that and the pump connection gets interrupted if we're not + * reacting quickly. */ public String errorMsg; public boolean suspended; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java index 33d10fc223..ac87486e77 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java @@ -7,12 +7,13 @@ import de.jotomo.ruffyscripter.RuffyScripter; /** * Interface for all commands to be executed by the pump. - * + *

* Note on cammond methods and timing: a method shall wait before and after executing * as necessary to not cause timing issues, so the caller can just call methods in * sequence, letting the methods take care of waits. */ public interface Command { CommandResult execute(RuffyScripter ruffyScripter, PumpState initialPumpState); + List validateArguments(); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandException.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandException.java index 5c25ba914c..d2f31cc8e2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandException.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandException.java @@ -6,7 +6,8 @@ public class CommandException extends RuntimeException { public Exception exception = null; public String message = null; - public CommandException() {} + public CommandException() { + } public CommandException success(boolean success) { this.success = success; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java index 296f61f056..41b07e3ba2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java @@ -30,7 +30,7 @@ public class CommandResult { } public CommandResult completionTime(long completionTime) { - this.completionTime = completionTime ; + this.completionTime = completionTime; return this; } @@ -51,12 +51,12 @@ public class CommandResult { public CommandResult history(History history) { this.history = history; - return this; + return this; } public CommandResult capabilities(PumpCapabilities capabilities) { this.capabilities = capabilities; - return this; + return this; } @Override diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index adc740c13e..cf704024c6 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -2,8 +2,6 @@ package de.jotomo.ruffyscripter.commands; import android.os.SystemClock; -import com.j256.ormlite.stmt.query.In; - import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; @@ -12,7 +10,6 @@ import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; -import java.util.Locale; import de.jotomo.ruffyscripter.PumpCapabilities; import de.jotomo.ruffyscripter.PumpState; @@ -34,7 +31,7 @@ public class DetermineCapabilitiesCommand implements Command { try { //read main menu 100% or TBR? Read remaining duration. - long durationBefore = readDisplayedTbrDurationMainMenu(scripter); + long durationBefore = readDisplayedTbrDurationMainMenu(scripter); long percentageBefore = readDisplayedTbrPercentageMainMenu(scripter); enterTbrMenu(scripter); @@ -49,14 +46,14 @@ public class DetermineCapabilitiesCommand implements Command { //TODO: check if TBR is still the same or duration was less than 5 minutes - long durationAfter = readDisplayedTbrDurationMainMenu(scripter); + long durationAfter = readDisplayedTbrDurationMainMenu(scripter); long percentageAfter = readDisplayedTbrPercentageMainMenu(scripter); - if(Math.abs(durationBefore-durationAfter) > 5){ + if (Math.abs(durationBefore - durationAfter) > 5) { throw new CommandException().message("Duration jump during DetermineCapabilities"); } - if(percentageAfter != percentageBefore){ - if(durationBefore<5 && percentageAfter == 100){ + if (percentageAfter != percentageBefore) { + if (durationBefore < 5 && percentageAfter == 100) { log.debug("(percentageBefore != percentageAfter) - ignoring as tbr is now 100% and had a very short duration left"); } throw new CommandException().message("TBR changed while determining maxTBR."); @@ -99,7 +96,7 @@ public class DetermineCapabilitiesCommand implements Command { long percentageChange = maximumTempBasal - activeTempBasal; long percentageSteps = percentageChange / 10; - int retries= 0; + int retries = 0; while (percentageSteps > 0 && retries < RETRIES) { log.debug("Pressing down " + percentageSteps + " times to get to previous value. Retry " + retries); for (int i = 0; i < percentageSteps; i++) { @@ -139,7 +136,7 @@ public class DetermineCapabilitiesCommand implements Command { private int readDisplayedTbrDurationMainMenu(RuffyScripter scripter) { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if(scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)){ + if (scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)) { // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); MenuTime duration = (MenuTime) durationObj; @@ -151,8 +148,8 @@ public class DetermineCapabilitiesCommand implements Command { private int readDisplayedTbrPercentageMainMenu(RuffyScripter scripter) { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if(scripter.currentMenu.attributes().contains(MenuAttribute.TBR)){ - return (int)((Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR)).doubleValue(); + if (scripter.currentMenu.attributes().contains(MenuAttribute.TBR)) { + return (int) ((Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR)).doubleValue(); } else { return 100; } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java index 09958f6bf1..264474d1cc 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java @@ -18,7 +18,8 @@ public class GetBasalCommand implements Command { private RuffyScripter scripter; - public GetBasalCommand() {} + public GetBasalCommand() { + } @Override public List validateArguments() { @@ -27,7 +28,7 @@ public class GetBasalCommand implements Command { return violations; } -// private void tick() + // private void tick() // { // switch (state) // { @@ -104,15 +105,14 @@ public class GetBasalCommand implements Command { @Override public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { try { - Map rate = new HashMap<>(); + Map rate = new HashMap<>(); - for(int i = 0; i < 24;i++) - { - Log.v("BASAL_RATE","BASAL_RATE from "+String.format("%02d",i)+":00 = "+rate.get(i)); + for (int i = 0; i < 24; i++) { + Log.v("BASAL_RATE", "BASAL_RATE from " + String.format("%02d", i) + ":00 = " + rate.get(i)); } } catch (Exception e) { - log.error("failed to get basal",e); - return new CommandResult().success(false).message("failed to get basal: "+e.getMessage()); + log.error("failed to get basal", e); + return new CommandResult().success(false).message("failed to get basal: " + e.getMessage()); } return new CommandResult().success(true).enacted(true).message("Basal Rate was read"); } 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 a0bc347ea9..3cd45b4953 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 @@ -124,7 +124,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { * The alerter frequently checks the result of the last executed command via the lastCmdResult * field and shows a notification with sound and vibration if an error occurred. * More details on the error can then be looked up in the Combo tab. - * + *

* The alarm is re-raised every 5 minutes for as long as the error persist. As soon * as a command succeeds no more new alerts are raised. */ @@ -199,7 +199,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public void onServiceConnected(ComponentName name, IBinder service) { - keepUnbound=false; + keepUnbound = false; ruffyScripter.start(IRuffyService.Stub.asInterface(service)); log.debug("ruffy serivce connected"); } @@ -210,7 +210,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { log.debug("ruffy service disconnected"); // try to reconnect ruffy service unless unbind was explicitely requested // via unbindRuffyService - if(!keepUnbound) { + if (!keepUnbound) { SystemClock.sleep(250); bindRuffyService(); } @@ -228,6 +228,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { } private boolean keepUnbound = false; + private void unbindRuffyService() { keepUnbound = true; ruffyScripter.unbind(); @@ -543,7 +544,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { tempBasal.source = Source.USER; pumpEnactResult.isTempCancel = true; } - } else if ((activeTemp.percentRate >= 90 && activeTemp.percentRate <= 110) && activeTemp.getPlannedRemainingMinutes() <= 15 ) { + } else if ((activeTemp.percentRate >= 90 && activeTemp.percentRate <= 110) && activeTemp.getPlannedRemainingMinutes() <= 15) { // Let fake neutral temp keep running (see below) log.debug("cancelTempBasal: skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins."); pumpEnactResult.comment = "cancelTempBasal skipping changing tbr since it already is at " + activeTemp.percentRate + "% and running for another " + activeTemp.getPlannedRemainingMinutes() + " mins."; @@ -556,7 +557,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { } else { // Set a fake neutral temp to avoid TBR cancel alert. Decide 90% vs 110% based on // on whether the TBR we're cancelling is above or below 100%. - long percentage = (activeTemp.percentRate > 100) ? 110:90; + long percentage = (activeTemp.percentRate > 100) ? 110 : 90; log.debug("cancelTempBasal: changing tbr to " + percentage + "% for 15 mins."); commandResult = runCommand(new SetTbrCommand(percentage, 15)); if (commandResult.enacted) { @@ -670,12 +671,12 @@ public class ComboPlugin implements PluginBase, PumpInterface { ToastUtils.showToastInUiThread(MainApp.instance(), "Ruffy not initialized."); return; } - if (isBusy()){ + if (isBusy()) { ToastUtils.showToastInUiThread(MainApp.instance(), "Pump busy!"); return; } CommandResult result = runCommand(new DetermineCapabilitiesCommand()); - if (result.success){ + if (result.success) { pumpDescription.maxTempPercent = (int) result.capabilities.maxTempPercent; SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance()); SharedPreferences.Editor editor = preferences.edit(); From a230501f74d896930fc26fed73b5d83cb4c828b3 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 17 Aug 2017 11:21:16 +0200 Subject: [PATCH 02/50] Add alternative SetTbrCommand for pumps with different behaviour. --- .../commands/SetTbrCommandAlt.java | 302 ++++++++++++++++++ .../plugins/PumpCombo/ComboPlugin.java | 9 +- 2 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java new file mode 100644 index 0000000000..14483b95ec --- /dev/null +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -0,0 +1,302 @@ +package de.jotomo.ruffyscripter.commands; + +import android.os.SystemClock; + +import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; +import org.monkey.d.ruffy.ruffy.driver.display.MenuType; +import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import de.jotomo.ruffyscripter.PumpState; +import de.jotomo.ruffyscripter.RuffyScripter; + +public class SetTbrCommandAlt implements Command { + private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); + + private final long percentage; + private final long duration; + + public SetTbrCommandAlt(long percentage, long duration) { + this.percentage = percentage; + this.duration = duration; + } + + @Override + public List validateArguments() { + List violations = new ArrayList<>(); + + if (percentage % 10 != 0) { + violations.add("TBR percentage must be set in 10% steps"); + } + if (percentage < 0 || percentage > 500) { + violations.add("TBR percentage must be within 0-500%"); + } + + if (percentage != 100) { + if (duration % 15 != 0) { + violations.add("TBR duration can only be set in 15 minute steps"); + } + if (duration > 60 * 24) { + violations.add("Maximum TBR duration is 24 hours"); + } + } + + if (percentage == 0 && duration > 120) { + violations.add("Max allowed zero-temp duration is 2h"); + } + + return violations; + } + + @Override + public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + try { + enterTbrMenu(scripter); + inputTbrPercentage(scripter); + verifyDisplayedTbrPercentage(scripter); + + if (percentage == 100) { + cancelTbrAndConfirmCancellationWarning(scripter); + } else { + // switch to TBR_DURATION menu by pressing menu key + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + scripter.pressMenuKey(); + scripter.waitForMenuUpdate(); + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + + inputTbrDuration(scripter); + verifyDisplayedTbrDuration(scripter); + + // confirm TBR + scripter.pressCheckKey(); + scripter.waitForMenuToBeLeft(MenuType.TBR_DURATION); + } + + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, + "Pump did not return to MAIN_MEU after setting TBR. " + + "Check pump manually, the TBR might not have been set/cancelled."); + + // check main menu shows the same values we just set + if (percentage == 100) { + verifyMainMenuShowsNoActiveTbr(scripter); + return new CommandResult().success(true).enacted(true).message("TBR was cancelled"); + } else { + verifyMainMenuShowsExpectedTbrActive(scripter); + return new CommandResult().success(true).enacted(true).message( + String.format(Locale.US, "TBR set to %d%% for %d min", percentage, duration)); + } + + } catch (CommandException e) { + return e.toCommandResult(); + } + } + + private void enterTbrMenu(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + scripter.navigateToMenu(MenuType.TBR_MENU); + scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU); + scripter.pressCheckKey(); + scripter.waitForMenuUpdate(); + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + } + + private void inputTbrPercentage(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + long currentPercent = readDisplayedTbrPercentage(scripter); + log.debug("Current TBR %: " + currentPercent); + long percentageChange = percentage - currentPercent; + long percentageSteps = percentageChange / 10; + boolean increasePercentage = true; + if (percentageSteps < 0) { + increasePercentage = false; + percentageSteps = Math.abs(percentageSteps); + } + log.debug("Pressing " + (increasePercentage ? "up" : "down") + " " + percentageSteps + " times"); + for (int i = 0; i < percentageSteps; i++) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + if (increasePercentage) scripter.pressUpKey(); + else scripter.pressDownKey(); + SystemClock.sleep(100); + log.debug("Push #" + (i + 1)); + } + // Give the pump time to finish any scrolling that might still be going on, can take + // up to 1100ms. Plus some extra time to be sure + SystemClock.sleep(2000); + } + + private void verifyDisplayedTbrPercentage(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + long displayedPercentage = readDisplayedTbrPercentage(scripter); + if (displayedPercentage != percentage) { + log.debug("Final displayed TBR percentage: " + displayedPercentage); + throw new CommandException().message("Failed to set TBR percentage"); + } + + // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long + SystemClock.sleep(2000); + long refreshedDisplayedTbrPecentage = readDisplayedTbrPercentage(scripter); + if (displayedPercentage != refreshedDisplayedTbrPecentage) { + throw new CommandException().message("Failed to set TBR percentage: " + + "percentage changed after input stopped from " + + displayedPercentage + " -> " + refreshedDisplayedTbrPecentage); + } + } + + private long readDisplayedTbrPercentage(RuffyScripter scripter) { + // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded + Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); + // this as a bit hacky, the display value is blinking, so we might catch that, so + // keep trying till we get the Double we want + while (!(percentageObj instanceof Double)) { + scripter.waitForMenuUpdate(); + percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); + } + return ((Double) percentageObj).longValue(); + } + + private void inputTbrDuration(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + long currentDuration = readDisplayedTbrDuration(scripter); + if (currentDuration % 15 != 0) { + // The duration displayed is how long an active TBR will still run, + // which might be something like 0:13, hence not in 15 minute steps. + // Pressing up will go to the next higher 15 minute step. + // Don't press down, from 0:13 it can't go down, so press up. + // Pressing up from 23:59 works to go to 24:00. + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + scripter.pressUpKey(); + scripter.waitForMenuUpdate(); + currentDuration = readDisplayedTbrDuration(scripter); + } + log.debug("Current TBR duration: " + currentDuration); + long durationChange = duration - currentDuration; + long durationSteps = durationChange / 15; + boolean increaseDuration = true; + if (durationSteps < 0) { + increaseDuration = false; + durationSteps = Math.abs(durationSteps); + } + log.debug("Pressing " + (increaseDuration ? "up" : "down") + " " + durationSteps + " times"); + for (int i = 0; i < durationSteps; i++) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + if (increaseDuration) scripter.pressUpKey(); + else scripter.pressDownKey(); + SystemClock.sleep(100); + log.debug("Push #" + (i + 1)); + } + // Give the pump time to finish any scrolling that might still be going on, can take + // up to 1100ms. Plus some extra time to be sure + SystemClock.sleep(2000); + } + + private void verifyDisplayedTbrDuration(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + long displayedDuration = readDisplayedTbrDuration(scripter); + if (displayedDuration != duration) { + log.debug("Final displayed TBR duration: " + displayedDuration); + throw new CommandException().message("Failed to set TBR duration"); + } + + // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long + SystemClock.sleep(2000); + long refreshedDisplayedTbrDuration = readDisplayedTbrDuration(scripter); + if (displayedDuration != refreshedDisplayedTbrDuration) { + throw new CommandException().message("Failed to set TBR duration: " + + "duration changed after input stopped from " + + displayedDuration + " -> " + refreshedDisplayedTbrDuration); + } + } + + private long readDisplayedTbrDuration(RuffyScripter scripter) { + // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); + // this as a bit hacky, the display value is blinking, so we might catch that, so + // keep trying till we get the Double we want + while (!(durationObj instanceof MenuTime)) { + scripter.waitForMenuUpdate(); + durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); + } + MenuTime duration = (MenuTime) durationObj; + return duration.getHour() * 60 + duration.getMinute(); + } + + private void cancelTbrAndConfirmCancellationWarning(RuffyScripter scripter) { + // confirm entered TBR + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + scripter.pressCheckKey(); + + // A "TBR CANCELLED alert" is only raised by the pump when the remaining time is + // greater than 60s (displayed as 0:01, the pump goes from there to finished. + // We could read the remaining duration from MAIN_MENU, but by the time we're here, + // the pumup could have moved from 0:02 to 0:01, so instead, check if a "TBR CANCELLED" alert + // is raised and if so dismiss it + long inFiveSeconds = System.currentTimeMillis() + 5 * 1000; + boolean alertProcessed = false; + while (System.currentTimeMillis() < inFiveSeconds && !alertProcessed) { + if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { + // Check the raised alarm is TBR CANCELLED, so we're not accidentally cancelling + // a different alarm that might be raised at the same time. + // Note that the message is permanently displayed, while the error code is blinking. + // A wait till the error code can be read results in the code hanging, despite + // menu updates coming in, so just check the message. + // TODO v2 this only works when the pump's language is English + String errorMsg = (String) scripter.currentMenu.getAttribute(MenuAttribute.MESSAGE); + if (!errorMsg.equals("TBR CANCELLED")) { + throw new CommandException().success(false).enacted(false) + .message("An alert other than the expected TBR CANCELLED was raised by the pump: " + + errorMsg + ". Please check the pump."); + } + // confirm "TBR CANCELLED" alert + scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); + scripter.pressCheckKey(); + // dismiss "TBR CANCELLED" alert + scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); + scripter.pressCheckKey(); + scripter.waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR); + alertProcessed = true; + } + SystemClock.sleep(10); + } + } + + private void verifyMainMenuShowsNoActiveTbr(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + Double tbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR); + boolean runtimeDisplayed = scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME); + if (tbrPercentage != 100 || runtimeDisplayed) { + throw new CommandException().message("Cancelling TBR failed, TBR is still set according to MAIN_MENU"); + } + } + + private void verifyMainMenuShowsExpectedTbrActive(RuffyScripter scripter) { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + // new TBR set; percentage and duration must be displayed ... + if (!scripter.currentMenu.attributes().contains(MenuAttribute.TBR) || + !scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)) { + throw new CommandException().message("Setting TBR failed, according to MAIN_MENU no TBR is active"); + } + Double mmTbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR); + MenuTime mmTbrDuration = (MenuTime) scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); + // ... and be the same as what we set + // note that displayed duration might have already counted down, e.g. from 30 minutes to + // 29 minutes and 59 seconds, so that 29 minutes are displayed + int mmTbrDurationInMinutes = mmTbrDuration.getHour() * 60 + mmTbrDuration.getMinute(); + if (mmTbrPercentage != percentage || (mmTbrDurationInMinutes != duration && mmTbrDurationInMinutes + 1 != duration)) { + throw new CommandException().message("Setting TBR failed, TBR in MAIN_MENU differs from expected"); + } + } + + @Override + public String toString() { + return "SetTbrCommand{" + + "percentage=" + percentage + + ", duration=" + duration + + '}'; + } +} 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 3cd45b4953..29e78847e0 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 @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; import java.util.Date; +import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; import de.jotomo.ruffyscripter.commands.BolusCommand; import de.jotomo.ruffyscripter.commands.CancelTbrCommand; @@ -33,7 +34,7 @@ import de.jotomo.ruffyscripter.commands.CommandResult; import de.jotomo.ruffyscripter.commands.DetermineCapabilitiesCommand; import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; -import de.jotomo.ruffyscripter.PumpState; +import de.jotomo.ruffyscripter.commands.SetTbrCommandAlt; import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -493,12 +494,16 @@ public class ComboPlugin implements PluginBase, PumpInterface { adjustedPercent = rounded.intValue(); } - CommandResult commandResult = runCommand(new SetTbrCommand(adjustedPercent, durationInMinutes)); + Command cmd = !BuildConfig.VERSION.contains("joe") + ? new SetTbrCommand(adjustedPercent, durationInMinutes) + : new SetTbrCommandAlt(adjustedPercent, durationInMinutes); + CommandResult commandResult = runCommand(cmd); if (commandResult.enacted) { TemporaryBasal tempStart = new TemporaryBasal(commandResult.completionTime); // TODO commandResult.state.tbrRemainingDuration might already display 29 if 30 was set, since 29:59 is shown as 29 ... // we should check this, but really ... something must be really screwed up if that number was anything different + // TODO actually ... might setting 29 help with gaps between TBRs? w/o the hack in TemporaryBasal? tempStart.durationInMinutes = durationInMinutes; tempStart.percentRate = adjustedPercent; tempStart.isAbsolute = false; From c1ecad1ed6c7b8928122ef4654c46ddceec40c6b Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Tue, 15 Aug 2017 20:20:30 +0200 Subject: [PATCH 03/50] Initial take on bolus progress reporting. --- .../ruffyscripter/commands/BolusCommand.java | 22 +++++++++++-- .../commands/ProgressReportCallback.java | 13 ++++++++ .../plugins/PumpCombo/ComboPlugin.java | 31 ++++++++++++++++++- 3 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index d5197452e3..073ef08653 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -14,12 +14,18 @@ import java.util.Locale; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.BOLUSING; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.FINISHED; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.PREPARING; + public class BolusCommand implements Command { private static final Logger log = LoggerFactory.getLogger(BolusCommand.class); private final double bolus; + private final ProgressReportCallback progressReportCallback; - public BolusCommand(double bolus) { + public BolusCommand(double bolus, ProgressReportCallback progressReportCallback) { + this.progressReportCallback = progressReportCallback; this.bolus = bolus; } @@ -36,6 +42,7 @@ public class BolusCommand implements Command { @Override public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + progressReportCallback.progress(PREPARING, 0, 0); try { enterBolusMenu(scripter); @@ -45,6 +52,7 @@ public class BolusCommand implements Command { // confirm bolus scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); scripter.pressCheckKey(); + progressReportCallback.progress(BOLUSING, 0, 0); // the pump displays the entered bolus and waits a bit to let user check and cancel scripter.waitForMenuToBeLeft(MenuType.BOLUS_ENTER); @@ -56,9 +64,15 @@ public class BolusCommand implements Command { // wait for bolus delivery to complete; the remaining units to deliver are counted // down and are displayed on the main menu. Double bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); + double lastBolusReported = 0; while (bolusRemaining != null) { - log.debug("Delivering bolus, remaining: " + bolusRemaining); - SystemClock.sleep(200); + if (lastBolusReported != bolusRemaining) { + log.debug("Delivering bolus, remaining: " + bolusRemaining); + int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100)); + progressReportCallback.progress(BOLUSING, percentDelivered, bolus - bolusRemaining); + lastBolusReported = bolusRemaining; + } + SystemClock.sleep(50); bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); } @@ -70,6 +84,8 @@ public class BolusCommand implements Command { "Bolus delivery did not complete as expected. " + "Check pump manually, the bolus might not have been delivered."); + progressReportCallback.progress(FINISHED, 100, bolus); + // read last bolus record; those menus display static data and therefore // only a single menu update is sent scripter.navigateToMenu(MenuType.MY_DATA_MENU); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java new file mode 100644 index 0000000000..c007dfb45f --- /dev/null +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java @@ -0,0 +1,13 @@ +package de.jotomo.ruffyscripter.commands; + +public interface ProgressReportCallback { + enum State { + PREPARING, + BOLUSING, + CANCELLING, + FINISHED, + CANCELLED + } + + void progress(State state, int percent, double delivered); +} 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 29e78847e0..bac8a960b6 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 @@ -31,6 +31,7 @@ import de.jotomo.ruffyscripter.commands.BolusCommand; import de.jotomo.ruffyscripter.commands.CancelTbrCommand; import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandResult; +import de.jotomo.ruffyscripter.commands.ProgressReportCallback; import de.jotomo.ruffyscripter.commands.DetermineCapabilitiesCommand; import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; @@ -48,6 +49,7 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI; import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; @@ -369,7 +371,34 @@ public class ComboPlugin implements PluginBase, PumpInterface { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0) { // bolus needed, ask pump to deliver it - CommandResult bolusCmdResult = runCommand(new BolusCommand(detailedBolusInfo.insulin)); + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + MainApp.bus().post(bolusingEvent); + CommandResult bolusCmdResult = runCommand(new BolusCommand(detailedBolusInfo.insulin, new ProgressReportCallback() { + @Override + public void progress(State state, int percent, double delivered) { + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + switch (state) { + // TODO move into enum as toString or so and make it translateb + case BOLUSING: + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered); + break; + case PREPARING: + bolusingEvent.status = "Preparing pump for bolus"; + break; + case FINISHED: + bolusingEvent.status = "Bolus delivery finished successfully"; + break; + case CANCELLED: + bolusingEvent.status = "Bolus delivery was cancelled"; + break; + case CANCELLING: + bolusingEvent.status = "Cancelling bolus delivery"; + break; + } + bolusingEvent.percent = percent; + MainApp.bus().post(bolusingEvent); + } + })); PumpEnactResult pumpEnactResult = new PumpEnactResult(); pumpEnactResult.success = bolusCmdResult.success; pumpEnactResult.enacted = bolusCmdResult.enacted; From a664bdeaaa40942317a9736798f177df1ebe4497 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Tue, 15 Aug 2017 20:42:31 +0200 Subject: [PATCH 04/50] Initial take on bolus cancellation. --- .../ruffyscripter/commands/BolusCommand.java | 27 ++++++++ .../plugins/PumpCombo/ComboPlugin.java | 63 ++++++++++--------- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 073ef08653..2d70c5d1b1 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -15,6 +15,8 @@ import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.BOLUSING; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.CANCELLED; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.CANCELLING; import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.FINISHED; import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.PREPARING; @@ -23,6 +25,7 @@ public class BolusCommand implements Command { private final double bolus; private final ProgressReportCallback progressReportCallback; + private volatile boolean cancelRequested; public BolusCommand(double bolus, ProgressReportCallback progressReportCallback) { this.progressReportCallback = progressReportCallback; @@ -52,10 +55,24 @@ public class BolusCommand implements Command { // confirm bolus scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); scripter.pressCheckKey(); + if (cancelRequested) { + scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 30_000); + progressReportCallback.progress(CANCELLED, 0, 0); + return new CommandResult().success(true).enacted(false).message("Bolus cancelled as per user request with no insulin delivered"); + } progressReportCallback.progress(BOLUSING, 0, 0); // the pump displays the entered bolus and waits a bit to let user check and cancel + // TODO pressing up (and possible other keys) cancels the bolus scripter.waitForMenuToBeLeft(MenuType.BOLUS_ENTER); + while (scripter.currentMenu.getType() == MenuType.BOLUS_ENTER) { + if (cancelRequested) { + scripter.pressUpKey(); + // TODO deal with error; write a method to wait for and cancel a specific alarm + // wait happens if the keypress comes too late? just try agoin below? + } + SystemClock.sleep(50); + } scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, "Pump did not return to MAIN_MEU from BOLUS_ENTER to deliver bolus. " @@ -66,12 +83,17 @@ public class BolusCommand implements Command { Double bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); double lastBolusReported = 0; while (bolusRemaining != null) { + if (cancelRequested) { + // TODO press up 3s, deal with bolus cancelled error, retrieved amount actually delivered from history and return it + // since the cancellation takes three seconds some insulin will have definately been delivered (delivery speed is roughly 0.1U/s) + } if (lastBolusReported != bolusRemaining) { log.debug("Delivering bolus, remaining: " + bolusRemaining); int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100)); progressReportCallback.progress(BOLUSING, percentDelivered, bolus - bolusRemaining); lastBolusReported = bolusRemaining; } + // TODO deal with alarms that can arise; an oclussion with raise an oclussion alert as well as a bolus cancelled alert SystemClock.sleep(50); bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); } @@ -174,6 +196,11 @@ public class BolusCommand implements Command { return (double) amountObj; } + public void requestCancellation() { + cancelRequested = true; + progressReportCallback.progress(CANCELLING, 0, 0); + } + @Override public String toString() { return "BolusCommand{" + 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 bac8a960b6..904317d361 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 @@ -80,6 +80,8 @@ public class ComboPlugin implements PluginBase, PumpInterface { @NonNull volatile Date lastCmdTime = new Date(0); volatile PumpState pumpState = new PumpState(); + @Nullable + private volatile BolusCommand runningBolusCommand; private static PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult(); @@ -364,6 +366,33 @@ public class ComboPlugin implements PluginBase, PumpInterface { return basal; } + private static ProgressReportCallback bolusProgressReportCallback = new ProgressReportCallback() { + @Override + public void progress(ProgressReportCallback.State state, int percent, double delivered) { + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + switch (state) { + // TODO move into enum as toString or so and make it translateb + case BOLUSING: + bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered); + break; + case PREPARING: + bolusingEvent.status = "Preparing pump for bolus"; + break; + case FINISHED: + bolusingEvent.status = "Bolus delivery finished successfully"; + break; + case CANCELLED: + bolusingEvent.status = "Bolus delivery was cancelled"; + break; + case CANCELLING: + bolusingEvent.status = "Cancelling bolus delivery"; + break; + } + bolusingEvent.percent = percent; + MainApp.bus().post(bolusingEvent); + } + }; + // what a mess: pump integration code reading carb info from Detailed**Bolus**Info, // writing carb treatments to the history table. What's PumpEnactResult for again? @Override @@ -373,32 +402,10 @@ public class ComboPlugin implements PluginBase, PumpInterface { // bolus needed, ask pump to deliver it EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); MainApp.bus().post(bolusingEvent); - CommandResult bolusCmdResult = runCommand(new BolusCommand(detailedBolusInfo.insulin, new ProgressReportCallback() { - @Override - public void progress(State state, int percent, double delivered) { - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - switch (state) { - // TODO move into enum as toString or so and make it translateb - case BOLUSING: - bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered); - break; - case PREPARING: - bolusingEvent.status = "Preparing pump for bolus"; - break; - case FINISHED: - bolusingEvent.status = "Bolus delivery finished successfully"; - break; - case CANCELLED: - bolusingEvent.status = "Bolus delivery was cancelled"; - break; - case CANCELLING: - bolusingEvent.status = "Cancelling bolus delivery"; - break; - } - bolusingEvent.percent = percent; - MainApp.bus().post(bolusingEvent); - } - })); + // TODO move into enum as toString or so and make it translateb + runningBolusCommand = new BolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback); + CommandResult bolusCmdResult = runCommand(runningBolusCommand); + runningBolusCommand = null; PumpEnactResult pumpEnactResult = new PumpEnactResult(); pumpEnactResult.success = bolusCmdResult.success; pumpEnactResult.enacted = bolusCmdResult.enacted; @@ -484,9 +491,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public void stopBolusDelivering() { - // there's no way to stop the combo once delivery has started - // but before that, we could interrupt the command thread ... pause - // till pump times out or raises an error + if (runningBolusCommand != null) runningBolusCommand.requestCancellation(); } // Note: AAPS calls this only to enact OpenAPS recommendations From 22e3517cd6dfa756c7c5478f8e8a82e0872db403 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 16 Aug 2017 23:03:21 +0200 Subject: [PATCH 05/50] wip cancelling --- .../jotomo/ruffyscripter/RuffyScripter.java | 1 + .../ruffyscripter/commands/BolusCommand.java | 83 ++++++++++++------- .../commands/ProgressReportCallback.java | 11 ++- .../plugins/PumpCombo/ComboPlugin.java | 15 ++-- 4 files changed, 65 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index f329a71df3..eabcdbf505 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -356,6 +356,7 @@ public class RuffyScripter { } catch (CommandException e) { return e.toCommandResult(); } catch (Exception e) { + // TODO detect and report pump warnings/errors differently? log.error("Error in ruffyscripter/ruffy", e); return new CommandResult().exception(e).message("Unexpected exception communication with ruffy: " + e.getMessage()); } finally { diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 2d70c5d1b1..6ae191bf64 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -14,10 +14,10 @@ import java.util.Locale; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.BOLUSING; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.CANCELLED; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.CANCELLING; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.FINISHED; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.DELIVERING; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.STOPPED; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.STOPPING; +import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.DELIVERED; import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.PREPARING; public class BolusCommand implements Command { @@ -45,55 +45,75 @@ public class BolusCommand implements Command { @Override public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { - progressReportCallback.progress(PREPARING, 0, 0); try { enterBolusMenu(scripter); - inputBolusAmount(scripter); verifyDisplayedBolusAmount(scripter); + if (cancelRequested) { + progressReportCallback.report(STOPPING, 0, 0); + scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 30 * 1000); + progressReportCallback.report(STOPPED, 0, 0); + return new CommandResult().success(true).enacted(false) + .message("Bolus cancelled as per user request with no insulin delivered"); + } + // confirm bolus scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); scripter.pressCheckKey(); - if (cancelRequested) { - scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 30_000); - progressReportCallback.progress(CANCELLED, 0, 0); - return new CommandResult().success(true).enacted(false).message("Bolus cancelled as per user request with no insulin delivered"); - } - progressReportCallback.progress(BOLUSING, 0, 0); - // the pump displays the entered bolus and waits a bit to let user check and cancel - // TODO pressing up (and possible other keys) cancels the bolus - scripter.waitForMenuToBeLeft(MenuType.BOLUS_ENTER); + // the pump displays the entered bolus and waits a few seconds to let user check and cancel while (scripter.currentMenu.getType() == MenuType.BOLUS_ENTER) { if (cancelRequested) { + progressReportCallback.report(STOPPING, 0, 0); scripter.pressUpKey(); - // TODO deal with error; write a method to wait for and cancel a specific alarm - // wait happens if the keypress comes too late? just try agoin below? + // wait up to 1s for a BOLUS_CANCELLED alert, if it doesn't happen we missed + // the window, simply continue and let the next cancel attempt try its luck + boolean alertWasCancelled = confirmAlert("BOLUS CANCELLED", 1000); + if (alertWasCancelled) { + progressReportCallback.report(STOPPED, 0, 0); + return new CommandResult().success(true).enacted(false) + .message("Bolus cancelled as per user request with no insulin delivered"); + } } - SystemClock.sleep(50); + SystemClock.sleep(10); } - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, "Pump did not return to MAIN_MEU from BOLUS_ENTER to deliver bolus. " + "Check pump manually, the bolus might not have been delivered."); - // wait for bolus delivery to complete; the remaining units to deliver are counted - // down and are displayed on the main menu. + progressReportCallback.report(DELIVERING, 0, 0); Double bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); double lastBolusReported = 0; + // wait for bolus delivery to complete; the remaining units to deliver are counted + // down and are displayed on the main menu. while (bolusRemaining != null) { if (cancelRequested) { + progressReportCallback.report(STOPPING, 0, 0); // TODO press up 3s, deal with bolus cancelled error, retrieved amount actually delivered from history and return it // since the cancellation takes three seconds some insulin will have definately been delivered (delivery speed is roughly 0.1U/s) + progressReportCallback.report(STOPPED, 0, 0); } if (lastBolusReported != bolusRemaining) { log.debug("Delivering bolus, remaining: " + bolusRemaining); int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100)); - progressReportCallback.progress(BOLUSING, percentDelivered, bolus - bolusRemaining); + progressReportCallback.report(DELIVERING, percentDelivered, bolus - bolusRemaining); lastBolusReported = bolusRemaining; } // TODO deal with alarms that can arise; an oclussion with raise an oclussion alert as well as a bolus cancelled alert + // occlusion cancels the bolus -> abort routine to report back delivered bolus; + // low cartridge alert lets bolus run out + // also, any other error or warning can occur and we should return in a controlled fashion - + // communicating back what was actually delivered. + // generally: cancel an alert on the pump and raise the error in AAPS? + // letting the alert go off disrupts comms if the user interacts with the pump, + // then we need to schedule a history read in the near future, let thee user know + // the data will be out of sync for a bit. + // how does the dana handle pump errors? has no vibration, but sound i guess + // should this be configurabe? initially? + if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { + + } SystemClock.sleep(50); bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); } @@ -106,7 +126,7 @@ public class BolusCommand implements Command { "Bolus delivery did not complete as expected. " + "Check pump manually, the bolus might not have been delivered."); - progressReportCallback.progress(FINISHED, 100, bolus); + progressReportCallback.report(DELIVERED, 100, bolus); // read last bolus record; those menus display static data and therefore // only a single menu update is sent @@ -130,12 +150,11 @@ public class BolusCommand implements Command { } log.debug("Bolus record in history confirms delivered bolus"); - // leave menu to go back to main menu - scripter.pressCheckKey(); - scripter.waitForMenuToBeLeft(MenuType.BOLUS_DATA); - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, - "Bolus was correctly delivered and checked against history, but we " - + "did not return the main menu successfully."); + if (!scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 15 * 1000)) { + throw new CommandException().success(false).enacted(true) + .message("Bolus was correctly delivered and checked against history, but we " + + "did not return the main menu successfully."); + } return new CommandResult().success(true).enacted(true) .message(String.format(Locale.US, "Delivered %02.1f U", bolus)); @@ -144,6 +163,10 @@ public class BolusCommand implements Command { } } + private boolean confirmAlert(String alertText, int maxWaitTillExpectedAlert) { + + } + private void enterBolusMenu(RuffyScripter scripter) { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); scripter.navigateToMenu(MenuType.BOLUS_MENU); @@ -198,7 +221,7 @@ public class BolusCommand implements Command { public void requestCancellation() { cancelRequested = true; - progressReportCallback.progress(CANCELLING, 0, 0); + progressReportCallback.report(STOPPING, 0, 0); } @Override diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java index c007dfb45f..4491da501d 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java @@ -2,12 +2,11 @@ package de.jotomo.ruffyscripter.commands; public interface ProgressReportCallback { enum State { - PREPARING, - BOLUSING, - CANCELLING, - FINISHED, - CANCELLED + DELIVERING, + DELIVERED, + STOPPING, + STOPPED } - void progress(State state, int percent, double delivered); + void report(State state, int percent, double delivered); } 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 904317d361..82a9e051e9 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 @@ -368,23 +368,20 @@ public class ComboPlugin implements PluginBase, PumpInterface { private static ProgressReportCallback bolusProgressReportCallback = new ProgressReportCallback() { @Override - public void progress(ProgressReportCallback.State state, int percent, double delivered) { + public void report(ProgressReportCallback.State state, int percent, double delivered) { EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); switch (state) { // TODO move into enum as toString or so and make it translateb - case BOLUSING: + case DELIVERING: bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered); break; - case PREPARING: - bolusingEvent.status = "Preparing pump for bolus"; - break; - case FINISHED: + case DELIVERED: bolusingEvent.status = "Bolus delivery finished successfully"; break; - case CANCELLED: + case STOPPED: bolusingEvent.status = "Bolus delivery was cancelled"; break; - case CANCELLING: + case STOPPING: bolusingEvent.status = "Cancelling bolus delivery"; break; } @@ -402,7 +399,6 @@ public class ComboPlugin implements PluginBase, PumpInterface { // bolus needed, ask pump to deliver it EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); MainApp.bus().post(bolusingEvent); - // TODO move into enum as toString or so and make it translateb runningBolusCommand = new BolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback); CommandResult bolusCmdResult = runCommand(runningBolusCommand); runningBolusCommand = null; @@ -433,6 +429,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { // TODO the ui freezes when the calculator issues a carb-only treatment // so just wait, yeah, this is dumb. for now; proper fix via GL#10 // info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog.scheduleDismiss() + // send event to indicate popup can be dismissed? SystemClock.sleep(6000); PumpEnactResult pumpEnactResult = new PumpEnactResult(); pumpEnactResult.success = true; From 738dd72f5bf64eb245b4b7a6f1c73f5856f7fef9 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 17 Aug 2017 10:14:43 +0200 Subject: [PATCH 06/50] Remove TODOs for extended bolus. --- .../nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 82a9e051e9..3ed1028434 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 @@ -103,7 +103,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { pumpDescription.isBolusCapable = true; pumpDescription.bolusStep = 0.1d; - pumpDescription.isExtendedBolusCapable = false; // TODO + pumpDescription.isExtendedBolusCapable = false; pumpDescription.extendedBolusStep = 0.1d; pumpDescription.extendedBolusDurationStep = 15; pumpDescription.extendedBolusMaxDuration = 12 * 60; @@ -618,7 +618,6 @@ public class ComboPlugin implements PluginBase, PumpInterface { return pumpEnactResult; } - // TODO @Override public PumpEnactResult cancelExtendedBolus() { return OPERATION_NOT_SUPPORTED; From fabaf7c2efbbbce6452ec2d467c9ed444e9bc934 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 17 Aug 2017 10:56:06 +0200 Subject: [PATCH 07/50] more --- .../ruffyscripter/commands/BolusCommand.java | 4 +- .../plugins/PumpCombo/ComboPlugin.java | 56 +++++++++---------- app/src/main/res/values/strings.xml | 2 + 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 6ae191bf64..b9f54205d2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -18,7 +18,6 @@ import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.DELI import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.STOPPED; import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.STOPPING; import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.DELIVERED; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.PREPARING; public class BolusCommand implements Command { private static final Logger log = LoggerFactory.getLogger(BolusCommand.class); @@ -164,7 +163,8 @@ public class BolusCommand implements Command { } private boolean confirmAlert(String alertText, int maxWaitTillExpectedAlert) { - + // TODO + return false; } private void enterBolusMenu(RuffyScripter scripter) { 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 3ed1028434..c2c7076e6c 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 @@ -369,36 +369,38 @@ public class ComboPlugin implements PluginBase, PumpInterface { private static ProgressReportCallback bolusProgressReportCallback = new ProgressReportCallback() { @Override public void report(ProgressReportCallback.State state, int percent, double delivered) { - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + EventOverviewBolusProgress enent = EventOverviewBolusProgress.getInstance(); switch (state) { - // TODO move into enum as toString or so and make it translateb case DELIVERING: - bolusingEvent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered); + enent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivering), delivered); break; case DELIVERED: - bolusingEvent.status = "Bolus delivery finished successfully"; - break; - case STOPPED: - bolusingEvent.status = "Bolus delivery was cancelled"; + enent.status = String.format(MainApp.sResources.getString(R.string.bolusdelivered), delivered); break; case STOPPING: - bolusingEvent.status = "Cancelling bolus delivery"; + enent.status = MainApp.sResources.getString(R.string.bolusstopping); + break; + case STOPPED: + enent.status = MainApp.sResources.getString(R.string.bolusstopped); break; } - bolusingEvent.percent = percent; - MainApp.bus().post(bolusingEvent); + enent.percent = percent; + MainApp.bus().post(enent); } }; - // what a mess: pump integration code reading carb info from Detailed**Bolus**Info, - // writing carb treatments to the history table. What's PumpEnactResult for again? + /** Updates Treatment records with carbs and boluses and delivers a bolus if needed */ @Override public PumpEnactResult deliverTreatment(DetailedBolusInfo detailedBolusInfo) { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0) { // bolus needed, ask pump to deliver it - EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); - MainApp.bus().post(bolusingEvent); + + // TODO read history to ensure there are no boluses delivered on the pump we aren't + // aware of and haven't included in the bolus calulation + + // Note that the BolusCommand send progress updates to the bolusProgressReporterCallback, + // which then posts appropriate events on the bus, so in this branch no posts are needed runningBolusCommand = new BolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback); CommandResult bolusCmdResult = runCommand(runningBolusCommand); runningBolusCommand = null; @@ -407,12 +409,8 @@ public class ComboPlugin implements PluginBase, PumpInterface { pumpEnactResult.enacted = bolusCmdResult.enacted; pumpEnactResult.comment = bolusCmdResult.message; - // if enacted, add bolus and carbs to treatment history + // if enacted by pump, add bolus and carbs to treatment history if (pumpEnactResult.enacted) { - // TODO if no error occurred, the requested bolus is what the pump delievered, - // that has been checked. If an error occurred, we should check how much insulin - // was delivered, e.g. when the cartridge went empty mid-bolus - // For the first iteration, the alert the pump raises must suffice pumpEnactResult.bolusDelivered = detailedBolusInfo.insulin; pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; @@ -425,11 +423,6 @@ public class ComboPlugin implements PluginBase, PumpInterface { return pumpEnactResult; } else { // no bolus required, carb only treatment - - // TODO the ui freezes when the calculator issues a carb-only treatment - // so just wait, yeah, this is dumb. for now; proper fix via GL#10 - // info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog.scheduleDismiss() - // send event to indicate popup can be dismissed? SystemClock.sleep(6000); PumpEnactResult pumpEnactResult = new PumpEnactResult(); pumpEnactResult.success = true; @@ -438,6 +431,10 @@ public class ComboPlugin implements PluginBase, PumpInterface { pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; pumpEnactResult.comment = MainApp.instance().getString(R.string.virtualpump_resultok); MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + bolusingEvent.percent = 100; + MainApp.bus().post(bolusingEvent); return pumpEnactResult; } } else { @@ -453,6 +450,12 @@ public class ComboPlugin implements PluginBase, PumpInterface { } } + @Override + public void stopBolusDelivering() { + BolusCommand localRunningBolusCommand = runningBolusCommand; + if (localRunningBolusCommand != null) localRunningBolusCommand.requestCancellation(); + } + private CommandResult runCommand(Command command) { if (ruffyScripter == null) { String msg = "No connection to ruffy. Pump control not available."; @@ -486,11 +489,6 @@ public class ComboPlugin implements PluginBase, PumpInterface { return commandResult; } - @Override - public void stopBolusDelivering() { - if (runningBolusCommand != null) runningBolusCommand.requestCancellation(); - } - // Note: AAPS calls this only to enact OpenAPS recommendations @Override public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean force) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8597ac3d74..bc806b0426 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -702,6 +702,8 @@ Ultra-Rapid Oref "DIA of %s too short - using %s instead!" ACTIVATE PROFILE + Stopping bolus delivery + Bolus delivery stopped From d851637d4f88e066791869f3b3b8397d3cdf9360 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Fri, 18 Aug 2017 11:54:57 +0200 Subject: [PATCH 08/50] more --- .../ruffyscripter/commands/BolusCommand.java | 37 ++++++++++++++++--- .../commands/ProgressReportCallback.java | 12 ------ .../plugins/PumpCombo/ComboPlugin.java | 7 ++-- 3 files changed, 34 insertions(+), 22 deletions(-) delete mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index b9f54205d2..cc03ab0f86 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -14,10 +14,10 @@ import java.util.Locale; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.DELIVERING; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.STOPPED; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.STOPPING; -import static de.jotomo.ruffyscripter.commands.ProgressReportCallback.State.DELIVERED; +import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.DELIVERING; +import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.STOPPED; +import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.STOPPING; +import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.DELIVERED; public class BolusCommand implements Command { private static final Logger log = LoggerFactory.getLogger(BolusCommand.class); @@ -86,11 +86,23 @@ public class BolusCommand implements Command { double lastBolusReported = 0; // wait for bolus delivery to complete; the remaining units to deliver are counted // down and are displayed on the main menu. + // TODO extract into method while (bolusRemaining != null) { if (cancelRequested) { progressReportCallback.report(STOPPING, 0, 0); + // TODO just press up 3s in a separated thread and let this loop run + // and at the end handle the outcome and returned raise alarms, whether cancel was reuqested etc + // TODO press up 3s, deal with bolus cancelled error, retrieved amount actually delivered from history and return it - // since the cancellation takes three seconds some insulin will have definately been delivered (delivery speed is roughly 0.1U/s) + // since the cancellation takes three seconds some insulin will have definitely been delivered (delivery speed is roughly 0.1U/s), + // but the pump may also finish delivering the bolus while we try to cancel it + // so, press a button, keep it press and deal with three outcomes: + // * delivery finished (no more remaining bolus displayed) + // * bolus was cancelled (warning raised) + // * any other error (low cartridge, occlusion, both will also trigger 'bolus cancelled' errors) + // cancelBolusInDelivery() + // TODO new thread to press button and then deal with outcomes below, since all errors can occur at all time, pressing + // abort just forces an error (if keyrpess is in time) progressReportCallback.report(STOPPED, 0, 0); } if (lastBolusReported != bolusRemaining) { @@ -111,7 +123,7 @@ public class BolusCommand implements Command { // how does the dana handle pump errors? has no vibration, but sound i guess // should this be configurabe? initially? if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { - + // see errors being dealt with trying to cancel } SystemClock.sleep(50); bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); @@ -162,6 +174,8 @@ public class BolusCommand implements Command { } } + // TODO confirmAlarms? and report back which were cancelled? + private boolean confirmAlert(String alertText, int maxWaitTillExpectedAlert) { // TODO return false; @@ -230,4 +244,15 @@ public class BolusCommand implements Command { "bolus=" + bolus + '}'; } + + public interface ProgressReportCallback { + enum State { + DELIVERING, + DELIVERED, + STOPPING, + STOPPED + } + + void report(State state, int percent, double delivered); + } } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java deleted file mode 100644 index 4491da501d..0000000000 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/ProgressReportCallback.java +++ /dev/null @@ -1,12 +0,0 @@ -package de.jotomo.ruffyscripter.commands; - -public interface ProgressReportCallback { - enum State { - DELIVERING, - DELIVERED, - STOPPING, - STOPPED - } - - void report(State state, int percent, double delivered); -} 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 c2c7076e6c..8d9344d98c 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 @@ -31,7 +31,6 @@ import de.jotomo.ruffyscripter.commands.BolusCommand; import de.jotomo.ruffyscripter.commands.CancelTbrCommand; import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandResult; -import de.jotomo.ruffyscripter.commands.ProgressReportCallback; import de.jotomo.ruffyscripter.commands.DetermineCapabilitiesCommand; import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; @@ -366,9 +365,9 @@ public class ComboPlugin implements PluginBase, PumpInterface { return basal; } - private static ProgressReportCallback bolusProgressReportCallback = new ProgressReportCallback() { + private static BolusCommand.ProgressReportCallback bolusProgressReportCallback = new BolusCommand.ProgressReportCallback() { @Override - public void report(ProgressReportCallback.State state, int percent, double delivered) { + public void report(BolusCommand.ProgressReportCallback.State state, int percent, double delivered) { EventOverviewBolusProgress enent = EventOverviewBolusProgress.getInstance(); switch (state) { case DELIVERING: @@ -399,7 +398,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { // TODO read history to ensure there are no boluses delivered on the pump we aren't // aware of and haven't included in the bolus calulation - // Note that the BolusCommand send progress updates to the bolusProgressReporterCallback, + // Note that the BolusCommand sends progress updates to the bolusProgressReporterCallback, // which then posts appropriate events on the bus, so in this branch no posts are needed runningBolusCommand = new BolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback); CommandResult bolusCmdResult = runCommand(runningBolusCommand); From b162fcce0120568d49c49578667ffd1e0d427da8 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 20 Aug 2017 20:47:58 +0200 Subject: [PATCH 09/50] wip --- .../ruffyscripter/commands/BolusCommand.java | 30 +++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index cc03ab0f86..d57b8cbe0d 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -84,9 +84,13 @@ public class BolusCommand implements Command { progressReportCallback.report(DELIVERING, 0, 0); Double bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); double lastBolusReported = 0; + List alarmsRaised = new ArrayList<>(); // wait for bolus delivery to complete; the remaining units to deliver are counted // down and are displayed on the main menu. // TODO extract into method + + // TODO 'low cartrdige' alarm must be handled inside, since the bolus continues regardless; + // it must be claread so we can see the remaining bolus again; while (bolusRemaining != null) { if (cancelRequested) { progressReportCallback.report(STOPPING, 0, 0); @@ -122,13 +126,32 @@ public class BolusCommand implements Command { // the data will be out of sync for a bit. // how does the dana handle pump errors? has no vibration, but sound i guess // should this be configurabe? initially? + if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { - // see errors being dealt with trying to cancel + String message = (String) scripter.currentMenu.getAttribute(MenuAttribute.MESSAGE); + if (message.equals("LOW CARTRIDGE")) { + alarmsRaised.add(message); + // confirm, note alert was raised and continue bolusing) + } else { + // any other alert + break; + } } SystemClock.sleep(50); bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); } + // wait up to 2s for any possible warning to be raised + long minWait = System.currentTimeMillis() + 2 * 1000; + while (scripter.currentMenu.getType() != MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { + SystemClock.sleep(50); + } + + // process warnings (confirm them, report back to AAPS about them) + while (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { + // TODO + } + // TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus? // TODO how are error states reported back to the caller that occur outside of calls in genal? Low battery, low cartridge? @@ -137,7 +160,8 @@ public class BolusCommand implements Command { "Bolus delivery did not complete as expected. " + "Check pump manually, the bolus might not have been delivered."); - progressReportCallback.report(DELIVERED, 100, bolus); + + // TODO report back what was read from history // read last bolus record; those menus display static data and therefore // only a single menu update is sent @@ -167,6 +191,8 @@ public class BolusCommand implements Command { + "did not return the main menu successfully."); } + progressReportCallback.report(DELIVERED, 100, bolus); + return new CommandResult().success(true).enacted(true) .message(String.format(Locale.US, "Delivered %02.1f U", bolus)); } catch (CommandException e) { From 6cc73dcc1ca5de10c0a2e6c3bf8d1dbec2a1ab99 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 20 Aug 2017 23:15:24 +0200 Subject: [PATCH 10/50] wip --- .../jotomo/ruffyscripter/RuffyScripter.java | 20 ++++++++ .../ruffyscripter/commands/BolusCommand.java | 46 ++++++++----------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index eabcdbf505..0508335caa 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -450,6 +450,26 @@ public class RuffyScripter { log.debug("Releasing back key"); } + public void pressKeyMs(final byte key, long ms) { + long stepMs = 100; + try { + log.debug("Scroll: Pressing key for " + ms + " ms with step " + stepMs + " ms"); + ruffyService.rtSendKey(key, true); + ruffyService.rtSendKey(key, false); + while (ms > stepMs) { + SystemClock.sleep(stepMs); + ruffyService.rtSendKey(key, false); + ms -= stepMs; + } + SystemClock.sleep(ms); + ruffyService.rtSendKey(Key.NO_KEY, true); + log.debug("Releasing key"); + } catch (Exception e) { + throw new CommandException().exception(e).message("Error while pressing buttons"); + } + } + + public boolean waitForScreenUpdate(long timeout) { synchronized (screenlock) { try { diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index d57b8cbe0d..7d880a9424 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -84,7 +84,7 @@ public class BolusCommand implements Command { progressReportCallback.report(DELIVERING, 0, 0); Double bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); double lastBolusReported = 0; - List alarmsRaised = new ArrayList<>(); + boolean lowCartdrigeAlarmTriggered = false; // wait for bolus delivery to complete; the remaining units to deliver are counted // down and are displayed on the main menu. // TODO extract into method @@ -94,20 +94,19 @@ public class BolusCommand implements Command { while (bolusRemaining != null) { if (cancelRequested) { progressReportCallback.report(STOPPING, 0, 0); - // TODO just press up 3s in a separated thread and let this loop run - // and at the end handle the outcome and returned raise alarms, whether cancel was reuqested etc - - // TODO press up 3s, deal with bolus cancelled error, retrieved amount actually delivered from history and return it - // since the cancellation takes three seconds some insulin will have definitely been delivered (delivery speed is roughly 0.1U/s), - // but the pump may also finish delivering the bolus while we try to cancel it - // so, press a button, keep it press and deal with three outcomes: - // * delivery finished (no more remaining bolus displayed) - // * bolus was cancelled (warning raised) - // * any other error (low cartridge, occlusion, both will also trigger 'bolus cancelled' errors) - // cancelBolusInDelivery() - // TODO new thread to press button and then deal with outcomes below, since all errors can occur at all time, pressing - // abort just forces an error (if keyrpess is in time) + scripter.pressKeyMs(RuffyScripter.Key.UP, 3000); progressReportCallback.report(STOPPED, 0, 0); + // if the bolus finished while we attempted to cancel it, there'll be no alarm + long timeout = System.currentTimeMillis() + 2000; + while (scripter.currentMenu.getType() != MenuType.WARNING_OR_ERROR && System.currentTimeMillis() < timeout) { + SystemClock.sleep(10); + } + while (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { + // TODO make this cleaner, extract method, needed below too + scripter.pressCheckKey(); + SystemClock.sleep(200); + } + break; } if (lastBolusReported != bolusRemaining) { log.debug("Delivering bolus, remaining: " + bolusRemaining); @@ -115,23 +114,12 @@ public class BolusCommand implements Command { progressReportCallback.report(DELIVERING, percentDelivered, bolus - bolusRemaining); lastBolusReported = bolusRemaining; } - // TODO deal with alarms that can arise; an oclussion with raise an oclussion alert as well as a bolus cancelled alert - // occlusion cancels the bolus -> abort routine to report back delivered bolus; - // low cartridge alert lets bolus run out - // also, any other error or warning can occur and we should return in a controlled fashion - - // communicating back what was actually delivered. - // generally: cancel an alert on the pump and raise the error in AAPS? - // letting the alert go off disrupts comms if the user interacts with the pump, - // then we need to schedule a history read in the near future, let thee user know - // the data will be out of sync for a bit. - // how does the dana handle pump errors? has no vibration, but sound i guess - // should this be configurabe? initially? if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { String message = (String) scripter.currentMenu.getAttribute(MenuAttribute.MESSAGE); if (message.equals("LOW CARTRIDGE")) { - alarmsRaised.add(message); - // confirm, note alert was raised and continue bolusing) + lowCartdrigeAlarmTriggered = true; + confirmAlert("LOW CARTRIDGE", 2000); } else { // any other alert break; @@ -141,7 +129,7 @@ public class BolusCommand implements Command { bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); } - // wait up to 2s for any possible warning to be raised + // wait up to 2s for any possible warning to be raised, if not raised already long minWait = System.currentTimeMillis() + 2 * 1000; while (scripter.currentMenu.getType() != MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { SystemClock.sleep(50); @@ -177,6 +165,8 @@ public class BolusCommand implements Command { .message("Bolus was delivered, but unable to confirm it with history record"); } + // TODO check date so we don't pick a false record if the previous bolus had the same amount; + // also, report back partial bolus. Just call ReadHsstory(timestamp, boluses=true) cmd ... double lastBolusInHistory = (double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS); if (Math.abs(bolus - lastBolusInHistory) > 0.05) { throw new CommandException().success(false).enacted(true) From 2eb86e1bd87477d4d8d7e1f219a7d32ded8f712a Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Mon, 21 Aug 2017 18:33:40 +0200 Subject: [PATCH 11/50] wip --- .../main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 7d880a9424..80fd1df285 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -45,6 +45,7 @@ public class BolusCommand implements Command { @Override public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { try { + // TODO read reservoir level and reject request if reservoir < bolus enterBolusMenu(scripter); inputBolusAmount(scripter); verifyDisplayedBolusAmount(scripter); From 04a03dedc317ea54f4b8d2c15242c997bedc477e Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 12:08:03 +0200 Subject: [PATCH 12/50] Extract BaseCommand. --- .../ruffyscripter/commands/BaseCommand.java | 15 +++++++++++++++ .../ruffyscripter/commands/BolusCommand.java | 2 +- .../ruffyscripter/commands/CancelTbrCommand.java | 2 +- .../commands/DetermineCapabilitiesCommand.java | 2 +- .../ruffyscripter/commands/GetBasalCommand.java | 2 +- .../commands/ReadPumpStateCommand.java | 2 +- .../ruffyscripter/commands/SetTbrCommand.java | 2 +- .../ruffyscripter/commands/SetTbrCommandAlt.java | 2 +- 8 files changed, 22 insertions(+), 7 deletions(-) create mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java new file mode 100644 index 0000000000..5f138637f3 --- /dev/null +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java @@ -0,0 +1,15 @@ +package de.jotomo.ruffyscripter.commands; + +import de.jotomo.ruffyscripter.RuffyScripter; + +public abstract class BaseCommand implements Command { + // RS will inject itself here + protected RuffyScripter scripter; + public void setScripter(RuffyScripter scripter) { this.scripter = scripter; } + + // TODO upcoming + protected volatile boolean cancelRequested = false; + public void requestCancellation() { + cancelRequested = true; + } +} diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index d5197452e3..aa0e16b7e7 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -14,7 +14,7 @@ import java.util.Locale; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -public class BolusCommand implements Command { +public class BolusCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(BolusCommand.class); private final double bolus; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java index 2931f1d9d9..761c8fcd47 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java @@ -14,7 +14,7 @@ import info.nightscout.androidaps.MainApp; // TODO robustness: can a TBR run out, whilst we're trying to cancel it? // Hm, we could just ignore TBRs that run out within the next 60s (0:01 or even 0:02 // given we need some time to process the request). -public class CancelTbrCommand implements Command { +public class CancelTbrCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(CancelTbrCommand.class); @Override diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index adc740c13e..2f33287507 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -19,7 +19,7 @@ import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -public class DetermineCapabilitiesCommand implements Command { +public class DetermineCapabilitiesCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(DetermineCapabilitiesCommand.class); public static final int UP_STEPS = 75; public static final int RETRIES = 5; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java index 09958f6bf1..a37e4c2be4 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java @@ -13,7 +13,7 @@ import java.util.Map; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -public class GetBasalCommand implements Command { +public class GetBasalCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(GetBasalCommand.class); private RuffyScripter scripter; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java index 58e52b0a4f..4b4d164133 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java @@ -6,7 +6,7 @@ import java.util.List; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -public class ReadPumpStateCommand implements Command { +public class ReadPumpStateCommand extends BaseCommand { @Override public CommandResult execute(RuffyScripter ruffyScripter, PumpState initialPumpState) { return new CommandResult().success(true).enacted(false).message("Returning pump state only"); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 8af26863f7..4edbf39e33 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -21,7 +21,7 @@ import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_MENU; import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_SET; import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.WARNING_OR_ERROR; -public class SetTbrCommand implements Command { +public class SetTbrCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); private final long percentage; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index 7a9035cfe5..5cc4094403 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -15,7 +15,7 @@ import java.util.Locale; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -public class SetTbrCommandAlt implements Command { +public class SetTbrCommandAlt extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); private final long percentage; From fe7f8314290de9d1bc1e0d1b6764f7b0370acab0 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 12:10:50 +0200 Subject: [PATCH 13/50] Inject scripter into commands. --- app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java | 3 ++- .../java/de/jotomo/ruffyscripter/commands/BaseCommand.java | 2 +- .../java/de/jotomo/ruffyscripter/commands/BolusCommand.java | 2 +- .../de/jotomo/ruffyscripter/commands/CancelTbrCommand.java | 5 ++--- .../main/java/de/jotomo/ruffyscripter/commands/Command.java | 3 ++- .../ruffyscripter/commands/DetermineCapabilitiesCommand.java | 5 +---- .../de/jotomo/ruffyscripter/commands/GetBasalCommand.java | 2 +- .../jotomo/ruffyscripter/commands/ReadPumpStateCommand.java | 3 +-- .../java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java | 2 +- .../de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java | 2 +- 10 files changed, 13 insertions(+), 16 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 3f8a99f665..3d11cf68d7 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -304,7 +304,8 @@ public class RuffyScripter { PumpState pumpState = readPumpState(); log.debug("Pump state before running command: " + pumpState); long cmdStartTime = System.currentTimeMillis(); - returnable.cmdResult = cmd.execute(scripter, pumpState); + cmd.setScripter(scripter); + returnable.cmdResult = cmd.execute(pumpState); long cmdEndTime = System.currentTimeMillis(); returnable.cmdResult.completionTime = cmdEndTime; log.debug("Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms"); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java index 5f138637f3..ab951c9185 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java @@ -5,7 +5,7 @@ import de.jotomo.ruffyscripter.RuffyScripter; public abstract class BaseCommand implements Command { // RS will inject itself here protected RuffyScripter scripter; - public void setScripter(RuffyScripter scripter) { this.scripter = scripter; } + @Override public void setScripter(RuffyScripter scripter) { this.scripter = scripter; } // TODO upcoming protected volatile boolean cancelRequested = false; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index aa0e16b7e7..3eb0b1ba26 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -35,7 +35,7 @@ public class BolusCommand extends BaseCommand { } @Override - public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { try { enterBolusMenu(scripter); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java index 761c8fcd47..047ac56376 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java @@ -8,7 +8,6 @@ import java.util.Collections; import java.util.List; import de.jotomo.ruffyscripter.PumpState; -import de.jotomo.ruffyscripter.RuffyScripter; import info.nightscout.androidaps.MainApp; // TODO robustness: can a TBR run out, whilst we're trying to cancel it? @@ -23,7 +22,7 @@ public class CancelTbrCommand extends BaseCommand { } @Override - public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { try { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); if (!initialPumpState.tbrActive) { @@ -49,7 +48,7 @@ public class CancelTbrCommand extends BaseCommand { } log.debug("Cancelling active TBR of " + initialPumpState.tbrPercent + "% with " + initialPumpState.tbrRemainingDuration + " min remaining"); - return new SetTbrCommand(100, 0).execute(scripter, initialPumpState); + return new SetTbrCommand(100, 0).execute(initialPumpState); } catch (CommandException e) { return e.toCommandResult(); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java index 33d10fc223..6848a2c3f2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java @@ -13,6 +13,7 @@ import de.jotomo.ruffyscripter.RuffyScripter; * sequence, letting the methods take care of waits. */ public interface Command { - CommandResult execute(RuffyScripter ruffyScripter, PumpState initialPumpState); + CommandResult execute(PumpState initialPumpState); List validateArguments(); + void setScripter(RuffyScripter scripter); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index 2f33287507..8eef298154 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -2,8 +2,6 @@ package de.jotomo.ruffyscripter.commands; import android.os.SystemClock; -import com.j256.ormlite.stmt.query.In; - import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; @@ -12,7 +10,6 @@ import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; -import java.util.Locale; import de.jotomo.ruffyscripter.PumpCapabilities; import de.jotomo.ruffyscripter.PumpState; @@ -30,7 +27,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { } @Override - public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { try { //read main menu 100% or TBR? Read remaining duration. diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java index a37e4c2be4..b8b451b901 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java @@ -102,7 +102,7 @@ public class GetBasalCommand extends BaseCommand { // } // } @Override - public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { try { Map rate = new HashMap<>(); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java index 4b4d164133..c346661c74 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java @@ -4,11 +4,10 @@ import java.util.Collections; import java.util.List; import de.jotomo.ruffyscripter.PumpState; -import de.jotomo.ruffyscripter.RuffyScripter; public class ReadPumpStateCommand extends BaseCommand { @Override - public CommandResult execute(RuffyScripter ruffyScripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { return new CommandResult().success(true).enacted(false).message("Returning pump state only"); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 4edbf39e33..38164cc116 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -60,7 +60,7 @@ public class SetTbrCommand extends BaseCommand { } @Override - public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { try { log.debug("1. going from " + scripter.currentMenu + " to TBR_MENU"); int retries = 5; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index 5cc4094403..45f589c173 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -54,7 +54,7 @@ public class SetTbrCommandAlt extends BaseCommand { } @Override - public CommandResult execute(RuffyScripter scripter, PumpState initialPumpState) { + public CommandResult execute(PumpState initialPumpState) { try { enterTbrMenu(scripter); inputTbrPercentage(scripter); From 3238cf9c35c5ab156e455fe2c011605205e26ff8 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 12:13:52 +0200 Subject: [PATCH 14/50] Remove pumpState arg from Command.execute. --- .../java/de/jotomo/ruffyscripter/RuffyScripter.java | 4 ++-- .../jotomo/ruffyscripter/commands/BolusCommand.java | 3 +-- .../ruffyscripter/commands/CancelTbrCommand.java | 11 ++++++----- .../de/jotomo/ruffyscripter/commands/Command.java | 3 +-- .../commands/DetermineCapabilitiesCommand.java | 3 +-- .../ruffyscripter/commands/GetBasalCommand.java | 3 +-- .../ruffyscripter/commands/ReadPumpStateCommand.java | 4 +--- .../jotomo/ruffyscripter/commands/SetTbrCommand.java | 3 +-- .../ruffyscripter/commands/SetTbrCommandAlt.java | 3 +-- 9 files changed, 15 insertions(+), 22 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 3d11cf68d7..460743ab7e 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -305,7 +305,7 @@ public class RuffyScripter { log.debug("Pump state before running command: " + pumpState); long cmdStartTime = System.currentTimeMillis(); cmd.setScripter(scripter); - returnable.cmdResult = cmd.execute(pumpState); + returnable.cmdResult = cmd.execute(); long cmdEndTime = System.currentTimeMillis(); returnable.cmdResult.completionTime = cmdEndTime; log.debug("Executing " + cmd + " took " + (cmdEndTime - cmdStartTime) + "ms"); @@ -602,7 +602,7 @@ public class RuffyScripter { /** This reads the state of the, which is whatever is currently displayed on the display, * no actions are performed. */ - private PumpState readPumpState() { + public PumpState readPumpState() { PumpState state = new PumpState(); Menu menu = currentMenu; if (menu == null) { diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 3eb0b1ba26..944da9b585 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -11,7 +11,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; public class BolusCommand extends BaseCommand { @@ -35,7 +34,7 @@ public class BolusCommand extends BaseCommand { } @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { try { enterBolusMenu(scripter); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java index 047ac56376..9ad4aae940 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java @@ -22,10 +22,11 @@ public class CancelTbrCommand extends BaseCommand { } @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { try { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if (!initialPumpState.tbrActive) { + PumpState pumpState = scripter.readPumpState(); + if (!pumpState.tbrActive) { log.debug("active temp basal 90s ago: " + MainApp.getConfigBuilder().getTempBasalFromHistory(System.currentTimeMillis() - 90 * 1000)); log.debug("active temp basal 60s ago: " + @@ -46,9 +47,9 @@ public class CancelTbrCommand extends BaseCommand { .enacted(true) .message("No TBR active"); } - log.debug("Cancelling active TBR of " + initialPumpState.tbrPercent - + "% with " + initialPumpState.tbrRemainingDuration + " min remaining"); - return new SetTbrCommand(100, 0).execute(initialPumpState); + log.debug("Cancelling active TBR of " + pumpState.tbrPercent + + "% with " + pumpState.tbrRemainingDuration + " min remaining"); + return new SetTbrCommand(100, 0).execute(); } catch (CommandException e) { return e.toCommandResult(); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java index 6848a2c3f2..e472d56fa9 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/Command.java @@ -2,7 +2,6 @@ package de.jotomo.ruffyscripter.commands; import java.util.List; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; /** @@ -13,7 +12,7 @@ import de.jotomo.ruffyscripter.RuffyScripter; * sequence, letting the methods take care of waits. */ public interface Command { - CommandResult execute(PumpState initialPumpState); + CommandResult execute(); List validateArguments(); void setScripter(RuffyScripter scripter); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index 8eef298154..502b472fbc 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -12,7 +12,6 @@ import java.util.Collections; import java.util.List; import de.jotomo.ruffyscripter.PumpCapabilities; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; @@ -27,7 +26,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { } @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { try { //read main menu 100% or TBR? Read remaining duration. diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java index b8b451b901..f69012ff29 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java @@ -10,7 +10,6 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; public class GetBasalCommand extends BaseCommand { @@ -102,7 +101,7 @@ public class GetBasalCommand extends BaseCommand { // } // } @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { try { Map rate = new HashMap<>(); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java index c346661c74..06ae717633 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java @@ -3,11 +3,9 @@ package de.jotomo.ruffyscripter.commands; import java.util.Collections; import java.util.List; -import de.jotomo.ruffyscripter.PumpState; - public class ReadPumpStateCommand extends BaseCommand { @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { return new CommandResult().success(true).enacted(false).message("Returning pump state only"); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 38164cc116..efe61a4897 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.MAIN_MENU; @@ -60,7 +59,7 @@ public class SetTbrCommand extends BaseCommand { } @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { try { log.debug("1. going from " + scripter.currentMenu + " to TBR_MENU"); int retries = 5; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index 45f589c173..c42630f2a6 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -12,7 +12,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; public class SetTbrCommandAlt extends BaseCommand { @@ -54,7 +53,7 @@ public class SetTbrCommandAlt extends BaseCommand { } @Override - public CommandResult execute(PumpState initialPumpState) { + public CommandResult execute() { try { enterTbrMenu(scripter); inputTbrPercentage(scripter); From 7537048a96d583dacdde23ac2c1d55fcf7196c7d Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 12:36:19 +0200 Subject: [PATCH 15/50] Finish injecting scripter. --- .../ruffyscripter/commands/BolusCommand.java | 18 +++---- .../DetermineCapabilitiesCommand.java | 28 +++++------ .../commands/SetTbrCommandAlt.java | 50 +++++++++---------- 3 files changed, 48 insertions(+), 48 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 944da9b585..4424b964f4 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -36,10 +36,10 @@ public class BolusCommand extends BaseCommand { @Override public CommandResult execute() { try { - enterBolusMenu(scripter); + enterBolusMenu(); - inputBolusAmount(scripter); - verifyDisplayedBolusAmount(scripter); + inputBolusAmount(); + verifyDisplayedBolusAmount(); // confirm bolus scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); @@ -105,7 +105,7 @@ public class BolusCommand extends BaseCommand { } } - private void enterBolusMenu(RuffyScripter scripter) { + private void enterBolusMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); scripter.navigateToMenu(MenuType.BOLUS_MENU); scripter.verifyMenuIsDisplayed(MenuType.BOLUS_MENU); @@ -114,7 +114,7 @@ public class BolusCommand extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); } - private void inputBolusAmount(RuffyScripter scripter) { + private void inputBolusAmount() { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); // press 'up' once for each 0.1 U increment long steps = Math.round(bolus * 10); @@ -128,9 +128,9 @@ public class BolusCommand extends BaseCommand { SystemClock.sleep(2000); } - private void verifyDisplayedBolusAmount(RuffyScripter scripter) { + private void verifyDisplayedBolusAmount() { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); - double displayedBolus = readDisplayedBolusAmount(scripter); + double displayedBolus = readDisplayedBolusAmount(); log.debug("Final bolus: " + displayedBolus); if (Math.abs(displayedBolus - bolus) > 0.05) { throw new CommandException().message("Failed to set correct bolus. Expected: " + bolus + ", actual: " + displayedBolus); @@ -138,14 +138,14 @@ public class BolusCommand extends BaseCommand { // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); - double refreshedDisplayedBolus = readDisplayedBolusAmount(scripter); + double refreshedDisplayedBolus = readDisplayedBolusAmount(); if (Math.abs(displayedBolus - refreshedDisplayedBolus) > 0.05) { throw new CommandException().message("Failed to set bolus: bolus changed after input stopped from " + displayedBolus + " -> " + refreshedDisplayedBolus); } } - private double readDisplayedBolusAmount(RuffyScripter scripter) { + private double readDisplayedBolusAmount() { // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); // bolus amount is blinking, so we need to make sure we catch it at the right moment diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index 502b472fbc..ad2ed1a551 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -30,11 +30,11 @@ public class DetermineCapabilitiesCommand extends BaseCommand { try { //read main menu 100% or TBR? Read remaining duration. - long durationBefore = readDisplayedTbrDurationMainMenu(scripter); - long percentageBefore = readDisplayedTbrPercentageMainMenu(scripter); + long durationBefore = readDisplayedTbrDurationMainMenu(); + long percentageBefore = readDisplayedTbrPercentageMainMenu(); - enterTbrMenu(scripter); - long maxTbrPercentage = findMaxTbrPercentage(scripter); + enterTbrMenu(); + long maxTbrPercentage = findMaxTbrPercentage(); // TODO v2 this can probably be removed by now SystemClock.sleep(750); @@ -45,8 +45,8 @@ public class DetermineCapabilitiesCommand extends BaseCommand { //TODO: check if TBR is still the same or duration was less than 5 minutes - long durationAfter = readDisplayedTbrDurationMainMenu(scripter); - long percentageAfter = readDisplayedTbrPercentageMainMenu(scripter); + long durationAfter = readDisplayedTbrDurationMainMenu(); + long percentageAfter = readDisplayedTbrPercentageMainMenu(); if(Math.abs(durationBefore-durationAfter) > 5){ throw new CommandException().message("Duration jump during DetermineCapabilities"); @@ -65,7 +65,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { } } - private void enterTbrMenu(RuffyScripter scripter) { + private void enterTbrMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); scripter.navigateToMenu(MenuType.TBR_MENU); scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU); @@ -74,9 +74,9 @@ public class DetermineCapabilitiesCommand extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); } - private long findMaxTbrPercentage(RuffyScripter scripter) { + private long findMaxTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long activeTempBasal = readDisplayedTbrPercentage(scripter); + long activeTempBasal = readDisplayedTbrPercentage(); // pretend to increase the TBR to more than 500% log.debug("Pressing up " + UP_STEPS + " times to get to maximum"); @@ -89,7 +89,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { //read the displayed maximum value scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long maximumTempBasal = readDisplayedTbrPercentage(scripter); + long maximumTempBasal = readDisplayedTbrPercentage(); //reset the TBR in a controlled manner long percentageChange = maximumTempBasal - activeTempBasal; @@ -106,7 +106,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { } //do the rest if button-presses failed. scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long currentPercentage = readDisplayedTbrPercentage(scripter); + long currentPercentage = readDisplayedTbrPercentage(); percentageChange = currentPercentage - activeTempBasal; percentageSteps = percentageChange / 10; retries++; @@ -120,7 +120,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { } - private long readDisplayedTbrPercentage(RuffyScripter scripter) { + private long readDisplayedTbrPercentage() { SystemClock.sleep(1000); // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); @@ -133,7 +133,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { return ((Double) percentageObj).longValue(); } - private int readDisplayedTbrDurationMainMenu(RuffyScripter scripter) { + private int readDisplayedTbrDurationMainMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); if(scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)){ // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded @@ -145,7 +145,7 @@ public class DetermineCapabilitiesCommand extends BaseCommand { } } - private int readDisplayedTbrPercentageMainMenu(RuffyScripter scripter) { + private int readDisplayedTbrPercentageMainMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); if(scripter.currentMenu.attributes().contains(MenuAttribute.TBR)){ return (int)((Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR)).doubleValue(); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index c42630f2a6..151a78cc7a 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -55,12 +55,12 @@ public class SetTbrCommandAlt extends BaseCommand { @Override public CommandResult execute() { try { - enterTbrMenu(scripter); - inputTbrPercentage(scripter); - verifyDisplayedTbrPercentage(scripter); + enterTbrMenu(); + inputTbrPercentage(); + verifyDisplayedTbrPercentage(); if (percentage == 100) { - cancelTbrAndConfirmCancellationWarning(scripter); + cancelTbrAndConfirmCancellationWarning(); } else { // switch to TBR_DURATION menu by pressing menu key scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); @@ -68,8 +68,8 @@ public class SetTbrCommandAlt extends BaseCommand { scripter.waitForMenuUpdate(); scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - inputTbrDuration(scripter); - verifyDisplayedTbrDuration(scripter); + inputTbrDuration(); + verifyDisplayedTbrDuration(); // confirm TBR scripter.pressCheckKey(); @@ -82,10 +82,10 @@ public class SetTbrCommandAlt extends BaseCommand { // check main menu shows the same values we just set if (percentage == 100) { - verifyMainMenuShowsNoActiveTbr(scripter); + verifyMainMenuShowsNoActiveTbr(); return new CommandResult().success(true).enacted(true).message("TBR was cancelled"); } else { - verifyMainMenuShowsExpectedTbrActive(scripter); + verifyMainMenuShowsExpectedTbrActive(); return new CommandResult().success(true).enacted(true).message( String.format(Locale.US, "TBR set to %d%% for %d min", percentage, duration)); } @@ -95,7 +95,7 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private void enterTbrMenu(RuffyScripter scripter) { + private void enterTbrMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); scripter.navigateToMenu(MenuType.TBR_MENU); scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU); @@ -104,9 +104,9 @@ public class SetTbrCommandAlt extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); } - private void inputTbrPercentage(RuffyScripter scripter) { + private void inputTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long currentPercent = readDisplayedTbrPercentage(scripter); + long currentPercent = readDisplayedTbrPercentage(); log.debug("Current TBR %: " + currentPercent); long percentageChange = percentage - currentPercent; long percentageSteps = percentageChange / 10; @@ -128,9 +128,9 @@ public class SetTbrCommandAlt extends BaseCommand { SystemClock.sleep(2000); } - private void verifyDisplayedTbrPercentage(RuffyScripter scripter) { + private void verifyDisplayedTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long displayedPercentage = readDisplayedTbrPercentage(scripter); + long displayedPercentage = readDisplayedTbrPercentage(); if (displayedPercentage != percentage) { log.debug("Final displayed TBR percentage: " + displayedPercentage); throw new CommandException().message("Failed to set TBR percentage"); @@ -138,7 +138,7 @@ public class SetTbrCommandAlt extends BaseCommand { // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); - long refreshedDisplayedTbrPecentage = readDisplayedTbrPercentage(scripter); + long refreshedDisplayedTbrPecentage = readDisplayedTbrPercentage(); if (displayedPercentage != refreshedDisplayedTbrPecentage) { throw new CommandException().message("Failed to set TBR percentage: " + "percentage changed after input stopped from " @@ -146,7 +146,7 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private long readDisplayedTbrPercentage(RuffyScripter scripter) { + private long readDisplayedTbrPercentage() { // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); // this as a bit hacky, the display value is blinking, so we might catch that, so @@ -158,9 +158,9 @@ public class SetTbrCommandAlt extends BaseCommand { return ((Double) percentageObj).longValue(); } - private void inputTbrDuration(RuffyScripter scripter) { + private void inputTbrDuration() { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long currentDuration = readDisplayedTbrDuration(scripter); + long currentDuration = readDisplayedTbrDuration(); if (currentDuration % 15 != 0) { // The duration displayed is how long an active TBR will still run, // which might be something like 0:13, hence not in 15 minute steps. @@ -170,7 +170,7 @@ public class SetTbrCommandAlt extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); scripter.pressUpKey(); scripter.waitForMenuUpdate(); - currentDuration = readDisplayedTbrDuration(scripter); + currentDuration = readDisplayedTbrDuration(); } log.debug("Current TBR duration: " + currentDuration); long durationChange = duration - currentDuration; @@ -193,9 +193,9 @@ public class SetTbrCommandAlt extends BaseCommand { SystemClock.sleep(2000); } - private void verifyDisplayedTbrDuration(RuffyScripter scripter) { + private void verifyDisplayedTbrDuration() { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long displayedDuration = readDisplayedTbrDuration(scripter); + long displayedDuration = readDisplayedTbrDuration(); if (displayedDuration != duration) { log.debug("Final displayed TBR duration: " + displayedDuration); throw new CommandException().message("Failed to set TBR duration"); @@ -203,7 +203,7 @@ public class SetTbrCommandAlt extends BaseCommand { // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); - long refreshedDisplayedTbrDuration = readDisplayedTbrDuration(scripter); + long refreshedDisplayedTbrDuration = readDisplayedTbrDuration(); if (displayedDuration != refreshedDisplayedTbrDuration) { throw new CommandException().message("Failed to set TBR duration: " + "duration changed after input stopped from " @@ -211,7 +211,7 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private long readDisplayedTbrDuration(RuffyScripter scripter) { + private long readDisplayedTbrDuration() { // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); @@ -225,7 +225,7 @@ public class SetTbrCommandAlt extends BaseCommand { return duration.getHour() * 60 + duration.getMinute(); } - private void cancelTbrAndConfirmCancellationWarning(RuffyScripter scripter) { + private void cancelTbrAndConfirmCancellationWarning() { // confirm entered TBR scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); scripter.pressCheckKey(); @@ -264,7 +264,7 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private void verifyMainMenuShowsNoActiveTbr(RuffyScripter scripter) { + private void verifyMainMenuShowsNoActiveTbr() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); Double tbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR); boolean runtimeDisplayed = scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME); @@ -273,7 +273,7 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private void verifyMainMenuShowsExpectedTbrActive(RuffyScripter scripter) { + private void verifyMainMenuShowsExpectedTbrActive() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); // new TBR set; percentage and duration must be displayed ... if (!scripter.currentMenu.attributes().contains(MenuAttribute.TBR) || From 785a01a056ed76b90eb8acd41b50eab06f75894c Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 13:02:49 +0200 Subject: [PATCH 16/50] Extract methods to read blinking values. --- .../jotomo/ruffyscripter/RuffyScripter.java | 20 ++++ .../ruffyscripter/commands/BaseCommand.java | 2 + .../ruffyscripter/commands/BolusCommand.java | 17 +--- .../ruffyscripter/commands/SetTbrCommand.java | 91 ++++++------------- .../commands/SetTbrCommandAlt.java | 44 ++------- 5 files changed, 63 insertions(+), 111 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 460743ab7e..de1694f639 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -597,6 +597,26 @@ public class RuffyScripter { } } + @SuppressWarnings("unchecked") + public T readBlinkingValue(Class expectedType, MenuAttribute attribute) { + int retries = 5; + Object value = currentMenu.getAttribute(attribute); + while (!value.getClass().isAssignableFrom(expectedType.getClass())) { + value = currentMenu.getAttribute(attribute); + waitForScreenUpdate(1000); + retries--; + if (retries == 0) { + throw new CommandException().message("Failed to read blinkng value: " + attribute); + } + } + return (T) value; + } + + public long readDisplayedDuration() { + MenuTime duration = readBlinkingValue(MenuTime.class, MenuAttribute.RUNTIME); + return duration.getHour() * 60 + duration.getMinute(); + } + // TODO v2 add remaining info we can extract from the main menu, low battery and low // cartridge warnings, running extended bolus (how does that look if a TBR is active as well?) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java index ab951c9185..0e83f0c1a1 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BaseCommand.java @@ -8,8 +8,10 @@ public abstract class BaseCommand implements Command { @Override public void setScripter(RuffyScripter scripter) { this.scripter = scripter; } // TODO upcoming + protected final boolean canBeCancelled = true; protected volatile boolean cancelRequested = false; public void requestCancellation() { cancelRequested = true; } + public boolean isCancellable() { return canBeCancelled; } } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 4424b964f4..947d31ed6b 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -130,7 +130,7 @@ public class BolusCommand extends BaseCommand { private void verifyDisplayedBolusAmount() { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); - double displayedBolus = readDisplayedBolusAmount(); + double displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); log.debug("Final bolus: " + displayedBolus); if (Math.abs(displayedBolus - bolus) > 0.05) { throw new CommandException().message("Failed to set correct bolus. Expected: " + bolus + ", actual: " + displayedBolus); @@ -138,25 +138,14 @@ public class BolusCommand extends BaseCommand { // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); - double refreshedDisplayedBolus = readDisplayedBolusAmount(); + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + double refreshedDisplayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); if (Math.abs(displayedBolus - refreshedDisplayedBolus) > 0.05) { throw new CommandException().message("Failed to set bolus: bolus changed after input stopped from " + displayedBolus + " -> " + refreshedDisplayedBolus); } } - private double readDisplayedBolusAmount() { - // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); - // bolus amount is blinking, so we need to make sure we catch it at the right moment - Object amountObj = scripter.currentMenu.getAttribute(MenuAttribute.BOLUS); - while (!(amountObj instanceof Double)) { - scripter.waitForMenuUpdate(); - amountObj = scripter.currentMenu.getAttribute(MenuAttribute.BOLUS); - } - return (double) amountObj; - } - @Override public String toString() { return "BolusCommand{" + diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index efe61a4897..6a494e34ff 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -93,25 +93,17 @@ public class SetTbrCommand extends BaseCommand { log.debug("SetTbrCommand: 3. getting/setting basal percentage in " + scripter.currentMenu); retries = 30; - double currentPercentage = -100; + double currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); while (currentPercentage != percentage && retries >= 0) { retries--; - Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); - - if (percentageObj != null && (percentageObj instanceof Double)) { - currentPercentage = ((Double) percentageObj).doubleValue(); - - if (currentPercentage != percentage) { - int requestedPercentage = (int) percentage; - int actualPercentage = (int) currentPercentage; - int steps = (requestedPercentage - actualPercentage) / 10; - log.debug("Adjusting basal(" + requestedPercentage + "/" + actualPercentage + ") with " + steps + " steps and " + retries + " retries left"); - scripter.step(steps, (steps < 0 ? RuffyScripter.Key.DOWN : RuffyScripter.Key.UP), 500); - scripter.waitForScreenUpdate(1000); - } - - } else { - currentPercentage = -100; + currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); + if (currentPercentage != percentage) { + int requestedPercentage = (int) percentage; + int actualPercentage = (int) currentPercentage; + int steps = (requestedPercentage - actualPercentage) / 10; + log.debug("Adjusting basal(" + requestedPercentage + "/" + actualPercentage + ") with " + steps + " steps and " + retries + " retries left"); + scripter.step(steps, (steps < 0 ? RuffyScripter.Key.DOWN : RuffyScripter.Key.UP), 500); + scripter.waitForScreenUpdate(1000); } scripter.waitForScreenUpdate(1000); } @@ -120,20 +112,8 @@ public class SetTbrCommand extends BaseCommand { log.debug("4. checking basal percentage in " + scripter.currentMenu); scripter.waitForScreenUpdate(1000); - currentPercentage = -1000; - retries = 10; - while (currentPercentage < 0 && retries >= 0) { - retries--; - Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); - - if (percentageObj != null && (percentageObj instanceof Double)) { - currentPercentage = ((Double) percentageObj).doubleValue(); - } else { - scripter.waitForScreenUpdate(1000); - } - } - - if (retries < 0 || currentPercentage != percentage) + currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); + if (currentPercentage != percentage) throw new CommandException().message("Unable to set percentage. Requested: " + percentage + ", value displayed on pump: " + currentPercentage); if (currentPercentage != 100) { @@ -155,47 +135,31 @@ public class SetTbrCommand extends BaseCommand { log.debug("6. getting/setting duration in " + scripter.currentMenu); retries = 30; - double currentDuration = -100; + double currentDuration = scripter.readDisplayedDuration(); while (currentDuration != duration && retries >= 0) { retries--; - Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); - log.debug("Requested time: " + duration + " actual time: " + durationObj); - if (durationObj != null && durationObj instanceof MenuTime) { - MenuTime time = (MenuTime) durationObj; - currentDuration = (time.getHour() * 60) + time.getMinute(); - if (currentDuration != duration) { - int requestedDuration = (int) duration; - int actualDuration = (int) currentDuration; - int steps = (requestedDuration - actualDuration) / 15; - if (currentDuration + (steps * 15) < requestedDuration) - steps++; - else if (currentDuration + (steps * 15) > requestedDuration) - steps--; - log.debug("Adjusting duration(" + requestedDuration + "/" + actualDuration + ") with " + steps + " steps and " + retries + " retries left"); - scripter.step(steps, (steps > 0 ? RuffyScripter.Key.UP : RuffyScripter.Key.DOWN), 500); - scripter.waitForScreenUpdate(1000); - } + currentDuration = scripter.readDisplayedDuration(); + log.debug("Requested time: " + duration + " actual time: " + currentDuration); + if (currentDuration != duration) { + int requestedDuration = (int) duration; + int actualDuration = (int) currentDuration; + int steps = (requestedDuration - actualDuration) / 15; + if (currentDuration + (steps * 15) < requestedDuration) + steps++; + else if (currentDuration + (steps * 15) > requestedDuration) + steps--; + log.debug("Adjusting duration(" + requestedDuration + "/" + actualDuration + ") with " + steps + " steps and " + retries + " retries left"); + scripter.step(steps, (steps > 0 ? RuffyScripter.Key.UP : RuffyScripter.Key.DOWN), 500); + scripter.waitForScreenUpdate(1000); } - scripter.waitForScreenUpdate(1000); } if (currentDuration < 0 || retries < 0) throw new CommandException().message("unable to set duration, requested:" + duration + ", displayed on pump: " + currentDuration); log.debug("7. checking duration in " + scripter.currentMenu); scripter.waitForScreenUpdate(1000); - currentDuration = -1000; - retries = 10; - while (currentDuration < 0 && retries >= 0) { - retries--; - Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); - - if (durationObj != null && durationObj instanceof MenuTime) { - MenuTime time = (MenuTime) durationObj; - currentDuration = (time.getHour() * 60) + time.getMinute(); - } else - scripter.waitForScreenUpdate(1000); - } - if (retries < 0 || currentDuration != duration) + currentDuration = scripter.readDisplayedDuration(); + if (currentDuration != duration) throw new CommandException().message("wrong duration! Requested: " + duration + ", displayed on pump: " + currentDuration); } @@ -216,6 +180,7 @@ public class SetTbrCommand extends BaseCommand { // TODO how probable is it, that a totally unrelated error (like occlusion alert) // is raised at this point, which we'd cancel together with the TBR cancelled alert? if (percentage == 100 && scripter.currentMenu.getType() == WARNING_OR_ERROR) { + // TODO extract method confirmAlert(alert) scripter.pressCheckKey(); retries++; cancelledError = true; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index 151a78cc7a..2ad5985dfc 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -12,8 +12,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.RuffyScripter; - public class SetTbrCommandAlt extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); @@ -106,7 +104,7 @@ public class SetTbrCommandAlt extends BaseCommand { private void inputTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long currentPercent = readDisplayedTbrPercentage(); + long currentPercent = scripter.readBlinkingValue(Long.class, MenuAttribute.BASAL_RATE); log.debug("Current TBR %: " + currentPercent); long percentageChange = percentage - currentPercent; long percentageSteps = percentageChange / 10; @@ -130,7 +128,7 @@ public class SetTbrCommandAlt extends BaseCommand { private void verifyDisplayedTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long displayedPercentage = readDisplayedTbrPercentage(); + long displayedPercentage = scripter.readBlinkingValue(Long.class, MenuAttribute.BASAL_RATE); if (displayedPercentage != percentage) { log.debug("Final displayed TBR percentage: " + displayedPercentage); throw new CommandException().message("Failed to set TBR percentage"); @@ -138,7 +136,8 @@ public class SetTbrCommandAlt extends BaseCommand { // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); - long refreshedDisplayedTbrPecentage = readDisplayedTbrPercentage(); + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + long refreshedDisplayedTbrPecentage = scripter.readBlinkingValue(Long.class, MenuAttribute.BASAL_RATE); if (displayedPercentage != refreshedDisplayedTbrPecentage) { throw new CommandException().message("Failed to set TBR percentage: " + "percentage changed after input stopped from " @@ -146,21 +145,9 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private long readDisplayedTbrPercentage() { - // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); - // this as a bit hacky, the display value is blinking, so we might catch that, so - // keep trying till we get the Double we want - while (!(percentageObj instanceof Double)) { - scripter.waitForMenuUpdate(); - percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); - } - return ((Double) percentageObj).longValue(); - } - private void inputTbrDuration() { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long currentDuration = readDisplayedTbrDuration(); + long currentDuration = scripter.readDisplayedDuration(); if (currentDuration % 15 != 0) { // The duration displayed is how long an active TBR will still run, // which might be something like 0:13, hence not in 15 minute steps. @@ -170,7 +157,7 @@ public class SetTbrCommandAlt extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); scripter.pressUpKey(); scripter.waitForMenuUpdate(); - currentDuration = readDisplayedTbrDuration(); + currentDuration = scripter.readDisplayedDuration(); } log.debug("Current TBR duration: " + currentDuration); long durationChange = duration - currentDuration; @@ -195,7 +182,7 @@ public class SetTbrCommandAlt extends BaseCommand { private void verifyDisplayedTbrDuration() { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long displayedDuration = readDisplayedTbrDuration(); + long displayedDuration = scripter.readDisplayedDuration(); if (displayedDuration != duration) { log.debug("Final displayed TBR duration: " + displayedDuration); throw new CommandException().message("Failed to set TBR duration"); @@ -203,7 +190,8 @@ public class SetTbrCommandAlt extends BaseCommand { // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); - long refreshedDisplayedTbrDuration = readDisplayedTbrDuration(); + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + long refreshedDisplayedTbrDuration = scripter.readDisplayedDuration(); if (displayedDuration != refreshedDisplayedTbrDuration) { throw new CommandException().message("Failed to set TBR duration: " + "duration changed after input stopped from " @@ -211,19 +199,7 @@ public class SetTbrCommandAlt extends BaseCommand { } } - private long readDisplayedTbrDuration() { - // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); - // this as a bit hacky, the display value is blinking, so we might catch that, so - // keep trying till we get the Double we want - while (!(durationObj instanceof MenuTime)) { - scripter.waitForMenuUpdate(); - durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); - } - MenuTime duration = (MenuTime) durationObj; - return duration.getHour() * 60 + duration.getMinute(); - } + private void cancelTbrAndConfirmCancellationWarning() { // confirm entered TBR From de693c0f7636a63d4c3bc9b2de0a04f0de0f3df7 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 13:08:22 +0200 Subject: [PATCH 17/50] Add reservoirLevel to PumpState. --- .../de/jotomo/ruffyscripter/PumpState.java | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java b/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java index 4d519b4669..f40f542e4f 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/PumpState.java @@ -20,7 +20,8 @@ public class PumpState { public String errorMsg; public boolean suspended; public boolean lowBattery; - public int insulinState; + public int insulinState = -1; + public int reservoirLevel = -1; public PumpState tbrActive(boolean tbrActive) { this.tbrActive = tbrActive; @@ -52,6 +53,21 @@ public class PumpState { return this; } + public PumpState lowBattery(boolean lowBattery) { + this.lowBattery = lowBattery; + return this; + } + + public PumpState insulinState(int insulinState) { + this.insulinState = insulinState; + return this; + } + + public PumpState reservoirLevel(int reservoirLevel) { + this.reservoirLevel = reservoirLevel; + return this; + } + @Override public String toString() { return "PumpState{" + @@ -63,6 +79,7 @@ public class PumpState { ", suspended=" + suspended + ", lowBattery=" + lowBattery + ", insulinState=" + insulinState + + ", reversoirLevel=" + reservoirLevel + ", timestamp=" + timestamp + '}'; } From 9349662f8e99cbde2cb21a4d37a0e62d22940f84 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 13:09:09 +0200 Subject: [PATCH 18/50] Rename ReadPumpStateCommand -> GetPumpStateCommand. --- .../java/ruffyscripter/RuffyScripterInstrumentedTest.java | 4 ++-- .../main/java/de/jotomo/ruffyscripter/RuffyScripter.java | 8 ++++---- ...ReadPumpStateCommand.java => GetPumpStateCommand.java} | 4 ++-- .../androidaps/plugins/PumpCombo/ComboPlugin.java | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) rename app/src/main/java/de/jotomo/ruffyscripter/commands/{ReadPumpStateCommand.java => GetPumpStateCommand.java} (81%) diff --git a/app/src/androidTest/java/ruffyscripter/RuffyScripterInstrumentedTest.java b/app/src/androidTest/java/ruffyscripter/RuffyScripterInstrumentedTest.java index afc17ff868..894eb292b4 100644 --- a/app/src/androidTest/java/ruffyscripter/RuffyScripterInstrumentedTest.java +++ b/app/src/androidTest/java/ruffyscripter/RuffyScripterInstrumentedTest.java @@ -19,7 +19,7 @@ import org.slf4j.LoggerFactory; import de.jotomo.ruffyscripter.RuffyScripter; import de.jotomo.ruffyscripter.commands.CommandResult; -import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; +import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; import static junit.framework.Assert.assertFalse; import static junit.framework.Assert.assertNotNull; @@ -99,7 +99,7 @@ public class RuffyScripterInstrumentedTest { // TODO now, how to get ruffy fired up in this test? @Test public void readPumpState() throws Exception { - CommandResult commandResult = ruffyScripter.runCommand(new ReadPumpStateCommand()); + CommandResult commandResult = ruffyScripter.runCommand(new GetPumpStateCommand()); assertTrue(commandResult.success); assertFalse(commandResult.enacted); assertNotNull(commandResult.state); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index de1694f639..54b4094f68 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -19,7 +19,7 @@ import java.util.List; import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandException; import de.jotomo.ruffyscripter.commands.CommandResult; -import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; +import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; // TODO regularly read "My data" history (boluses, TBR) to double check all commands ran successfully. // Automatically compare against AAPS db, or log all requests in the PumpInterface (maybe Milos @@ -275,7 +275,7 @@ public class RuffyScripter { return; } } - // Except for ReadPumpStateCommand: fail on all requests if the pump is suspended. + // Except for GetPumpStateCommand: fail on all requests if the pump is suspended. // All trickery of not executing but returning success, so that AAPS can non-sensically TBR away when suspended // are dangerous in the current model where commands are dispatched without checking state beforehand, so // the above tactic would result in boluses not being applied and no warning being raised. @@ -285,7 +285,7 @@ public class RuffyScripter { // esp. with AAPS). // So, for v1, just check the pump is not suspended before executing commands and raising an error for all - // but the ReadPumpStateCommand. For v2, we'll have to come up with a better idea how to deal with the pump's + // but the GetPumpStateCommand. For v2, we'll have to come up with a better idea how to deal with the pump's // state. Maybe having read-only commands and write/treatment commands treated differently, or maybe // build an abstraction on top of the commands, so that e.g. a method on RuffyScripter encapsulates checking // pre-condititions, running one or several commands, checking-post conditions and what not. @@ -293,7 +293,7 @@ public class RuffyScripter { // level to handle state and logic. // For now, when changing cartridges and such: tell AAPS to stop the loop, change cartridge and resume the loop. if (currentMenu == null || currentMenu.getType() == MenuType.STOP) { - if (cmd instanceof ReadPumpStateCommand) { + if (cmd instanceof GetPumpStateCommand) { returnable.cmdResult = new CommandResult().success(true).enacted(false); } else { returnable.cmdResult = new CommandResult().success(false).enacted(false).message("Pump is suspended"); diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java similarity index 81% rename from app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java rename to app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java index 06ae717633..567685e2af 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/ReadPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java @@ -3,7 +3,7 @@ package de.jotomo.ruffyscripter.commands; import java.util.Collections; import java.util.List; -public class ReadPumpStateCommand extends BaseCommand { +public class GetPumpStateCommand extends BaseCommand { @Override public CommandResult execute() { return new CommandResult().success(true).enacted(false).message("Returning pump state only"); @@ -16,6 +16,6 @@ public class ReadPumpStateCommand extends BaseCommand { @Override public String toString() { - return "ReadPumpStateCommand{}"; + return "GetPumpStateCommand{}"; } } 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 2f61f95e80..e46fd67c10 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 @@ -32,7 +32,7 @@ import de.jotomo.ruffyscripter.commands.CancelTbrCommand; import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandResult; import de.jotomo.ruffyscripter.commands.DetermineCapabilitiesCommand; -import de.jotomo.ruffyscripter.commands.ReadPumpStateCommand; +import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommandAlt; import info.nightscout.androidaps.BuildConfig; @@ -348,7 +348,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { if (notAUserRequest && wasRunAtLeastOnce && ranWithinTheLastMinute) { log.debug("Not fetching state from pump, since we did already within the last 60 seconds"); } else { - runCommand(new ReadPumpStateCommand()); + runCommand(new GetPumpStateCommand()); } } From 6b19759a9fb29a012a36d26409a32218fd00e304 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 13:19:51 +0200 Subject: [PATCH 19/50] Command stubs. --- ...d.java => GetBasalRateProfileCommand.java} | 10 ++++---- .../commands/GetReservoirLevelCommand.java | 24 +++++++++++++++++++ .../commands/SetBasalRateProfileCommand.java | 17 +++++++++++++ 3 files changed, 46 insertions(+), 5 deletions(-) rename app/src/main/java/de/jotomo/ruffyscripter/commands/{GetBasalCommand.java => GetBasalRateProfileCommand.java} (94%) create mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/GetReservoirLevelCommand.java create mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/SetBasalRateProfileCommand.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalRateProfileCommand.java similarity index 94% rename from app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java rename to app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalRateProfileCommand.java index f69012ff29..a97a24f173 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetBasalRateProfileCommand.java @@ -12,12 +12,12 @@ import java.util.Map; import de.jotomo.ruffyscripter.RuffyScripter; -public class GetBasalCommand extends BaseCommand { - private static final Logger log = LoggerFactory.getLogger(GetBasalCommand.class); +public class GetBasalRateProfileCommand extends BaseCommand { + private static final Logger log = LoggerFactory.getLogger(GetBasalRateProfileCommand.class); private RuffyScripter scripter; - public GetBasalCommand() {} + public GetBasalRateProfileCommand() {} @Override public List validateArguments() { @@ -94,8 +94,8 @@ public class GetBasalCommand extends BaseCommand { // case ERROR: // case AFTER: // scripter.goToMainMenuScreen(MenuType.MAIN_MENU,2000); -// synchronized(GetBasalCommand.this) { -// GetBasalCommand.this.notify(); +// synchronized(GetBasalRateProfileCommand.this) { +// GetBasalRateProfileCommand.this.notify(); // } // break; // } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetReservoirLevelCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetReservoirLevelCommand.java new file mode 100644 index 0000000000..3a620a0fef --- /dev/null +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetReservoirLevelCommand.java @@ -0,0 +1,24 @@ +package de.jotomo.ruffyscripter.commands; + +import java.util.List; + +public class GetReservoirLevelCommand extends BaseCommand { + @Override + public CommandResult execute() { + // TODO stub + // watch out, level goes into PumpState, which is usually set by RuffyScripter + // after a command ran, unless a command has already set it ... I don't like + // that, it's too implicit ... + + // also, maybe ditch this command and add a parameter to GetPumpStateCommand to also + // read the reservoir level if possible (pump must be in a state to accept commands + // (possible on main, stop ...) + return null; + } + + @Override + public List validateArguments() { + // TODO stub + return null; + } +} diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetBasalRateProfileCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetBasalRateProfileCommand.java new file mode 100644 index 0000000000..6d98c94d42 --- /dev/null +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetBasalRateProfileCommand.java @@ -0,0 +1,17 @@ +package de.jotomo.ruffyscripter.commands; + +import java.util.List; + +public class SetBasalRateProfileCommand extends BaseCommand { + @Override + public CommandResult execute() { + // TODO stub + return null; + } + + @Override + public List validateArguments() { + // TODO stub + return null; + } +} From 7a41117a642f53ae289a1df6f3e1679c80b0d1a9 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 19:23:05 +0200 Subject: [PATCH 20/50] Experiments. --- .../commands/GetPumpStateCommand.java | 145 +++++++++++++++++- 1 file changed, 144 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java index 567685e2af..9b51011bbd 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java @@ -1,14 +1,157 @@ package de.jotomo.ruffyscripter.commands; +import org.monkey.d.ruffy.ruffy.driver.display.MenuType; + import java.util.Collections; import java.util.List; +import de.jotomo.ruffyscripter.PumpState; +import de.jotomo.ruffyscripter.RuffyScripter; + +import static de.jotomo.ruffyscripter.commands.GetPumpStateCommand.Stepper.runStep; + public class GetPumpStateCommand extends BaseCommand { + interface Step { + void doStep(); + } + + static boolean cancelRequested; + + + public static class Stepper { + public static void runStep(int retries, String desc, Step step) { + runStep(retries, desc, step, null, null); + } + public static void runStep(int retries, String desc, Step step, String recoveryDesc, Step recovery) { + // pre-checks here + if (cancelRequested) { +// runStep(0, "return to neutral state", () -> scripter.navigateToMainMenu()); +// if (recovery != null) recovery.doStep(); +// throw new CommandAbortedException(true); + } + if (true /*conectionLost*/) { + // either try to reconnect and deal with raised alarms (corfirm them and forward to AAPS) + // or let RS know he should reconnect and handle it (if that routine handles + // recovery in a generic way + } + /*boolean success/result =*/ step.doStep(); + if (true /*successful*/) { + // + } else { + runStep(retries - 1, desc, step, recoveryDesc, recovery); + } + } + } + + static class StepBuilder { + public StepBuilder(String desc) {} + + public String result; + + Step cancel = new Step() { + @Override + public void doStep() { + // default recovery + } + }; + + public StepBuilder retries(int retries) { return this; } + public StepBuilder description(Step step) { + return this; + } + public StepBuilder step(Step step) { + return this; + } + public StepBuilder recover(Step step) { + return this; + } + public StepBuilder cancel(Step step) { + return this; + } + public StepBuilder run() { + return this; + } + } + + + + // state/info on whether an abort in that situtaion will raise a pump alert that we need + // to connect to the pump for quickly and dismiss it + + +// void step(String description, Code c) { +// c.run(); +// +// exception/unexpected state +// user requested cancel +// disconnect info from ruffy +// +// } + + public CommandResult execute2() { + + new StepBuilder("Navigate to bolus menu") // turn into a method createStep() or so, which has access to the scripter + .step(new Step() { + @Override + public void doStep() { + System.out.println("something"); + } + }) + .recover(new Step() { + @Override + public void doStep() { + System.out.println("default impl: navigate back to main menu, no alarms"); + } + }) + .run(); + new StepBuilder("Input bolus") // turn into a method createStep() or so, which has access to the scripter + .retries(5) + .step(new Step() { + @Override + public void doStep() { + System.out.println("something"); + } + }) + .recover(new Step() { + @Override + public void doStep() { + System.out.println("navigate back and cancel 'bolus cancelled' alert"); + } + }) + .run(); + // ^^ would allow overriding a default recovery or abort method + // vv below code as well, with varargs and overloading or simply more methods like runStepWithCustomRecovery + runStep(0, "check things", new Step() { + @Override + public void doStep() { + scripter.navigateToMenu(MenuType.MY_DATA_MENU); + } + }); + runStep(0, "check things", new Step() { + @Override + public void doStep() { + scripter.navigateToMenu(MenuType.MY_DATA_MENU); + } + }, "recover by doing x", new Step() { + @Override + public void doStep() { + // recover + } + }); + + return null; + } + @Override public CommandResult execute() { return new CommandResult().success(true).enacted(false).message("Returning pump state only"); } +// @Override +// public CommandResult execute() { +// return new CommandResult().success(true).enacted(false).message("Returning pump state only"); +// } + @Override public List validateArguments() { return Collections.emptyList(); @@ -16,6 +159,6 @@ public class GetPumpStateCommand extends BaseCommand { @Override public String toString() { - return "GetPumpStateCommand{}"; + return "ReadPumpStateCommand{}"; } } From 5eea6d7b8d887f658f7fdf27857711fd2ab1265c Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 19:35:19 +0200 Subject: [PATCH 21/50] Fix waiting between reconnects. --- .../de/jotomo/ruffyscripter/RuffyScripter.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 54b4094f68..941aa96c39 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -33,9 +33,7 @@ import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; public class RuffyScripter { private static final Logger log = LoggerFactory.getLogger(RuffyScripter.class); - private IRuffyService ruffyService; - private final long connectionTimeOutMs = 5000; private String unrecoverableError = null; public volatile Menu currentMenu; @@ -44,9 +42,6 @@ public class RuffyScripter { private volatile long lastCmdExecutionTime; private volatile Command activeCmd = null; - private volatile boolean connected = false; - private volatile long lastDisconnected = 0; - private boolean started = false; private final Object keylock = new Object(); @@ -99,23 +94,25 @@ public class RuffyScripter { } private boolean canDisconnect = false; + private volatile boolean connected = false; + private volatile long lastDisconnected = 0; + private Thread idleDisconnectMonitorThread = new Thread(new Runnable() { @Override public void run() { - long lastDisconnect = System.currentTimeMillis(); while (unrecoverableError == null) { try { long now = System.currentTimeMillis(); + long connectionTimeOutMs = 5000; if (connected && activeCmd == null && now > lastCmdExecutionTime + connectionTimeOutMs // don't disconnect too frequently, confuses ruffy? - && now > lastDisconnect + 15 * 1000) { + && now > lastDisconnected + 15 * 1000) { log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout"); - lastDisconnect = now; + lastDisconnected = now; canDisconnect = true; ruffyService.doRTDisconnect(mHandler); connected = false; - lastDisconnect = System.currentTimeMillis(); // don't attempt anything fancy in the next 10s, let the pump settle SystemClock.sleep(10 * 1000); } else { @@ -388,6 +385,8 @@ public class RuffyScripter { // When connecting again shortly after disconnecting, the pump sometimes fails // to come up. So for v1, just wait. This happens rarely, so no overly fancy logic needed. // TODO v2 see if we can do this cleaner, use isDisconnected as well maybe. GL#34. + // TODO remove this, will be in the way of quickly reconnecting after an exception and dealing + // with an alarm; we'll then see if the pump can deal with this if (System.currentTimeMillis() < lastDisconnected + 10 * 1000) { log.debug("Waiting 10s to let pump settle after recent disconnect"); SystemClock.sleep(10 * 1000); From eb74a24e546297421283a43ae38447d579edfec7 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Wed, 23 Aug 2017 22:10:19 +0200 Subject: [PATCH 22/50] Misc cleanups. --- .../jotomo/ruffyscripter/RuffyScripter.java | 24 +++------ .../ruffyscripter/commands/BolusCommand.java | 12 ++--- .../DetermineCapabilitiesCommand.java | 13 +++-- .../commands/GetPumpStateCommand.java | 8 +++ .../ruffyscripter/commands/SetTbrCommand.java | 52 +++++++++---------- .../commands/SetTbrCommandAlt.java | 16 +++--- .../plugins/PumpCombo/ComboPlugin.java | 16 +++--- 7 files changed, 67 insertions(+), 74 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 941aa96c39..e5a45f4afd 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -36,7 +36,7 @@ public class RuffyScripter { private IRuffyService ruffyService; private String unrecoverableError = null; - public volatile Menu currentMenu; + private volatile Menu currentMenu; private volatile long menuLastUpdated = 0; private volatile long lastCmdExecutionTime; @@ -49,10 +49,6 @@ public class RuffyScripter { private final Object screenlock = new Object(); - public RuffyScripter() { - - } - public void start(IRuffyService newService) { try { if (ruffyService != null) { @@ -72,23 +68,11 @@ public class RuffyScripter { newService.addHandler(mHandler); } } catch (Exception e) { + log.error("Unhandled exception starting RuffyScripter", e); throw new RuntimeException(e); } } - public void stop() { - if (started) { - started = false; - // TODO ruffy removes dead handlers automatically by now. - // still, check this when going through recovery logic -/* try { - ruffyService.removeHandler(mHandler); - } catch (RemoteException e) { - log.warn("Removing IRTHandler from Ruffy service failed, ignoring", e); - }*/ - } - } - public boolean isRunning() { return started; } @@ -234,6 +218,10 @@ public class RuffyScripter { this.ruffyService = null; } + public Menu getCurrentMenu() { + return currentMenu; + } + private static class Returnable { CommandResult cmdResult; } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 947d31ed6b..621a47fd76 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -11,8 +11,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.RuffyScripter; - public class BolusCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(BolusCommand.class); @@ -54,11 +52,11 @@ public class BolusCommand extends BaseCommand { // wait for bolus delivery to complete; the remaining units to deliver are counted // down and are displayed on the main menu. - Double bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); + Double bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); while (bolusRemaining != null) { log.debug("Delivering bolus, remaining: " + bolusRemaining); SystemClock.sleep(200); - bolusRemaining = (Double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS_REMAINING); + bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); } // TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus? @@ -74,16 +72,16 @@ public class BolusCommand extends BaseCommand { scripter.navigateToMenu(MenuType.MY_DATA_MENU); scripter.verifyMenuIsDisplayed(MenuType.MY_DATA_MENU); scripter.pressCheckKey(); - if (scripter.currentMenu.getType() != MenuType.BOLUS_DATA) { + if (scripter.getCurrentMenu().getType() != MenuType.BOLUS_DATA) { scripter.waitForMenuUpdate(); } - if (!scripter.currentMenu.attributes().contains(MenuAttribute.BOLUS)) { + if (!scripter.getCurrentMenu().attributes().contains(MenuAttribute.BOLUS)) { throw new CommandException().success(false).enacted(true) .message("Bolus was delivered, but unable to confirm it with history record"); } - double lastBolusInHistory = (double) scripter.currentMenu.getAttribute(MenuAttribute.BOLUS); + double lastBolusInHistory = (double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS); if (Math.abs(bolus - lastBolusInHistory) > 0.05) { throw new CommandException().success(false).enacted(true) .message("Last bolus shows " + lastBolusInHistory diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index ad2ed1a551..172a7742e1 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -12,7 +12,6 @@ import java.util.Collections; import java.util.List; import de.jotomo.ruffyscripter.PumpCapabilities; -import de.jotomo.ruffyscripter.RuffyScripter; public class DetermineCapabilitiesCommand extends BaseCommand { @@ -123,21 +122,21 @@ public class DetermineCapabilitiesCommand extends BaseCommand { private long readDisplayedTbrPercentage() { SystemClock.sleep(1000); // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); + Object percentageObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.BASAL_RATE); // this as a bit hacky, the display value is blinking, so we might catch that, so // keep trying till we get the Double we want while (!(percentageObj instanceof Double)) { scripter.waitForMenuUpdate(); - percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.BASAL_RATE); + percentageObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.BASAL_RATE); } return ((Double) percentageObj).longValue(); } private int readDisplayedTbrDurationMainMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if(scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)){ + if(scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME)){ // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); + Object durationObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); MenuTime duration = (MenuTime) durationObj; return duration.getHour() * 60 + duration.getMinute(); } else { @@ -147,8 +146,8 @@ public class DetermineCapabilitiesCommand extends BaseCommand { private int readDisplayedTbrPercentageMainMenu() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if(scripter.currentMenu.attributes().contains(MenuAttribute.TBR)){ - return (int)((Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR)).doubleValue(); + if(scripter.getCurrentMenu().attributes().contains(MenuAttribute.TBR)){ + return (int)((Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR)).doubleValue(); } else { return 100; } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java index 9b51011bbd..6f489b6bc3 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java @@ -4,6 +4,7 @@ import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import java.util.Collections; import java.util.List; +import java.util.TreeSet; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; @@ -68,6 +69,7 @@ public class GetPumpStateCommand extends BaseCommand { public StepBuilder cancel(Step step) { return this; } + public StepBuilder failure(Step step) { return this; } public StepBuilder run() { return this; } @@ -106,6 +108,12 @@ public class GetPumpStateCommand extends BaseCommand { .run(); new StepBuilder("Input bolus") // turn into a method createStep() or so, which has access to the scripter .retries(5) + .failure(new Step() { + @Override + public void doStep() { + System.out.println("retry command"); + } + }) .step(new Step() { @Override public void doStep() { diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 6a494e34ff..82a1780df0 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -61,36 +61,36 @@ public class SetTbrCommand extends BaseCommand { @Override public CommandResult execute() { try { - log.debug("1. going from " + scripter.currentMenu + " to TBR_MENU"); + log.debug("1. going from " + scripter.getCurrentMenu() + " to TBR_MENU"); int retries = 5; while (!scripter.goToMainTypeScreen(TBR_MENU, 3000)) { retries--; if (retries == 0) - throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.currentMenu); + throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.getCurrentMenu()); SystemClock.sleep(500); - if (scripter.currentMenu.getType() == TBR_MENU) + if (scripter.getCurrentMenu().getType() == TBR_MENU) break; } - if (scripter.currentMenu.getType() != TBR_MENU) - throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.currentMenu); + if (scripter.getCurrentMenu().getType() != TBR_MENU) + throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.getCurrentMenu()); - log.debug("2. entering " + scripter.currentMenu); + log.debug("2. entering " + scripter.getCurrentMenu()); retries = 5; while (!scripter.enterMenu(TBR_MENU, MenuType.TBR_SET, RuffyScripter.Key.CHECK, 2000)) { retries--; if (retries == 0) - throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.currentMenu); + throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.getCurrentMenu()); SystemClock.sleep(500); - if (scripter.currentMenu.getType() == TBR_SET) + if (scripter.getCurrentMenu().getType() == TBR_SET) break; - if (scripter.currentMenu.getType() == TBR_DURATION) { + if (scripter.getCurrentMenu().getType() == TBR_DURATION) { scripter.pressMenuKey(); scripter.waitForScreenUpdate(1000); } } - log.debug("SetTbrCommand: 3. getting/setting basal percentage in " + scripter.currentMenu); + log.debug("SetTbrCommand: 3. getting/setting basal percentage in " + scripter.getCurrentMenu()); retries = 30; double currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); @@ -110,29 +110,29 @@ public class SetTbrCommand extends BaseCommand { if (currentPercentage < 0 || retries < 0) throw new CommandException().message("unable to set basal percentage"); - log.debug("4. checking basal percentage in " + scripter.currentMenu); + log.debug("4. checking basal percentage in " + scripter.getCurrentMenu()); scripter.waitForScreenUpdate(1000); currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); if (currentPercentage != percentage) throw new CommandException().message("Unable to set percentage. Requested: " + percentage + ", value displayed on pump: " + currentPercentage); if (currentPercentage != 100) { - log.debug("5. change to TBR_DURATION from " + scripter.currentMenu); + log.debug("5. change to TBR_DURATION from " + scripter.getCurrentMenu()); retries = 5; while (retries >= 0 && !scripter.enterMenu(TBR_SET, MenuType.TBR_DURATION, RuffyScripter.Key.MENU, 2000)) { retries--; if (retries == 0) - throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.currentMenu); + throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.getCurrentMenu()); SystemClock.sleep(500); - if (scripter.currentMenu.getType() == TBR_DURATION) + if (scripter.getCurrentMenu().getType() == TBR_DURATION) break; - if (scripter.currentMenu.getType() == TBR_SET) { + if (scripter.getCurrentMenu().getType() == TBR_SET) { scripter.pressMenuKey(); scripter.waitForScreenUpdate(1000); } } - log.debug("6. getting/setting duration in " + scripter.currentMenu); + log.debug("6. getting/setting duration in " + scripter.getCurrentMenu()); retries = 30; double currentDuration = scripter.readDisplayedDuration(); @@ -156,30 +156,30 @@ public class SetTbrCommand extends BaseCommand { if (currentDuration < 0 || retries < 0) throw new CommandException().message("unable to set duration, requested:" + duration + ", displayed on pump: " + currentDuration); - log.debug("7. checking duration in " + scripter.currentMenu); + log.debug("7. checking duration in " + scripter.getCurrentMenu()); scripter.waitForScreenUpdate(1000); currentDuration = scripter.readDisplayedDuration(); if (currentDuration != duration) throw new CommandException().message("wrong duration! Requested: " + duration + ", displayed on pump: " + currentDuration); } - log.debug("8. confirming TBR om " + scripter.currentMenu); + log.debug("8. confirming TBR om " + scripter.getCurrentMenu()); retries = 5; - while (retries >= 0 && (scripter.currentMenu.getType() == TBR_DURATION || scripter.currentMenu.getType() == TBR_SET)) { + while (retries >= 0 && (scripter.getCurrentMenu().getType() == TBR_DURATION || scripter.getCurrentMenu().getType() == TBR_SET)) { retries--; scripter.pressCheckKey(); scripter.waitForScreenUpdate(1000); } - if (retries < 0 || scripter.currentMenu.getType() == TBR_DURATION || scripter.currentMenu.getType() == TBR_SET) + if (retries < 0 || scripter.getCurrentMenu().getType() == TBR_DURATION || scripter.getCurrentMenu().getType() == TBR_SET) throw new CommandException().message("failed setting basal!"); retries = 10; boolean cancelledError = true; if (percentage == 100) cancelledError = false; - while (retries >= 0 && scripter.currentMenu.getType() != MAIN_MENU) { + while (retries >= 0 && scripter.getCurrentMenu().getType() != MAIN_MENU) { // TODO how probable is it, that a totally unrelated error (like occlusion alert) // is raised at this point, which we'd cancel together with the TBR cancelled alert? - if (percentage == 100 && scripter.currentMenu.getType() == WARNING_OR_ERROR) { + if (percentage == 100 && scripter.getCurrentMenu().getType() == WARNING_OR_ERROR) { // TODO extract method confirmAlert(alert) scripter.pressCheckKey(); retries++; @@ -187,17 +187,17 @@ public class SetTbrCommand extends BaseCommand { scripter.waitForScreenUpdate(1000); } else { retries--; - if (scripter.currentMenu.getType() == MAIN_MENU && cancelledError) + if (scripter.getCurrentMenu().getType() == MAIN_MENU && cancelledError) break; } } log.debug("9. verifying the main menu display the TBR we just set/cancelled"); - if (retries < 0 || scripter.currentMenu.getType() != MAIN_MENU) + if (retries < 0 || scripter.getCurrentMenu().getType() != MAIN_MENU) throw new CommandException().message("failed going to main!"); - Object percentageObj = scripter.currentMenu.getAttribute(MenuAttribute.TBR); - Object durationObj = scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); + Object percentageObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); + Object durationObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); if (percentage == 100) { if (durationObj != null) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index 2ad5985dfc..ab376ffd68 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -214,14 +214,14 @@ public class SetTbrCommandAlt extends BaseCommand { long inFiveSeconds = System.currentTimeMillis() + 5 * 1000; boolean alertProcessed = false; while (System.currentTimeMillis() < inFiveSeconds && !alertProcessed) { - if (scripter.currentMenu.getType() == MenuType.WARNING_OR_ERROR) { + if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { // Check the raised alarm is TBR CANCELLED, so we're not accidentally cancelling // a different alarm that might be raised at the same time. // Note that the message is permanently displayed, while the error code is blinking. // A wait till the error code can be read results in the code hanging, despite // menu updates coming in, so just check the message. // TODO v2 this only works when the pump's language is English - String errorMsg = (String) scripter.currentMenu.getAttribute(MenuAttribute.MESSAGE); + String errorMsg = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE); if (!errorMsg.equals("TBR CANCELLED")) { throw new CommandException().success(false).enacted(false) .message("An alert other than the expected TBR CANCELLED was raised by the pump: " @@ -242,8 +242,8 @@ public class SetTbrCommandAlt extends BaseCommand { private void verifyMainMenuShowsNoActiveTbr() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - Double tbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR); - boolean runtimeDisplayed = scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME); + Double tbrPercentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); + boolean runtimeDisplayed = scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME); if (tbrPercentage != 100 || runtimeDisplayed) { throw new CommandException().message("Cancelling TBR failed, TBR is still set according to MAIN_MENU"); } @@ -252,12 +252,12 @@ public class SetTbrCommandAlt extends BaseCommand { private void verifyMainMenuShowsExpectedTbrActive() { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); // new TBR set; percentage and duration must be displayed ... - if (!scripter.currentMenu.attributes().contains(MenuAttribute.TBR) || - !scripter.currentMenu.attributes().contains(MenuAttribute.RUNTIME)) { + if (!scripter.getCurrentMenu().attributes().contains(MenuAttribute.TBR) || + !scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME)) { throw new CommandException().message("Setting TBR failed, according to MAIN_MENU no TBR is active"); } - Double mmTbrPercentage = (Double) scripter.currentMenu.getAttribute(MenuAttribute.TBR); - MenuTime mmTbrDuration = (MenuTime) scripter.currentMenu.getAttribute(MenuAttribute.RUNTIME); + Double mmTbrPercentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); + MenuTime mmTbrDuration = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); // ... and be the same as what we set // note that displayed duration might have already counted down, e.g. from 30 minutes to // 29 minutes and 59 seconds, so that 29 minutes are displayed 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 e46fd67c10..e61fc75e58 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 @@ -189,10 +189,11 @@ public class ComboPlugin implements PluginBase, PumpInterface { // this must be the base package of the app (check package attribute in // manifest element in the manifest file of the providing app) "org.monkey.d.ruffy.ruffy", - // full path to the driver + // full path to the driver; // in the logs this service is mentioned as (note the slash) - // "org.monkey.d.ruffy.ruffy/.driver.Ruffy" - //org.monkey.d.ruffy.ruffy is the base package identifier and /.driver.Ruffy the service within the package + // "org.monkey.d.ruffy.ruffy/.driver.Ruffy"; + // org.monkey.d.ruffy.ruffy is the base package identifier + // and /.driver.Ruffy the service within the package "org.monkey.d.ruffy.ruffy.driver.Ruffy" )); context.startService(intent); @@ -208,9 +209,8 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public void onServiceDisconnected(ComponentName name) { - ruffyScripter.stop(); log.debug("ruffy service disconnected"); - // try to reconnect ruffy service unless unbind was explicitely requested + // try to reconnect ruffy service unless unbind was explicitly requested // via unbindRuffyService if(!keepUnbound) { SystemClock.sleep(250); @@ -311,7 +311,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public boolean isBusy() { - return ruffyScripter == null || ruffyScripter.isPumpBusy(); + return ruffyScripter.isPumpBusy(); } // TODO @@ -337,8 +337,8 @@ public class ComboPlugin implements PluginBase, PumpInterface { log.debug("RefreshDataFromPump called"); // if Android is sluggish this might get called before ruffy is bound - if (ruffyScripter == null) { - log.warn("Rejecting call to RefreshDataFromPump: ruffy service not bound (yet)"); + if (!ruffyScripter.isRunning()) { + log.warn("Rejecting call to RefreshDataFromPump: scripter not ready yet."); return; } From c301d6585c5d4f63cc89b5350f5ac0b73c72e162 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 24 Aug 2017 11:13:54 +0200 Subject: [PATCH 23/50] ComboPlugin: implement Constraint, ProfileInterface. --- .../plugins/PumpCombo/ComboPlugin.java | 102 +++++++++++++++--- .../plugins/PumpDanaR/DanaRPlugin.java | 25 ++--- 2 files changed, 99 insertions(+), 28 deletions(-) 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 e61fc75e58..8f3efb408e 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 @@ -24,6 +24,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; +import java.util.Objects; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; @@ -37,15 +38,19 @@ import de.jotomo.ruffyscripter.commands.SetTbrCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommandAlt; import info.nightscout.androidaps.BuildConfig; import info.nightscout.androidaps.Config; +import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; +import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -57,7 +62,7 @@ import info.nightscout.utils.ToastUtils; /** * Created by mike on 05.08.2016. */ -public class ComboPlugin implements PluginBase, PumpInterface { +public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface { public static final String COMBO_MAX_TEMP_PERCENT_SP = "combo_maxTempPercent"; private static Logger log = LoggerFactory.getLogger(ComboPlugin.class); @@ -100,7 +105,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { pumpDescription.isBolusCapable = true; pumpDescription.bolusStep = 0.1d; - pumpDescription.isExtendedBolusCapable = false; // TODO + pumpDescription.isExtendedBolusCapable = false; // TODO GL#70 pumpDescription.extendedBolusStep = 0.1d; pumpDescription.extendedBolusDurationStep = 15; pumpDescription.extendedBolusMaxDuration = 12 * 60; @@ -115,7 +120,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { pumpDescription.tempMaxDuration = 24 * 60; - pumpDescription.isSetBasalProfileCapable = false; // TODO + pumpDescription.isSetBasalProfileCapable = false; // TODO GL#14 pumpDescription.basalStep = 0.01d; pumpDescription.basalMinimumRate = 0.0d; @@ -517,11 +522,6 @@ public class ComboPlugin implements PluginBase, PumpInterface { int adjustedPercent = percent; - if (adjustedPercent > pumpDescription.maxTempPercent) { - log.debug("Reducing requested TBR to the maximum support by the pump: " + percent + " -> " + pumpDescription.maxTempPercent); - adjustedPercent = pumpDescription.maxTempPercent; - } - if (adjustedPercent % 10 != 0) { Long rounded = Math.round(adjustedPercent / 10d) * 10; log.debug("Rounded requested percentage:" + adjustedPercent + " -> " + rounded); @@ -561,6 +561,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { + // TODO GL#70 return OPERATION_NOT_SUPPORTED; } @@ -688,6 +689,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public String shortStatus(boolean veryShort) { + // TODO trim for wear if veryShort==true return statusSummary; } @@ -698,7 +700,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { @SuppressWarnings("UnusedParameters") @Subscribe - public void onStatusEvent(final EventAppExit e) { + public void onStatusEvent(final EventAppExit ignored) { unbindRuffyService(); } @@ -728,10 +730,84 @@ public class ComboPlugin implements PluginBase, PumpInterface { } } + @Override + public boolean isLoopEnabled() { + return true; + } -} + @Override + public boolean isClosedModeEnabled() { + return true; + } + @Override + public boolean isAutosensModeEnabled() { + return true; + } -// If you want update fragment call -// MainApp.bus().post(new EventComboPumpUpdateGUI()); -// fragment should fetch data from plugin and display status, buttons etc ... + @Override + public boolean isAMAModeEnabled() { + return true; + } + + @Override + public Double applyBasalConstraints(Double absoluteRate) { + double origAbsoluteRate = absoluteRate; + // TODO GL#56 + if (absoluteRate > 25d) { + absoluteRate = 25d; + if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) + log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); + } + return absoluteRate; + } + + @Override + public Integer applyBasalConstraints(Integer percentRate) { + Integer origPercentRate = percentRate; + if (percentRate < 0) percentRate = 0; + if (percentRate > pumpDescription.maxTempPercent) + percentRate = pumpDescription.maxTempPercent; + if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) + log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); + return percentRate; + } + + @Override + public Double applyBolusConstraints(Double insulin) { + // Hard pump limits are not directly readable from pump and serve as a fail safe. + // TODO GL#56 + return insulin; + } + + @Override + public Integer applyCarbsConstraints(Integer carbs) { + // pump is oblivious to carbs + return carbs; + } + + @Override + public Double applyMaxIOBConstraints(Double maxIob) { + // pump is oblivious to IOB + return maxIob; + } + + @Nullable + @Override + public ProfileStore getProfile() { + // TODO GL#13 + return null; + } + + @Override + public String getUnits() { + // pump has no concept of senors/blood glucose + return Constants.MGDL; + } + + @Override + public String getProfileName() { + // TODO GL#13 + return "Profile 1"; + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index bc5b23ad92..b8ee6db8bf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.squareup.otto.Subscribe; @@ -66,6 +67,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C public static DanaRExecutionService sExecutionService; + @NonNull private static DanaRPump pump = DanaRPump.getInstance(); private static boolean useExtendedBoluses = false; @@ -743,21 +745,17 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C return true; } - @SuppressWarnings("PointlessBooleanExpression") @Override public Double applyBasalConstraints(Double absoluteRate) { double origAbsoluteRate = absoluteRate; - if (pump != null) { - if (absoluteRate > pump.maxBasal) { - absoluteRate = pump.maxBasal; - if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) - log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); - } + if (absoluteRate > pump.maxBasal) { + absoluteRate = pump.maxBasal; + if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) + log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); } return absoluteRate; } - @SuppressWarnings("PointlessBooleanExpression") @Override public Integer applyBasalConstraints(Integer percentRate) { Integer origPercentRate = percentRate; @@ -769,16 +767,13 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C return percentRate; } - @SuppressWarnings("PointlessBooleanExpression") @Override public Double applyBolusConstraints(Double insulin) { double origInsulin = insulin; - if (pump != null) { - if (insulin > pump.maxBolus) { - insulin = pump.maxBolus; - if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) - log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); - } + if (insulin > pump.maxBolus) { + insulin = pump.maxBolus; + if (Config.logConstraintsChanges && origInsulin != Constants.bolusOnlyForCheckLimit) + log.debug("Limiting bolus " + origInsulin + "U by pump constraint to " + insulin + "U"); } return insulin; } From 9f57f82b6adde12ad8bd594de905da3f3869e1fc Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 24 Aug 2017 15:31:27 +0200 Subject: [PATCH 24/50] Remove wait for carb-only treatment. --- .../plugins/PumpCombo/ComboPlugin.java | 37 +++---------------- .../plugins/PumpCombo/ComboPump.java | 4 ++ 2 files changed, 10 insertions(+), 31 deletions(-) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java 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 8f3efb408e..b1c8b157be 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 @@ -54,6 +54,7 @@ import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI; import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; @@ -377,40 +378,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf if (!Config.comboSplitBoluses) { return deliverBolus(detailedBolusInfo); } else { - // split up bolus into 2 U parts - PumpEnactResult pumpEnactResult = new PumpEnactResult(); - pumpEnactResult.success = true; - pumpEnactResult.enacted = true; - pumpEnactResult.bolusDelivered = 0d; - pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; - pumpEnactResult.comment = MainApp.instance().getString(R.string.virtualpump_resultok); - - double remainingBolus = detailedBolusInfo.insulin; - int split = 1; - while (remainingBolus > 0.05) { - double bolus = remainingBolus > 2 ? 2 : remainingBolus; - DetailedBolusInfo bolusInfo = new DetailedBolusInfo(); - bolusInfo.insulin = bolus; - bolusInfo.isValid = false; - log.debug("Delivering split bolus #" + split + " with " + bolus + " U"); - PumpEnactResult bolusResult = deliverBolus(bolusInfo); - if (!bolusResult.success) { - return bolusResult; - } - pumpEnactResult.bolusDelivered += bolus; - remainingBolus -= 2; - split++; - } - MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); - return pumpEnactResult; + return deliverSplittedBolus(detailedBolusInfo); } } else { // no bolus required, carb only treatment - - // TODO the ui freezes when the calculator issues a carb-only treatment - // so just wait, yeah, this is dumb. for now; proper fix via GL#10 - // info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog.scheduleDismiss() - SystemClock.sleep(6000); PumpEnactResult pumpEnactResult = new PumpEnactResult(); pumpEnactResult.success = true; pumpEnactResult.enacted = true; @@ -418,6 +389,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; pumpEnactResult.comment = MainApp.instance().getString(R.string.virtualpump_resultok); MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + + EventOverviewBolusProgress bolusingEvent = EventOverviewBolusProgress.getInstance(); + bolusingEvent.percent = 100; + MainApp.bus().post(bolusingEvent); return pumpEnactResult; } } else { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java new file mode 100644 index 0000000000..c9581f5911 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java @@ -0,0 +1,4 @@ +package info.nightscout.androidaps.plugins.PumpCombo; + +public class ComboPump { +} From 3fdac4b23ec9089d9606b534d124f8cd46fe430e Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 24 Aug 2017 15:31:52 +0200 Subject: [PATCH 25/50] Small refactoring. --- .../plugins/PumpCombo/ComboPlugin.java | 35 +++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) 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 b1c8b157be..9d23814e90 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 @@ -84,6 +84,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf volatile CommandResult lastCmdResult; @NonNull volatile Date lastCmdTime = new Date(0); + // TODO move into ComboPump? Accessor for fragment; more accessors? solves volatile issues; volatile PumpState pumpState = new PumpState(); private static PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult(); @@ -434,6 +435,36 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf return pumpEnactResult; } + @NonNull + private PumpEnactResult deliverSplittedBolus(DetailedBolusInfo detailedBolusInfo) { + // split up bolus into 2 U parts + PumpEnactResult pumpEnactResult = new PumpEnactResult(); + pumpEnactResult.success = true; + pumpEnactResult.enacted = true; + pumpEnactResult.bolusDelivered = 0d; + pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; + pumpEnactResult.comment = MainApp.instance().getString(R.string.virtualpump_resultok); + + double remainingBolus = detailedBolusInfo.insulin; + int split = 1; + while (remainingBolus > 0.05) { + double bolus = remainingBolus > 2 ? 2 : remainingBolus; + DetailedBolusInfo bolusInfo = new DetailedBolusInfo(); + bolusInfo.insulin = bolus; + bolusInfo.isValid = false; + log.debug("Delivering split bolus #" + split + " with " + bolus + " U"); + PumpEnactResult bolusResult = deliverBolus(bolusInfo); + if (!bolusResult.success) { + return bolusResult; + } + pumpEnactResult.bolusDelivered += bolus; + remainingBolus -= 2; + split++; + } + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + return pumpEnactResult; + } + private CommandResult runCommand(Command command) { if (ruffyScripter == null) { String msg = "No connection to ruffy. Pump control not available."; @@ -728,7 +759,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Double applyBasalConstraints(Double absoluteRate) { double origAbsoluteRate = absoluteRate; - // TODO GL#56 + // TODO GL#56, #42 if (absoluteRate > 25d) { absoluteRate = 25d; if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) @@ -751,7 +782,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Double applyBolusConstraints(Double insulin) { // Hard pump limits are not directly readable from pump and serve as a fail safe. - // TODO GL#56 + // TODO GL#56, #42 return insulin; } From 37523fbdd17a3e1cfd4d1770d3bba6d27579eaf0 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 24 Aug 2017 16:00:24 +0200 Subject: [PATCH 26/50] ComboPlugin: Extract fields into ComboPump. --- .../plugins/PumpCombo/ComboFragment.java | 10 +-- .../plugins/PumpCombo/ComboPlugin.java | 88 +++++++++---------- .../plugins/PumpCombo/ComboPump.java | 20 ++++- 3 files changed, 65 insertions(+), 53 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java index 2ae111ab6b..855ac662ae 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java @@ -148,9 +148,9 @@ public class ComboFragment extends Fragment implements View.OnClickListener { activity.runOnUiThread(new Runnable() { @Override public void run() { - statusText.setText(getPlugin().statusSummary); + statusText.setText(getPlugin().getPump().stateSummary); if (getPlugin().isInitialized()) { - PumpState ps = getPlugin().pumpState; + PumpState ps = getPlugin().getPump().state; if (ps != null) { boolean tbrActive = ps.tbrPercent != -1 && ps.tbrPercent != 100; if (tbrActive) { @@ -183,16 +183,16 @@ public class ComboFragment extends Fragment implements View.OnClickListener { } } - Command lastCmd = getPlugin().lastCmd; + Command lastCmd = getPlugin().getPump().lastCmd; if (lastCmd != null) { lastCmdText.setText(lastCmd.toString()); - lastCmdTimeText.setText(getPlugin().lastCmdTime.toLocaleString()); + lastCmdTimeText.setText(getPlugin().getPump().lastCmdTime.toLocaleString()); } else { lastCmdText.setText(""); lastCmdTimeText.setText(""); } - CommandResult lastCmdResult = getPlugin().lastCmdResult; + CommandResult lastCmdResult = getPlugin().getPump().lastCmdResult; if (lastCmdResult != null && lastCmdResult.message != null) { lastCmdResultText.setText(lastCmdResult.message); lastCmdDurationText.setText(lastCmdResult.duration); 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 9d23814e90..913cc12f8c 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 @@ -75,17 +75,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf private RuffyScripter ruffyScripter; private ServiceConnection mRuffyServiceConnection; - // package-protected only so ComboFragment can access these - @NonNull - volatile String statusSummary = "Initializing"; - @Nullable - volatile Command lastCmd; - @Nullable - volatile CommandResult lastCmdResult; - @NonNull - volatile Date lastCmdTime = new Date(0); - // TODO move into ComboPump? Accessor for fragment; more accessors? solves volatile issues; - volatile PumpState pumpState = new PumpState(); + private ComboPump pump = new ComboPump(); private static PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult(); @@ -129,6 +119,10 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf pumpDescription.isRefillingCapable = true; } + public ComboPump getPump() { + return pump; + } + /** * The alerter frequently checks the result of the last executed command via the lastCmdResult * field and shows a notification with sound and vibration if an error occurred. @@ -146,15 +140,15 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf int id = 1000; long lastAlarmTime = 0; while (true) { - Command localLastCmd = lastCmd; - CommandResult localLastCmdResult = lastCmdResult; + Command localLastCmd = pump.lastCmd; + CommandResult localLastCmdResult = pump.lastCmdResult; if (localLastCmdResult != null && !localLastCmdResult.success) { long now = System.currentTimeMillis(); long fiveMinutesSinceLastAlarm = lastAlarmTime + (5 * 60 * 1000) + (15 * 1000); if (now > fiveMinutesSinceLastAlarm) { log.error("Command failed: " + localLastCmd); log.error("Command result: " + localLastCmdResult); - PumpState localPumpState = pumpState; + PumpState localPumpState = pump.state; if (localPumpState != null && localPumpState.errorMsg != null) { log.warn("Pump is in error state, displaying; " + localPumpState.errorMsg); } @@ -231,7 +225,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } if (!boundSucceeded) { - statusSummary = "No connection to ruffy. Pump control not available."; + pump.stateSummary = "No connection to ruffy. Pump control not available."; } return true; } @@ -308,12 +302,12 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf public boolean isInitialized() { // consider initialized when the pump's state was initially fetched, // after that lastCmd* variables will have values - return lastCmdTime.getTime() > 0; + return pump.lastCmdTime.getTime() > 0; } @Override public boolean isSuspended() { - return pumpState != null && pumpState.suspended; + return pump.state != null && pump.state.suspended; } @Override @@ -335,7 +329,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public Date lastDataTime() { - return lastCmdTime; + return pump.lastCmdTime; } // this method is regularly called from info.nightscout.androidaps.receivers.KeepAliveReceiver @@ -350,8 +344,8 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf } boolean notAUserRequest = !reason.toLowerCase().contains("user"); - boolean wasRunAtLeastOnce = lastCmdTime.getTime() > 0; - boolean ranWithinTheLastMinute = System.currentTimeMillis() < lastCmdTime.getTime() + 60 * 1000; + boolean wasRunAtLeastOnce = pump.lastCmdTime.getTime() > 0; + boolean ranWithinTheLastMinute = System.currentTimeMillis() < pump.lastCmdTime.getTime() + 60 * 1000; if (notAUserRequest && wasRunAtLeastOnce && ranWithinTheLastMinute) { log.debug("Not fetching state from pump, since we did already within the last 60 seconds"); } else { @@ -468,11 +462,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf private CommandResult runCommand(Command command) { if (ruffyScripter == null) { String msg = "No connection to ruffy. Pump control not available."; - statusSummary = msg; + pump.stateSummary = msg; return new CommandResult().message(msg); } - statusSummary = "Executing " + command; + pump.stateSummary = "Executing " + command; MainApp.bus().post(new EventComboPumpUpdateGUI()); CommandResult commandResult = ruffyScripter.runCommand(command); @@ -481,17 +475,17 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf log.error("Exception received from pump", commandResult.exception); } - lastCmd = command; - lastCmdTime = new Date(); - lastCmdResult = commandResult; - pumpState = commandResult.state; + pump.lastCmd = command; + pump.lastCmdTime = new Date(); + pump.lastCmdResult = commandResult; + pump.state = commandResult.state; if (commandResult.success && commandResult.state.suspended) { - statusSummary = "Suspended"; + pump.stateSummary = "Suspended"; } else if (commandResult.success) { - statusSummary = "Idle"; + pump.stateSummary = "Idle"; } else { - statusSummary = "Error"; + pump.stateSummary = "Error"; } MainApp.bus().post(new EventComboPumpUpdateGUI()); @@ -639,41 +633,41 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf // TODO v2 add battery, reservoir info when we start reading that and clean up the code @Override public JSONObject getJSONStatus() { - if (lastCmdTime.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { + if (pump.lastCmdTime.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { return null; } try { - JSONObject pump = new JSONObject(); - JSONObject status = new JSONObject(); - JSONObject extended = new JSONObject(); - status.put("status", statusSummary); - extended.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); + JSONObject pumpJson = new JSONObject(); + JSONObject statusJson = new JSONObject(); + JSONObject extendedJson = new JSONObject(); + statusJson.put("status", pump.stateSummary); + extendedJson.put("Version", BuildConfig.VERSION_NAME + "-" + BuildConfig.BUILDVERSION); try { - extended.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); + extendedJson.put("ActiveProfile", MainApp.getConfigBuilder().getProfileName()); } catch (Exception e) { } - status.put("timestamp", lastCmdTime); + statusJson.put("timestamp", pump.lastCmdTime); - PumpState ps = pumpState; + PumpState ps = pump.state; if (ps != null) { if (ps.tbrActive) { - extended.put("TempBasalAbsoluteRate", ps.tbrRate); - extended.put("TempBasalPercent", ps.tbrPercent); - extended.put("TempBasalRemaining", ps.tbrRemainingDuration); + extendedJson.put("TempBasalAbsoluteRate", ps.tbrRate); + extendedJson.put("TempBasalPercent", ps.tbrPercent); + extendedJson.put("TempBasalRemaining", ps.tbrRemainingDuration); } if (ps.errorMsg != null) { - extended.put("ErrorMessage", ps.errorMsg); + extendedJson.put("ErrorMessage", ps.errorMsg); } } // more info here .... look at dana plugin - pump.put("status", status); - pump.put("extended", extended); - pump.put("clock", DateUtil.toISOString(lastCmdTime)); + pumpJson.put("status", statusJson); + pumpJson.put("extended", extendedJson); + pumpJson.put("clock", DateUtil.toISOString(pump.lastCmdTime)); - return pump; + return pumpJson; } catch (Exception e) { log.warn("Failed to gather device status for upload", e); } @@ -696,7 +690,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public String shortStatus(boolean veryShort) { // TODO trim for wear if veryShort==true - return statusSummary; + return pump.stateSummary; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java index c9581f5911..d24a31607c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboPump.java @@ -1,4 +1,22 @@ package info.nightscout.androidaps.plugins.PumpCombo; -public class ComboPump { +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.util.Date; + +import de.jotomo.ruffyscripter.PumpState; +import de.jotomo.ruffyscripter.commands.Command; +import de.jotomo.ruffyscripter.commands.CommandResult; + +class ComboPump { + @NonNull + volatile String stateSummary = "Initializing"; + @Nullable + volatile Command lastCmd; + @Nullable + volatile CommandResult lastCmdResult; + @NonNull + volatile Date lastCmdTime = new Date(0); + volatile PumpState state = new PumpState(); } From e6ba99b02f14d003078ba6c1cc949a9a18874ef2 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 11:05:37 +0200 Subject: [PATCH 27/50] Fix reading blinking values, use alternate SetTbrCommand by default, cleanups --- .../jotomo/ruffyscripter/RuffyScripter.java | 148 +++++++++++------- .../commands/CancelTbrCommand.java | 4 +- .../commands/GetPumpStateCommand.java | 4 - .../commands/SetTbrCommandAlt.java | 8 +- .../info/nightscout/androidaps/Config.java | 2 +- 5 files changed, 100 insertions(+), 66 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index e5a45f4afd..8f8d784e7d 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -218,10 +218,6 @@ public class RuffyScripter { this.ruffyService = null; } - public Menu getCurrentMenu() { - return currentMenu; - } - private static class Returnable { CommandResult cmdResult; } @@ -401,6 +397,53 @@ public class RuffyScripter { } } + // TODO v2 add remaining info we can extract from the main menu, low battery and low + // cartridge warnings, running extended bolus (how does that look if a TBR is active as well?) + + /** This reads the state of the, which is whatever is currently displayed on the display, + * no actions are performed. */ + public PumpState readPumpState() { + PumpState state = new PumpState(); + Menu menu = currentMenu; + if (menu == null) { + return new PumpState().errorMsg("Menu is not available"); + } + MenuType menuType = menu.getType(); + if (menuType == MenuType.MAIN_MENU) { + Double tbrPercentage = (Double) menu.getAttribute(MenuAttribute.TBR); + if (tbrPercentage != 100) { + state.tbrActive = true; + Double displayedTbr = (Double) menu.getAttribute(MenuAttribute.TBR); + state.tbrPercent = displayedTbr.intValue(); + MenuTime durationMenuTime = ((MenuTime) menu.getAttribute(MenuAttribute.RUNTIME)); + state.tbrRemainingDuration = durationMenuTime.getHour() * 60 + durationMenuTime.getMinute(); + state.tbrRate = ((double) menu.getAttribute(MenuAttribute.BASAL_RATE)); + } + state.lowBattery = ((boolean) menu.getAttribute(MenuAttribute.LOW_BATTERY)); + state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE)); + // TODO v2, read current base basal rate, which is shown center when no TBR is active. + // Check if that holds true when an extended bolus is running. + // Add a field to PumpStatus, rather than renaming/overloading tbrRate to mean + // either TBR rate or basal rate depending on whether a TBR is active. + } else if (menuType == MenuType.WARNING_OR_ERROR) { + state.errorMsg = (String) menu.getAttribute(MenuAttribute.MESSAGE); + } else if (menuType == MenuType.STOP) { + state.suspended = true; + state.lowBattery = ((boolean) menu.getAttribute(MenuAttribute.LOW_BATTERY)); + state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE)); + } else { + StringBuilder sb = new StringBuilder(); + for (MenuAttribute menuAttribute : menu.attributes()) { + sb.append(menuAttribute); + sb.append(": "); + sb.append(menu.getAttribute(menuAttribute)); + sb.append("\n"); + } + state.errorMsg = "Pump is on menu " + menuType + ", listing attributes: \n" + sb.toString(); + } + return state; + } + // below: methods to be used by commands // TODO move into a new Operations(scripter) class commands can delegate to, // so this class can focus on providing a connection to run commands @@ -415,10 +458,50 @@ public class RuffyScripter { public static byte BACK = (byte) 0x33; } + interface Step { + void run(boolean waitForPumpUpdateAfterwards); + } +/* + + private long lastPumpWrite = 0; + + private void wrapNoNotTheSubwayKind(Step step, boolean waitForPumpUpdateAfterwards) { + if (!connected) { + // try to reconnect, with a timeout before the pump raises a menu timeout + // timeout = lastPumpWrite + 15 * 1000 // avoid default pump timeout of 20s + } + step.run(waitForPumpUpdateAfterwards); + // TODO there's a chance the above was not executed by the pump; assume that if we're not + // still connected and abort the command and retry if it it's retryable + // isConnected + lastPumpWrite = System.currentTimeMillis(); + + // TODO: spike: source the ruffy driver package and do away with the remote service + + refuse to debug and fix incomprehensive code that Sandra wrote, can't explain why she + did what she did nor commented on it + + if (!connected) { +// cancelInternal(); +// if (activeCmd.isRetriable) { + } + } +*/ + + // === pump ops === + public Menu getCurrentMenu() { + return currentMenu; + } + public void pressUpKey() { - log.debug("Pressing up key"); - pressKey(Key.UP, 2000); - log.debug("Releasing up key"); +// wrapNoNotTheSubwayKind(new Step() { +// @Override +// public void doStep() { + log.debug("Pressing up key"); + pressKey(Key.UP, 2000); + log.debug("Releasing up key"); +// } +// }); } public void pressDownKey() { @@ -588,12 +671,12 @@ public class RuffyScripter { public T readBlinkingValue(Class expectedType, MenuAttribute attribute) { int retries = 5; Object value = currentMenu.getAttribute(attribute); - while (!value.getClass().isAssignableFrom(expectedType.getClass())) { + while (!expectedType.isInstance(value)) { value = currentMenu.getAttribute(attribute); waitForScreenUpdate(1000); retries--; if (retries == 0) { - throw new CommandException().message("Failed to read blinkng value: " + attribute); + throw new CommandException().message("Failed to read blinkng value: " + attribute + "=" + value + " type=" + value.getClass()); } } return (T) value; @@ -603,51 +686,4 @@ public class RuffyScripter { MenuTime duration = readBlinkingValue(MenuTime.class, MenuAttribute.RUNTIME); return duration.getHour() * 60 + duration.getMinute(); } - - // TODO v2 add remaining info we can extract from the main menu, low battery and low - // cartridge warnings, running extended bolus (how does that look if a TBR is active as well?) - - /** This reads the state of the, which is whatever is currently displayed on the display, - * no actions are performed. */ - public PumpState readPumpState() { - PumpState state = new PumpState(); - Menu menu = currentMenu; - if (menu == null) { - return new PumpState().errorMsg("Menu is not available"); - } - MenuType menuType = menu.getType(); - if (menuType == MenuType.MAIN_MENU) { - Double tbrPercentage = (Double) menu.getAttribute(MenuAttribute.TBR); - if (tbrPercentage != 100) { - state.tbrActive = true; - Double displayedTbr = (Double) menu.getAttribute(MenuAttribute.TBR); - state.tbrPercent = displayedTbr.intValue(); - MenuTime durationMenuTime = ((MenuTime) menu.getAttribute(MenuAttribute.RUNTIME)); - state.tbrRemainingDuration = durationMenuTime.getHour() * 60 + durationMenuTime.getMinute(); - state.tbrRate = ((double) menu.getAttribute(MenuAttribute.BASAL_RATE)); - } - state.lowBattery = ((boolean) menu.getAttribute(MenuAttribute.LOW_BATTERY)); - state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE)); - // TODO v2, read current base basal rate, which is shown center when no TBR is active. - // Check if that holds true when an extended bolus is running. - // Add a field to PumpStatus, rather than renaming/overloading tbrRate to mean - // either TBR rate or basal rate depending on whether a TBR is active. - } else if (menuType == MenuType.WARNING_OR_ERROR) { - state.errorMsg = (String) menu.getAttribute(MenuAttribute.MESSAGE); - } else if (menuType == MenuType.STOP) { - state.suspended = true; - state.lowBattery = ((boolean) menu.getAttribute(MenuAttribute.LOW_BATTERY)); - state.insulinState = ((int) menu.getAttribute(MenuAttribute.INSULIN_STATE)); - } else { - StringBuilder sb = new StringBuilder(); - for (MenuAttribute menuAttribute : menu.attributes()) { - sb.append(menuAttribute); - sb.append(": "); - sb.append(menu.getAttribute(menuAttribute)); - sb.append("\n"); - } - state.errorMsg = "Pump is on menu " + menuType + ", listing attributes: \n" + sb.toString(); - } - return state; - } } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java index 9ad4aae940..7d6fa98d37 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancelTbrCommand.java @@ -49,7 +49,9 @@ public class CancelTbrCommand extends BaseCommand { } log.debug("Cancelling active TBR of " + pumpState.tbrPercent + "% with " + pumpState.tbrRemainingDuration + " min remaining"); - return new SetTbrCommand(100, 0).execute(); + SetTbrCommand setTbrCommand = new SetTbrCommand(100, 0); + setTbrCommand.setScripter(scripter); + return setTbrCommand.execute(); } catch (CommandException e) { return e.toCommandResult(); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java index 6f489b6bc3..b298fcb41e 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/GetPumpStateCommand.java @@ -4,10 +4,6 @@ import org.monkey.d.ruffy.ruffy.driver.display.MenuType; import java.util.Collections; import java.util.List; -import java.util.TreeSet; - -import de.jotomo.ruffyscripter.PumpState; -import de.jotomo.ruffyscripter.RuffyScripter; import static de.jotomo.ruffyscripter.commands.GetPumpStateCommand.Stepper.runStep; diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index ab376ffd68..17af79a782 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -104,7 +104,7 @@ public class SetTbrCommandAlt extends BaseCommand { private void inputTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long currentPercent = scripter.readBlinkingValue(Long.class, MenuAttribute.BASAL_RATE); + long currentPercent = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); log.debug("Current TBR %: " + currentPercent); long percentageChange = percentage - currentPercent; long percentageSteps = percentageChange / 10; @@ -128,16 +128,16 @@ public class SetTbrCommandAlt extends BaseCommand { private void verifyDisplayedTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long displayedPercentage = scripter.readBlinkingValue(Long.class, MenuAttribute.BASAL_RATE); + long displayedPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); if (displayedPercentage != percentage) { log.debug("Final displayed TBR percentage: " + displayedPercentage); - throw new CommandException().message("Failed to set TBR percentage"); + throw new CommandException().message("Failed to set TBR percentage, requested: " + percentage + ", actual: " + displayedPercentage); } // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long SystemClock.sleep(2000); scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long refreshedDisplayedTbrPecentage = scripter.readBlinkingValue(Long.class, MenuAttribute.BASAL_RATE); + long refreshedDisplayedTbrPecentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); if (displayedPercentage != refreshedDisplayedTbrPecentage) { throw new CommandException().message("Failed to set TBR percentage: " + "percentage changed after input stopped from " diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index d5d056da61..0488671154 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -50,7 +50,7 @@ public class Config { // Combo specific /** use alternate SetTbrCommand (uses the initial implementation) */ - public static final boolean comboUseAlternateSetTbrCommand = false; + public static final boolean comboUseAlternateSetTbrCommand = true; /** very quick hack to split up bolus into 2 U parts, spaced roughly 45s apart */ public static final boolean comboSplitBoluses = false; } From fce696b51d2a75002a649c5789ce8b2a41054dfd Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 11:40:14 +0200 Subject: [PATCH 28/50] Cleanup, fix merge issues. --- .../ruffyscripter/commands/SetTbrCommand.java | 363 ++++++++++-------- .../commands/SetTbrCommandAlt.java | 281 -------------- .../info/nightscout/androidaps/Config.java | 6 - .../plugins/PumpCombo/ComboPlugin.java | 2 +- 4 files changed, 202 insertions(+), 450 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 82a1780df0..15ab5a7b32 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -12,14 +12,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.RuffyScripter; - -import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.MAIN_MENU; -import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_DURATION; -import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_MENU; -import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.TBR_SET; -import static org.monkey.d.ruffy.ruffy.driver.display.MenuType.WARNING_OR_ERROR; - public class SetTbrCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); @@ -61,170 +53,217 @@ public class SetTbrCommand extends BaseCommand { @Override public CommandResult execute() { try { - log.debug("1. going from " + scripter.getCurrentMenu() + " to TBR_MENU"); - int retries = 5; - while (!scripter.goToMainTypeScreen(TBR_MENU, 3000)) { - retries--; - if (retries == 0) - throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.getCurrentMenu()); - SystemClock.sleep(500); - if (scripter.getCurrentMenu().getType() == TBR_MENU) - break; - } - - if (scripter.getCurrentMenu().getType() != TBR_MENU) - throw new CommandException().message("not able to find TBR_MENU: stuck in " + scripter.getCurrentMenu()); - - log.debug("2. entering " + scripter.getCurrentMenu()); - retries = 5; - while (!scripter.enterMenu(TBR_MENU, MenuType.TBR_SET, RuffyScripter.Key.CHECK, 2000)) { - retries--; - if (retries == 0) - throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.getCurrentMenu()); - SystemClock.sleep(500); - if (scripter.getCurrentMenu().getType() == TBR_SET) - break; - if (scripter.getCurrentMenu().getType() == TBR_DURATION) { - scripter.pressMenuKey(); - scripter.waitForScreenUpdate(1000); - } - } - - log.debug("SetTbrCommand: 3. getting/setting basal percentage in " + scripter.getCurrentMenu()); - retries = 30; - - double currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); - while (currentPercentage != percentage && retries >= 0) { - retries--; - currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); - if (currentPercentage != percentage) { - int requestedPercentage = (int) percentage; - int actualPercentage = (int) currentPercentage; - int steps = (requestedPercentage - actualPercentage) / 10; - log.debug("Adjusting basal(" + requestedPercentage + "/" + actualPercentage + ") with " + steps + " steps and " + retries + " retries left"); - scripter.step(steps, (steps < 0 ? RuffyScripter.Key.DOWN : RuffyScripter.Key.UP), 500); - scripter.waitForScreenUpdate(1000); - } - scripter.waitForScreenUpdate(1000); - } - if (currentPercentage < 0 || retries < 0) - throw new CommandException().message("unable to set basal percentage"); - - log.debug("4. checking basal percentage in " + scripter.getCurrentMenu()); - scripter.waitForScreenUpdate(1000); - currentPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE); - if (currentPercentage != percentage) - throw new CommandException().message("Unable to set percentage. Requested: " + percentage + ", value displayed on pump: " + currentPercentage); - - if (currentPercentage != 100) { - log.debug("5. change to TBR_DURATION from " + scripter.getCurrentMenu()); - retries = 5; - while (retries >= 0 && !scripter.enterMenu(TBR_SET, MenuType.TBR_DURATION, RuffyScripter.Key.MENU, 2000)) { - retries--; - if (retries == 0) - throw new CommandException().message("not able to find TBR_SET: stuck in " + scripter.getCurrentMenu()); - SystemClock.sleep(500); - if (scripter.getCurrentMenu().getType() == TBR_DURATION) - break; - if (scripter.getCurrentMenu().getType() == TBR_SET) { - scripter.pressMenuKey(); - scripter.waitForScreenUpdate(1000); - } - } - - log.debug("6. getting/setting duration in " + scripter.getCurrentMenu()); - retries = 30; - - double currentDuration = scripter.readDisplayedDuration(); - while (currentDuration != duration && retries >= 0) { - retries--; - currentDuration = scripter.readDisplayedDuration(); - log.debug("Requested time: " + duration + " actual time: " + currentDuration); - if (currentDuration != duration) { - int requestedDuration = (int) duration; - int actualDuration = (int) currentDuration; - int steps = (requestedDuration - actualDuration) / 15; - if (currentDuration + (steps * 15) < requestedDuration) - steps++; - else if (currentDuration + (steps * 15) > requestedDuration) - steps--; - log.debug("Adjusting duration(" + requestedDuration + "/" + actualDuration + ") with " + steps + " steps and " + retries + " retries left"); - scripter.step(steps, (steps > 0 ? RuffyScripter.Key.UP : RuffyScripter.Key.DOWN), 500); - scripter.waitForScreenUpdate(1000); - } - } - if (currentDuration < 0 || retries < 0) - throw new CommandException().message("unable to set duration, requested:" + duration + ", displayed on pump: " + currentDuration); - - log.debug("7. checking duration in " + scripter.getCurrentMenu()); - scripter.waitForScreenUpdate(1000); - currentDuration = scripter.readDisplayedDuration(); - if (currentDuration != duration) - throw new CommandException().message("wrong duration! Requested: " + duration + ", displayed on pump: " + currentDuration); - } - - log.debug("8. confirming TBR om " + scripter.getCurrentMenu()); - retries = 5; - while (retries >= 0 && (scripter.getCurrentMenu().getType() == TBR_DURATION || scripter.getCurrentMenu().getType() == TBR_SET)) { - retries--; - scripter.pressCheckKey(); - scripter.waitForScreenUpdate(1000); - } - if (retries < 0 || scripter.getCurrentMenu().getType() == TBR_DURATION || scripter.getCurrentMenu().getType() == TBR_SET) - throw new CommandException().message("failed setting basal!"); - retries = 10; - boolean cancelledError = true; - if (percentage == 100) - cancelledError = false; - while (retries >= 0 && scripter.getCurrentMenu().getType() != MAIN_MENU) { - // TODO how probable is it, that a totally unrelated error (like occlusion alert) - // is raised at this point, which we'd cancel together with the TBR cancelled alert? - if (percentage == 100 && scripter.getCurrentMenu().getType() == WARNING_OR_ERROR) { - // TODO extract method confirmAlert(alert) - scripter.pressCheckKey(); - retries++; - cancelledError = true; - scripter.waitForScreenUpdate(1000); - } else { - retries--; - if (scripter.getCurrentMenu().getType() == MAIN_MENU && cancelledError) - break; - } - } - - log.debug("9. verifying the main menu display the TBR we just set/cancelled"); - if (retries < 0 || scripter.getCurrentMenu().getType() != MAIN_MENU) - throw new CommandException().message("failed going to main!"); - - Object percentageObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); - Object durationObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); + enterTbrMenu(); + inputTbrPercentage(); + verifyDisplayedTbrPercentage(); if (percentage == 100) { - if (durationObj != null) - throw new CommandException().message("TBR cancelled, but main menu shows a running TBR"); + cancelTbrAndConfirmCancellationWarning(); + } else { + // switch to TBR_DURATION menu by pressing menu key + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + scripter.pressMenuKey(); + scripter.waitForMenuUpdate(); + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - return new CommandResult().success(true).enacted(true).message("TBR was cancelled"); + inputTbrDuration(); + verifyDisplayedTbrDuration(); + + // confirm TBR + scripter.pressCheckKey(); + scripter.waitForMenuToBeLeft(MenuType.TBR_DURATION); } - if (percentageObj == null || !(percentageObj instanceof Double)) - throw new CommandException().message("not percentage"); + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, + "Pump did not return to MAIN_MEU after setting TBR. " + + "Check pump manually, the TBR might not have been set/cancelled."); - if (((double) percentageObj) != percentage) - throw new CommandException().message("wrong percentage set!"); + // check main menu shows the same values we just set + if (percentage == 100) { + verifyMainMenuShowsNoActiveTbr(); + return new CommandResult().success(true).enacted(true).message("TBR was cancelled"); + } else { + verifyMainMenuShowsExpectedTbrActive(); + return new CommandResult().success(true).enacted(true).message( + String.format(Locale.US, "TBR set to %d%% for %d min", percentage, duration)); + } - if (durationObj == null || !(durationObj instanceof MenuTime)) - throw new CommandException().message("not time"); + } catch (CommandException e) { + return e.toCommandResult(); + } + } - MenuTime t = (MenuTime) durationObj; - if (t.getMinute() + (60 * t.getHour()) > duration || t.getMinute() + (60 * t.getHour()) < duration - 5) - throw new CommandException().message("wrong time set!"); + private void enterTbrMenu() { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + scripter.navigateToMenu(MenuType.TBR_MENU); + scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU); + scripter.pressCheckKey(); + scripter.waitForMenuUpdate(); + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + } + + private void inputTbrPercentage() { + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + long currentPercent = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); + log.debug("Current TBR %: " + currentPercent); + long percentageChange = percentage - currentPercent; + long percentageSteps = percentageChange / 10; + boolean increasePercentage = true; + if (percentageSteps < 0) { + increasePercentage = false; + percentageSteps = Math.abs(percentageSteps); + } + log.debug("Pressing " + (increasePercentage ? "up" : "down") + " " + percentageSteps + " times"); + for (int i = 0; i < percentageSteps; i++) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + log.debug("Push #" + (i + 1)); + if (increasePercentage) scripter.pressUpKey(); + else scripter.pressDownKey(); + SystemClock.sleep(100); + } + // Give the pump time to finish any scrolling that might still be going on, can take + // up to 1100ms. Plus some extra time to be sure + SystemClock.sleep(2000); + } + + private void verifyDisplayedTbrPercentage() { + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + long displayedPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); + if (displayedPercentage != percentage) { + log.debug("Final displayed TBR percentage: " + displayedPercentage); + throw new CommandException().message("Failed to set TBR percentage, requested: " + percentage + ", actual: " + displayedPercentage); + } + + // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long + SystemClock.sleep(2000); + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + long refreshedDisplayedTbrPecentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); + if (displayedPercentage != refreshedDisplayedTbrPecentage) { + throw new CommandException().message("Failed to set TBR percentage: " + + "percentage changed after input stopped from " + + displayedPercentage + " -> " + refreshedDisplayedTbrPecentage); + } + } + + private void inputTbrDuration() { + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + long currentDuration = scripter.readDisplayedDuration(); + if (currentDuration % 15 != 0) { + // The duration displayed is how long an active TBR will still run, + // which might be something like 0:13, hence not in 15 minute steps. + // Pressing up will go to the next higher 15 minute step. + // Don't press down, from 0:13 it can't go down, so press up. + // Pressing up from 23:59 works to go to 24:00. + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + scripter.pressUpKey(); + scripter.waitForMenuUpdate(); + currentDuration = scripter.readDisplayedDuration(); + } + log.debug("Current TBR duration: " + currentDuration); + long durationChange = duration - currentDuration; + long durationSteps = durationChange / 15; + boolean increaseDuration = true; + if (durationSteps < 0) { + increaseDuration = false; + durationSteps = Math.abs(durationSteps); + } + log.debug("Pressing " + (increaseDuration ? "up" : "down") + " " + durationSteps + " times"); + for (int i = 0; i < durationSteps; i++) { + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + if (increaseDuration) scripter.pressUpKey(); + else scripter.pressDownKey(); + SystemClock.sleep(100); + log.debug("Push #" + (i + 1)); + } + // Give the pump time to finish any scrolling that might still be going on, can take + // up to 1100ms. Plus some extra time to be sure + SystemClock.sleep(2000); + } + + private void verifyDisplayedTbrDuration() { + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + long displayedDuration = scripter.readDisplayedDuration(); + if (displayedDuration != duration) { + log.debug("Final displayed TBR duration: " + displayedDuration); + throw new CommandException().message("Failed to set TBR duration"); + } + + // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long + SystemClock.sleep(2000); + scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + long refreshedDisplayedTbrDuration = scripter.readDisplayedDuration(); + if (displayedDuration != refreshedDisplayedTbrDuration) { + throw new CommandException().message("Failed to set TBR duration: " + + "duration changed after input stopped from " + + displayedDuration + " -> " + refreshedDisplayedTbrDuration); + } + } - return new CommandResult().success(true).enacted(true).message( - String.format(Locale.US, "TBR set to %d%% for %d min", percentage, duration)); - } catch (Exception e) { - log.error("got exception: ", e); - return new CommandResult().success(false).message(e.getMessage()).exception(e); + + private void cancelTbrAndConfirmCancellationWarning() { + // confirm entered TBR + scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + scripter.pressCheckKey(); + + // A "TBR CANCELLED alert" is only raised by the pump when the remaining time is + // greater than 60s (displayed as 0:01, the pump goes from there to finished. + // We could read the remaining duration from MAIN_MENU, but by the time we're here, + // the pumup could have moved from 0:02 to 0:01, so instead, check if a "TBR CANCELLED" alert + // is raised and if so dismiss it + long inFiveSeconds = System.currentTimeMillis() + 5 * 1000; + boolean alertProcessed = false; + while (System.currentTimeMillis() < inFiveSeconds && !alertProcessed) { + if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { + // Check the raised alarm is TBR CANCELLED, so we're not accidentally cancelling + // a different alarm that might be raised at the same time. + // Note that the message is permanently displayed, while the error code is blinking. + // A wait till the error code can be read results in the code hanging, despite + // menu updates coming in, so just check the message. + // TODO v2 this only works when the pump's language is English + String errorMsg = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE); + if (!errorMsg.equals("TBR CANCELLED")) { + throw new CommandException().success(false).enacted(false) + .message("An alert other than the expected TBR CANCELLED was raised by the pump: " + + errorMsg + ". Please check the pump."); + } + // confirm "TBR CANCELLED" alert + scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); + scripter.pressCheckKey(); + // dismiss "TBR CANCELLED" alert + scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); + scripter.pressCheckKey(); + scripter.waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR); + alertProcessed = true; + } + SystemClock.sleep(10); + } + } + + private void verifyMainMenuShowsNoActiveTbr() { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + Double tbrPercentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); + boolean runtimeDisplayed = scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME); + if (tbrPercentage != 100 || runtimeDisplayed) { + throw new CommandException().message("Cancelling TBR failed, TBR is still set according to MAIN_MENU"); + } + } + + private void verifyMainMenuShowsExpectedTbrActive() { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + // new TBR set; percentage and duration must be displayed ... + if (!scripter.getCurrentMenu().attributes().contains(MenuAttribute.TBR) || + !scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME)) { + throw new CommandException().message("Setting TBR failed, according to MAIN_MENU no TBR is active"); + } + Double mmTbrPercentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); + MenuTime mmTbrDuration = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); + // ... and be the same as what we set + // note that displayed duration might have already counted down, e.g. from 30 minutes to + // 29 minutes and 59 seconds, so that 29 minutes are displayed + int mmTbrDurationInMinutes = mmTbrDuration.getHour() * 60 + mmTbrDuration.getMinute(); + if (mmTbrPercentage != percentage || (mmTbrDurationInMinutes != duration && mmTbrDurationInMinutes + 1 != duration)) { + throw new CommandException().message("Setting TBR failed, TBR in MAIN_MENU differs from expected"); } } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java index 1a72e7153c..e69de29bb2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java @@ -1,281 +0,0 @@ -package de.jotomo.ruffyscripter.commands; - -import android.os.SystemClock; - -import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; -import org.monkey.d.ruffy.ruffy.driver.display.MenuType; -import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; -import java.util.Locale; - -public class SetTbrCommandAlt extends BaseCommand { - private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); - - private final long percentage; - private final long duration; - - public SetTbrCommandAlt(long percentage, long duration) { - this.percentage = percentage; - this.duration = duration; - } - - @Override - public List validateArguments() { - List violations = new ArrayList<>(); - - if (percentage % 10 != 0) { - violations.add("TBR percentage must be set in 10% steps"); - } - if (percentage < 0 || percentage > 500) { - violations.add("TBR percentage must be within 0-500%"); - } - - if (percentage != 100) { - if (duration % 15 != 0) { - violations.add("TBR duration can only be set in 15 minute steps"); - } - if (duration > 60 * 24) { - violations.add("Maximum TBR duration is 24 hours"); - } - } - - if (percentage == 0 && duration > 120) { - violations.add("Max allowed zero-temp duration is 2h"); - } - - return violations; - } - - @Override - public CommandResult execute() { - try { - enterTbrMenu(); - inputTbrPercentage(); - verifyDisplayedTbrPercentage(); - - if (percentage == 100) { - cancelTbrAndConfirmCancellationWarning(); - } else { - // switch to TBR_DURATION menu by pressing menu key - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - scripter.pressMenuKey(); - scripter.waitForMenuUpdate(); - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - - inputTbrDuration(); - verifyDisplayedTbrDuration(); - - // confirm TBR - scripter.pressCheckKey(); - scripter.waitForMenuToBeLeft(MenuType.TBR_DURATION); - } - - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, - "Pump did not return to MAIN_MEU after setting TBR. " + - "Check pump manually, the TBR might not have been set/cancelled."); - - // check main menu shows the same values we just set - if (percentage == 100) { - verifyMainMenuShowsNoActiveTbr(); - return new CommandResult().success(true).enacted(true).message("TBR was cancelled"); - } else { - verifyMainMenuShowsExpectedTbrActive(); - return new CommandResult().success(true).enacted(true).message( - String.format(Locale.US, "TBR set to %d%% for %d min", percentage, duration)); - } - - } catch (CommandException e) { - return e.toCommandResult(); - } - } - - private void enterTbrMenu() { - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - scripter.navigateToMenu(MenuType.TBR_MENU); - scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU); - scripter.pressCheckKey(); - scripter.waitForMenuUpdate(); - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - } - - private void inputTbrPercentage() { - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long currentPercent = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); - log.debug("Current TBR %: " + currentPercent); - long percentageChange = percentage - currentPercent; - long percentageSteps = percentageChange / 10; - boolean increasePercentage = true; - if (percentageSteps < 0) { - increasePercentage = false; - percentageSteps = Math.abs(percentageSteps); - } - log.debug("Pressing " + (increasePercentage ? "up" : "down") + " " + percentageSteps + " times"); - for (int i = 0; i < percentageSteps; i++) { - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - log.debug("Push #" + (i + 1)); - if (increasePercentage) scripter.pressUpKey(); - else scripter.pressDownKey(); - SystemClock.sleep(100); - if (increasePercentage) scripter.pressUpKey(); - else scripter.pressDownKey(); - SystemClock.sleep(100); - log.debug("Push #" + (i + 1)); - } - // Give the pump time to finish any scrolling that might still be going on, can take - // up to 1100ms. Plus some extra time to be sure - SystemClock.sleep(2000); - } - - private void verifyDisplayedTbrPercentage() { - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long displayedPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); - if (displayedPercentage != percentage) { - log.debug("Final displayed TBR percentage: " + displayedPercentage); - throw new CommandException().message("Failed to set TBR percentage, requested: " + percentage + ", actual: " + displayedPercentage); - } - - // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long - SystemClock.sleep(2000); - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long refreshedDisplayedTbrPecentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); - if (displayedPercentage != refreshedDisplayedTbrPecentage) { - throw new CommandException().message("Failed to set TBR percentage: " + - "percentage changed after input stopped from " - + displayedPercentage + " -> " + refreshedDisplayedTbrPecentage); - } - } - - private void inputTbrDuration() { - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long currentDuration = scripter.readDisplayedDuration(); - if (currentDuration % 15 != 0) { - // The duration displayed is how long an active TBR will still run, - // which might be something like 0:13, hence not in 15 minute steps. - // Pressing up will go to the next higher 15 minute step. - // Don't press down, from 0:13 it can't go down, so press up. - // Pressing up from 23:59 works to go to 24:00. - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - scripter.pressUpKey(); - scripter.waitForMenuUpdate(); - currentDuration = scripter.readDisplayedDuration(); - } - log.debug("Current TBR duration: " + currentDuration); - long durationChange = duration - currentDuration; - long durationSteps = durationChange / 15; - boolean increaseDuration = true; - if (durationSteps < 0) { - increaseDuration = false; - durationSteps = Math.abs(durationSteps); - } - log.debug("Pressing " + (increaseDuration ? "up" : "down") + " " + durationSteps + " times"); - for (int i = 0; i < durationSteps; i++) { - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - if (increaseDuration) scripter.pressUpKey(); - else scripter.pressDownKey(); - SystemClock.sleep(100); - log.debug("Push #" + (i + 1)); - } - // Give the pump time to finish any scrolling that might still be going on, can take - // up to 1100ms. Plus some extra time to be sure - SystemClock.sleep(2000); - } - - private void verifyDisplayedTbrDuration() { - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long displayedDuration = scripter.readDisplayedDuration(); - if (displayedDuration != duration) { - log.debug("Final displayed TBR duration: " + displayedDuration); - throw new CommandException().message("Failed to set TBR duration"); - } - - // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long - SystemClock.sleep(2000); - scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - long refreshedDisplayedTbrDuration = scripter.readDisplayedDuration(); - if (displayedDuration != refreshedDisplayedTbrDuration) { - throw new CommandException().message("Failed to set TBR duration: " + - "duration changed after input stopped from " - + displayedDuration + " -> " + refreshedDisplayedTbrDuration); - } - } - - - - private void cancelTbrAndConfirmCancellationWarning() { - // confirm entered TBR - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - scripter.pressCheckKey(); - - // A "TBR CANCELLED alert" is only raised by the pump when the remaining time is - // greater than 60s (displayed as 0:01, the pump goes from there to finished. - // We could read the remaining duration from MAIN_MENU, but by the time we're here, - // the pumup could have moved from 0:02 to 0:01, so instead, check if a "TBR CANCELLED" alert - // is raised and if so dismiss it - long inFiveSeconds = System.currentTimeMillis() + 5 * 1000; - boolean alertProcessed = false; - while (System.currentTimeMillis() < inFiveSeconds && !alertProcessed) { - if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { - // Check the raised alarm is TBR CANCELLED, so we're not accidentally cancelling - // a different alarm that might be raised at the same time. - // Note that the message is permanently displayed, while the error code is blinking. - // A wait till the error code can be read results in the code hanging, despite - // menu updates coming in, so just check the message. - // TODO v2 this only works when the pump's language is English - String errorMsg = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE); - if (!errorMsg.equals("TBR CANCELLED")) { - throw new CommandException().success(false).enacted(false) - .message("An alert other than the expected TBR CANCELLED was raised by the pump: " - + errorMsg + ". Please check the pump."); - } - // confirm "TBR CANCELLED" alert - scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); - scripter.pressCheckKey(); - // dismiss "TBR CANCELLED" alert - scripter.verifyMenuIsDisplayed(MenuType.WARNING_OR_ERROR); - scripter.pressCheckKey(); - scripter.waitForMenuToBeLeft(MenuType.WARNING_OR_ERROR); - alertProcessed = true; - } - SystemClock.sleep(10); - } - } - - private void verifyMainMenuShowsNoActiveTbr() { - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - Double tbrPercentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); - boolean runtimeDisplayed = scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME); - if (tbrPercentage != 100 || runtimeDisplayed) { - throw new CommandException().message("Cancelling TBR failed, TBR is still set according to MAIN_MENU"); - } - } - - private void verifyMainMenuShowsExpectedTbrActive() { - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - // new TBR set; percentage and duration must be displayed ... - if (!scripter.getCurrentMenu().attributes().contains(MenuAttribute.TBR) || - !scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME)) { - throw new CommandException().message("Setting TBR failed, according to MAIN_MENU no TBR is active"); - } - Double mmTbrPercentage = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR); - MenuTime mmTbrDuration = (MenuTime) scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); - // ... and be the same as what we set - // note that displayed duration might have already counted down, e.g. from 30 minutes to - // 29 minutes and 59 seconds, so that 29 minutes are displayed - int mmTbrDurationInMinutes = mmTbrDuration.getHour() * 60 + mmTbrDuration.getMinute(); - if (mmTbrPercentage != percentage || (mmTbrDurationInMinutes != duration && mmTbrDurationInMinutes + 1 != duration)) { - throw new CommandException().message("Setting TBR failed, TBR in MAIN_MENU differs from expected"); - } - } - - @Override - public String toString() { - return "SetTbrCommand{" + - "percentage=" + percentage + - ", duration=" + duration + - '}'; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 0488671154..7f3aad2f93 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -47,10 +47,4 @@ public class Config { public static final boolean logDanaBTComm = true; public static final boolean logDanaMessageDetail = true; public static final boolean logDanaSerialEngine = true; - - // Combo specific - /** use alternate SetTbrCommand (uses the initial implementation) */ - public static final boolean comboUseAlternateSetTbrCommand = true; - /** very quick hack to split up bolus into 2 U parts, spaced roughly 45s apart */ - public static final boolean comboSplitBoluses = false; } 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 7c7bce1e2d..78b9129b28 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 @@ -12,7 +12,6 @@ import android.net.Uri; import android.os.IBinder; import android.os.SystemClock; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; @@ -213,6 +212,7 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf @Override public void onServiceDisconnected(ComponentName name) { + // TODO stop? log.debug("ruffy service disconnected"); // try to reconnect ruffy service unless unbind was explicitly requested // via unbindRuffyService From 99b98f1dec8b85f045da8f184fc9f0b8596f049b Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 11:46:08 +0200 Subject: [PATCH 29/50] Set custom version --- app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 9a994d38cb..174799d5c4 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -44,7 +44,7 @@ android { minSdkVersion 21 targetSdkVersion 23 versionCode 1500 - version "1.5h-combo-dev" + version "1.5h-combo-dev-jotomo" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", generateGitBuild() } From bc68f2cc1b3ba10d4cc7a29397ac826f1a83a6a4 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 11:46:14 +0200 Subject: [PATCH 30/50] Better log output. --- .../java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 15ab5a7b32..9f390d87f5 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -185,7 +185,7 @@ public class SetTbrCommand extends BaseCommand { long displayedDuration = scripter.readDisplayedDuration(); if (displayedDuration != duration) { log.debug("Final displayed TBR duration: " + displayedDuration); - throw new CommandException().message("Failed to set TBR duration"); + throw new CommandException().message("Failed to set TBR duration, requested: " + duration + ", actual: " + displayedDuration); } // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long From 4046305380412d9601eba926973130fab9c71573 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 12:00:30 +0200 Subject: [PATCH 31/50] Build against ruffy b916a900c0899ef58ad58c7427d1c30d3c8731f4. --- .../d/ruffy/ruffy/driver/IRTHandler.aidl | 9 ++--- .../d/ruffy/ruffy/driver/IRuffyService.aidl | 10 ++---- .../d/ruffy/ruffy/driver/package-info.java | 1 + .../jotomo/ruffyscripter/RuffyScripter.java | 36 +++++-------------- 4 files changed, 15 insertions(+), 41 deletions(-) create mode 100644 app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl index b6a07226b8..996b10b666 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl @@ -10,17 +10,12 @@ interface IRTHandler { void fail(String message); void requestBluetooth(); - boolean canDisconnect(); void rtStopped(); void rtStarted(); void rtClearDisplay(); void rtUpdateDisplay(in byte[] quarter, int which); - void rtDisplayHandleMenu(in Menu menu, in int sequence); - void rtDisplayHandleNoMenu(in int sequence); - - void keySent(in int sequence); - - String getServiceIdentifier(); + void rtDisplayHandleMenu(in Menu menu); + void rtDisplayHandleNoMenu(); } diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl index f4879445b7..6c988aa038 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl @@ -6,22 +6,18 @@ import org.monkey.d.ruffy.ruffy.driver.IRTHandler; interface IRuffyService { - void addHandler(IRTHandler handler); - void removeHandler(IRTHandler handler); + void setHandler(IRTHandler handler); /** Connect to the pump * * @return 0 if successful, -1 otherwise */ - int doRTConnect(IRTHandler handler); + int doRTConnect(); /** Disconnect from the pump */ - void doRTDisconnect(IRTHandler handler); + void doRTDisconnect(); - /*What's the meaning of 'changed'? - * changed means if a button state has been changed, like btton pressed is a change and button release another*/ void rtSendKey(byte keyCode, boolean changed); void resetPairing(); boolean isConnected(); - boolean isBoundToPump(); } diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java new file mode 100644 index 0000000000..ab1def7407 --- /dev/null +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java @@ -0,0 +1 @@ +//b916a900c0899ef58ad58c7427d1c30d3c8731f4 \ No newline at end of file diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 4bf0f85833..4c7111033d 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -51,6 +51,7 @@ public class RuffyScripter { public void start(IRuffyService newService) { try { +/* if (ruffyService != null) { try { ruffyService.removeHandler(mHandler); @@ -58,6 +59,7 @@ public class RuffyScripter { // ignore } } +*/ if (newService != null) { this.ruffyService = newService; // TODO this'll be done better in v2 via ConnectionManager @@ -65,7 +67,7 @@ public class RuffyScripter { idleDisconnectMonitorThread.start(); } started = true; - newService.addHandler(mHandler); + newService.setHandler(mHandler); } } catch (Exception e) { log.error("Unhandled exception starting RuffyScripter", e); @@ -95,7 +97,7 @@ public class RuffyScripter { log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout"); lastDisconnected = now; canDisconnect = true; - ruffyService.doRTDisconnect(mHandler); + ruffyService.doRTDisconnect(); connected = false; // don't attempt anything fancy in the next 10s, let the pump settle SystemClock.sleep(10 * 1000); @@ -132,11 +134,6 @@ public class RuffyScripter { log.trace("Ruffy invoked requestBluetooth callback"); } - @Override - public boolean canDisconnect() throws RemoteException { - return canDisconnect; - } - @Override public void rtStopped() throws RemoteException { log.debug("rtStopped callback invoked"); @@ -159,7 +156,7 @@ public class RuffyScripter { } @Override - public void rtDisplayHandleMenu(Menu menu, int sequence) throws RemoteException { + public void rtDisplayHandleMenu(Menu menu) throws RemoteException { // method is called every ~500ms log.debug("rtDisplayHandleMenu: " + menu); @@ -182,26 +179,9 @@ public class RuffyScripter { } @Override - public void rtDisplayHandleNoMenu(int sequence) throws RemoteException { + public void rtDisplayHandleNoMenu() throws RemoteException { log.debug("rtDisplayHandleNoMenu callback invoked"); } - - - @Override - public void keySent(int sequence) throws RemoteException { - synchronized (keylock) { - if (keynotwait > 0) - keynotwait--; - else - keylock.notify(); - } - } - - @Override - public String getServiceIdentifier() throws RemoteException { - return this.toString(); - } - }; public boolean isPumpBusy() { @@ -209,12 +189,14 @@ public class RuffyScripter { } public void unbind() { + /* if (ruffyService != null) try { ruffyService.removeHandler(mHandler); } catch (Exception e) { // ignore } + */ this.ruffyService = null; } @@ -378,7 +360,7 @@ public class RuffyScripter { } canDisconnect = false; - boolean connectInitSuccessful = ruffyService.doRTConnect(mHandler) == 0; + boolean connectInitSuccessful = ruffyService.doRTConnect() == 0; log.debug("Connect init successful: " + connectInitSuccessful); log.debug("Waiting for first menu update to be sent"); // Note: there was an 'if(currentMenu == null)' around the next call, since From fdab7daf2cc061854574e422098cbd73e2e18f9f Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sat, 19 Aug 2017 23:05:20 +0200 Subject: [PATCH 32/50] Only display Extended Bolus tab in Treatments if pump supports them. (cherry picked from commit e862c35) --- .../androidaps/plugins/Treatments/TreatmentsFragment.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java index 1bf66ca5ec..9f839e6fef 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Treatments/TreatmentsFragment.java @@ -47,6 +47,9 @@ public class TreatmentsFragment extends Fragment implements View.OnClickListener profileSwitchTab = (TextView) view.findViewById(R.id.treatments_profileswitches); treatmentsTab.setOnClickListener(this); extendedBolusesTab.setOnClickListener(this); + if (!MainApp.getConfigBuilder().getPumpDescription().isExtendedBolusCapable) { + extendedBolusesTab.setVisibility(View.GONE); + } tempBasalsTab.setOnClickListener(this); tempTargetTab.setOnClickListener(this); profileSwitchTab.setOnClickListener(this); From c2ae0b7289d55c0fc2266bdb6f0863ac17e38f45 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 12:36:15 +0200 Subject: [PATCH 33/50] Cleanup. --- .../jotomo/ruffyscripter/RuffyScripter.java | 28 +++++++------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 4c7111033d..7630907160 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -44,9 +44,6 @@ public class RuffyScripter { private boolean started = false; - private final Object keylock = new Object(); - private int keynotwait = 0; - private final Object screenlock = new Object(); public void start(IRuffyService newService) { @@ -79,7 +76,6 @@ public class RuffyScripter { return started; } - private boolean canDisconnect = false; private volatile boolean connected = false; private volatile long lastDisconnected = 0; @@ -96,13 +92,10 @@ public class RuffyScripter { && now > lastDisconnected + 15 * 1000) { log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout"); lastDisconnected = now; - canDisconnect = true; ruffyService.doRTDisconnect(); connected = false; // don't attempt anything fancy in the next 10s, let the pump settle SystemClock.sleep(10 * 1000); - } else { - canDisconnect = false; } } catch (Exception e) { // TODO do we need to catch this exception somewhere else too? right now it's @@ -359,7 +352,6 @@ public class RuffyScripter { SystemClock.sleep(10 * 1000); } - canDisconnect = false; boolean connectInitSuccessful = ruffyService.doRTConnect() == 0; log.debug("Connect init successful: " + connectInitSuccessful); log.debug("Waiting for first menu update to be sent"); @@ -606,17 +598,17 @@ public class RuffyScripter { private void pressKey(final byte key, long timeout) { try { ruffyService.rtSendKey(key, true); - //SystemClock.sleep(200); + SystemClock.sleep(200); ruffyService.rtSendKey(Key.NO_KEY, true); - if (timeout > 0) { - synchronized (keylock) { - keylock.wait(timeout); - } - } else { - synchronized (keylock) { - keynotwait++; - } - } +// if (timeout > 0) { +// synchronized (keylock) { +// keylock.wait(timeout); +// } +// } else { +// synchronized (keylock) { +// keynotwait++; +// } +// } } catch (Exception e) { throw new CommandException().exception(e).message("Error while pressing buttons"); } From 1d53305ff92de74c77fa754e4e917acfcbad2c23 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 12:43:52 +0200 Subject: [PATCH 34/50] Use string resource. --- .../info/nightscout/androidaps/plugins/Loop/LoopPlugin.java | 2 +- .../nightscout/androidaps/plugins/Wear/ActionStringHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java index 6e459a03b2..2ad9ab1ffb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Loop/LoopPlugin.java @@ -257,7 +257,7 @@ public class LoopPlugin implements PluginBase { return; } - // check rate for constrais + // check rate for constraints final APSResult resultAfterConstraints = result.clone(); resultAfterConstraints.rate = constraintsInterface.applyBasalConstraints(resultAfterConstraints.rate); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java index e60e30d158..a0760a84ee 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/Wear/ActionStringHandler.java @@ -440,7 +440,7 @@ public class ActionStringHandler { ret += "OPEN LOOP\n"; } final APSInterface aps = MainApp.getConfigBuilder().getActiveAPS(); - ret += "APS: " + ((aps == null) ? "NO APS SELECTED!" : ((PluginBase) aps).getName()); + ret += "APS: " + ((aps == null) ? R.string.noapsselected : ((PluginBase) aps).getName()); if (activeloop.lastRun != null) { if (activeloop.lastRun.lastAPSRun != null) ret += "\nLast Run: " + DateUtil.timeString(activeloop.lastRun.lastAPSRun); From ff088ddd3f5661abe7dd692216bafc73384be43d Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 13:08:17 +0200 Subject: [PATCH 35/50] ComboPlugin: don't implement ConstraintsInterface, ProfileInterface. --- .../plugins/PumpCombo/ComboPlugin.java | 89 ++----------------- 1 file changed, 6 insertions(+), 83 deletions(-) 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 78b9129b28..2f66bbd33e 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 @@ -62,7 +62,7 @@ import info.nightscout.utils.ToastUtils; /** * Created by mike on 05.08.2016. */ -public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterface, ProfileInterface { +public class ComboPlugin implements PluginBase, PumpInterface { public static final String COMBO_MAX_TEMP_PERCENT_SP = "combo_maxTempPercent"; private static Logger log = LoggerFactory.getLogger(ComboPlugin.class); @@ -513,6 +513,11 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf int adjustedPercent = percent; + if (adjustedPercent > pumpDescription.maxTempPercent) { + log.debug("Reducing requested TBR to the maximum support by the pump: " + percent + " -> " + pumpDescription.maxTempPercent); + adjustedPercent = pumpDescription.maxTempPercent; + } + if (adjustedPercent % 10 != 0) { Long rounded = Math.round(adjustedPercent / 10d) * 10; log.debug("Rounded requested percentage:" + adjustedPercent + " -> " + rounded); @@ -693,7 +698,6 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf public void updateCapabilities() { - // if Android is sluggish this might get called before ruffy is bound if (ruffyScripter == null) { log.warn("Rejecting call to RefreshDataFromPump: ruffy service not bound (yet)"); @@ -716,85 +720,4 @@ public class ComboPlugin implements PluginBase, PumpInterface, ConstraintsInterf ToastUtils.showToastInUiThread(MainApp.instance(), "No success."); } } - - @Override - public boolean isLoopEnabled() { - return true; - } - - @Override - public boolean isClosedModeEnabled() { - return true; - } - - @Override - public boolean isAutosensModeEnabled() { - return true; - } - - @Override - public boolean isAMAModeEnabled() { - return true; - } - - @Override - public Double applyBasalConstraints(Double absoluteRate) { - double origAbsoluteRate = absoluteRate; - // TODO GL#56, #42 - if (absoluteRate > 25d) { - absoluteRate = 25d; - if (Config.logConstraintsChanges && origAbsoluteRate != Constants.basalAbsoluteOnlyForCheckLimit) - log.debug("Limiting rate " + origAbsoluteRate + "U/h by pump constraint to " + absoluteRate + "U/h"); - } - return absoluteRate; - } - - @Override - public Integer applyBasalConstraints(Integer percentRate) { - Integer origPercentRate = percentRate; - if (percentRate < 0) percentRate = 0; - if (percentRate > pumpDescription.maxTempPercent) - percentRate = pumpDescription.maxTempPercent; - if (!Objects.equals(percentRate, origPercentRate) && Config.logConstraintsChanges && !Objects.equals(origPercentRate, Constants.basalPercentOnlyForCheckLimit)) - log.debug("Limiting percent rate " + origPercentRate + "% to " + percentRate + "%"); - return percentRate; - } - - @Override - public Double applyBolusConstraints(Double insulin) { - // Hard pump limits are not directly readable from pump and serve as a fail safe. - // TODO GL#56, #42 - return insulin; - } - - @Override - public Integer applyCarbsConstraints(Integer carbs) { - // pump is oblivious to carbs - return carbs; - } - - @Override - public Double applyMaxIOBConstraints(Double maxIob) { - // pump is oblivious to IOB - return maxIob; - } - - @Nullable - @Override - public ProfileStore getProfile() { - // TODO GL#13 - return null; - } - - @Override - public String getUnits() { - // pump has no concept of senors/blood glucose - return Constants.MGDL; - } - - @Override - public String getProfileName() { - // TODO GL#13 - return "Profile 1"; - } } \ No newline at end of file From 40941996c2370a5143c120c71a7e0fe50aaab66a Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 13:54:07 +0200 Subject: [PATCH 36/50] Don't provide status JSON until we can provide it properly. --- .../nightscout/androidaps/plugins/PumpCombo/ComboPlugin.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 2f66bbd33e..9f0e227cc5 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 @@ -625,7 +625,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { // TODO v2 add battery, reservoir info when we start reading that and clean up the code @Override public JSONObject getJSONStatus() { - if (pump.lastCmdTime.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { + if (true) { //pump.lastCmdTime.getTime() + 5 * 60 * 1000L < System.currentTimeMillis()) { return null; } From c8f7b535c2b7d2fb8ba7ca0d09ef76d8b3e49656 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 13:39:29 +0200 Subject: [PATCH 37/50] Remove code to determine pump capabilities for the time being. --- .../ruffyscripter/PumpCapabilities.java | 23 --- .../ruffyscripter/commands/CommandResult.java | 7 - .../DetermineCapabilitiesCommand.java | 160 ------------------ .../plugins/PumpCombo/ComboFragment.java | 32 ---- .../plugins/PumpCombo/ComboPlugin.java | 26 --- .../main/res/layout/combopump_fragment.xml | 54 ------ 6 files changed, 302 deletions(-) delete mode 100644 app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java b/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java deleted file mode 100644 index 50016db80e..0000000000 --- a/app/src/main/java/de/jotomo/ruffyscripter/PumpCapabilities.java +++ /dev/null @@ -1,23 +0,0 @@ -package de.jotomo.ruffyscripter; - -/** - * Created by adrian on 26/07/17. - *

- * Contains the capabilities of the current pump model. - */ - -public class PumpCapabilities { - public long maxTempPercent; - - public PumpCapabilities maxTempPercent(long maxTempPercent) { - this.maxTempPercent = maxTempPercent; - return this; - } - - @Override - public String toString() { - return "PumpCapabilities{" + - "maxTempPercent=" + maxTempPercent + - '}'; - } -} diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java index b759eb32dc..9d1bbb321e 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CommandResult.java @@ -3,7 +3,6 @@ package de.jotomo.ruffyscripter.commands; import java.util.Date; import de.jotomo.ruffyscripter.History; -import de.jotomo.ruffyscripter.PumpCapabilities; import de.jotomo.ruffyscripter.PumpState; public class CommandResult { @@ -14,7 +13,6 @@ public class CommandResult { public String message; public PumpState state; public History history; - public PumpCapabilities capabilities; public String duration; public CommandResult() { @@ -60,11 +58,6 @@ public class CommandResult { return this; } - public CommandResult capabilities(PumpCapabilities capabilities) { - this.capabilities = capabilities; - return this; - } - @Override public String toString() { return "CommandResult{" + diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java index 172a7742e1..e69de29bb2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java @@ -1,160 +0,0 @@ -package de.jotomo.ruffyscripter.commands; - -import android.os.SystemClock; - -import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; -import org.monkey.d.ruffy.ruffy.driver.display.MenuType; -import org.monkey.d.ruffy.ruffy.driver.display.menu.MenuTime; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Collections; -import java.util.List; - -import de.jotomo.ruffyscripter.PumpCapabilities; - - -public class DetermineCapabilitiesCommand extends BaseCommand { - private static final Logger log = LoggerFactory.getLogger(DetermineCapabilitiesCommand.class); - public static final int UP_STEPS = 75; - public static final int RETRIES = 5; - - @Override - public List validateArguments() { - return Collections.emptyList(); - } - - @Override - public CommandResult execute() { - try { - - //read main menu 100% or TBR? Read remaining duration. - long durationBefore = readDisplayedTbrDurationMainMenu(); - long percentageBefore = readDisplayedTbrPercentageMainMenu(); - - enterTbrMenu(); - long maxTbrPercentage = findMaxTbrPercentage(); - - // TODO v2 this can probably be removed by now - SystemClock.sleep(750); - - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, - "Pump did not return to MAIN_MEU after finding max tbr. " + - "Check pump manually, the TBR might be wrong."); - - - //TODO: check if TBR is still the same or duration was less than 5 minutes - long durationAfter = readDisplayedTbrDurationMainMenu(); - long percentageAfter = readDisplayedTbrPercentageMainMenu(); - - if(Math.abs(durationBefore-durationAfter) > 5){ - throw new CommandException().message("Duration jump during DetermineCapabilities"); - } - if(percentageAfter != percentageBefore){ - if(durationBefore<5 && percentageAfter == 100){ - log.debug("(percentageBefore != percentageAfter) - ignoring as tbr is now 100% and had a very short duration left"); - } - throw new CommandException().message("TBR changed while determining maxTBR."); - } - - //TODO return Result - return new CommandResult().success(true).enacted(false).message("Capablities: {maxTbrPercentage = " + maxTbrPercentage + ", success=" + "success }").capabilities((new PumpCapabilities()).maxTempPercent(maxTbrPercentage)); - } catch (CommandException e) { - return e.toCommandResult(); - } - } - - private void enterTbrMenu() { - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - scripter.navigateToMenu(MenuType.TBR_MENU); - scripter.verifyMenuIsDisplayed(MenuType.TBR_MENU); - scripter.pressCheckKey(); - scripter.waitForMenuUpdate(); - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - } - - private long findMaxTbrPercentage() { - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long activeTempBasal = readDisplayedTbrPercentage(); - - // pretend to increase the TBR to more than 500% - log.debug("Pressing up " + UP_STEPS + " times to get to maximum"); - for (int i = 0; i < UP_STEPS; i++) { - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - scripter.pressUpKey(); - SystemClock.sleep(200); - log.debug("Push #" + (i + 1)); - } - - //read the displayed maximum value - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long maximumTempBasal = readDisplayedTbrPercentage(); - - //reset the TBR in a controlled manner - long percentageChange = maximumTempBasal - activeTempBasal; - long percentageSteps = percentageChange / 10; - - int retries= 0; - while (percentageSteps > 0 && retries < RETRIES) { - log.debug("Pressing down " + percentageSteps + " times to get to previous value. Retry " + retries); - for (int i = 0; i < percentageSteps; i++) { - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - scripter.pressDownKey(); - SystemClock.sleep(200); - log.debug("Push #" + (i + 1)); - } - //do the rest if button-presses failed. - scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); - long currentPercentage = readDisplayedTbrPercentage(); - percentageChange = currentPercentage - activeTempBasal; - percentageSteps = percentageChange / 10; - retries++; - } - - - //exit menu - scripter.pressCheckKey(); - scripter.waitForMenuToBeLeft(MenuType.TBR_SET); - return maximumTempBasal; - } - - - private long readDisplayedTbrPercentage() { - SystemClock.sleep(1000); - // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - Object percentageObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.BASAL_RATE); - // this as a bit hacky, the display value is blinking, so we might catch that, so - // keep trying till we get the Double we want - while (!(percentageObj instanceof Double)) { - scripter.waitForMenuUpdate(); - percentageObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.BASAL_RATE); - } - return ((Double) percentageObj).longValue(); - } - - private int readDisplayedTbrDurationMainMenu() { - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if(scripter.getCurrentMenu().attributes().contains(MenuAttribute.RUNTIME)){ - // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded - Object durationObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.RUNTIME); - MenuTime duration = (MenuTime) durationObj; - return duration.getHour() * 60 + duration.getMinute(); - } else { - return 0; - } - } - - private int readDisplayedTbrPercentageMainMenu() { - scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); - if(scripter.getCurrentMenu().attributes().contains(MenuAttribute.TBR)){ - return (int)((Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.TBR)).doubleValue(); - } else { - return 100; - } - } - - @Override - public String toString() { - return "DetermineCapabilitiesCommand{}"; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java index 855ac662ae..f4d49c0a94 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCombo/ComboFragment.java @@ -34,7 +34,6 @@ public class ComboFragment extends Fragment implements View.OnClickListener { } private Button refresh; - private TextView updateCapabilities; private TextView statusText; @@ -48,7 +47,6 @@ public class ComboFragment extends Fragment implements View.OnClickListener { private TextView lastCmdResultText; private TextView lastCmdDurationText; - private TextView tbrCapabilityText; private TextView pumpstateBatteryText; private TextView insulinstateText; @@ -59,7 +57,6 @@ public class ComboFragment extends Fragment implements View.OnClickListener { View view = inflater.inflate(R.layout.combopump_fragment, container, false); refresh = (Button) view.findViewById(R.id.combo_refresh); - updateCapabilities = (TextView) view.findViewById(R.id.combo_update_capabilities); statusText = (TextView) view.findViewById(R.id.combo_status); @@ -72,12 +69,10 @@ public class ComboFragment extends Fragment implements View.OnClickListener { lastCmdTimeText = (TextView) view.findViewById(R.id.combo_last_command_time); lastCmdResultText = (TextView) view.findViewById(R.id.combo_last_command_result); lastCmdDurationText = (TextView) view.findViewById(R.id.combo_last_command_duration); - tbrCapabilityText = (TextView) view.findViewById(R.id.combo_tbr_capability); pumpstateBatteryText = (TextView) view.findViewById(R.id.combo_pumpstate_battery); insulinstateText = (TextView) view.findViewById(R.id.combo_insulinstate); refresh.setOnClickListener(this); - updateCapabilities.setOnClickListener(this); updateGUI(); return view; @@ -113,32 +108,6 @@ public class ComboFragment extends Fragment implements View.OnClickListener { }); thread.start(); break; - case R.id.combo_update_capabilities: - (new Thread(new Runnable() { - @Override - public void run() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - updateCapabilities.setText("{fa-bluetooth spin}"); - } - }); - - getPlugin().updateCapabilities(); - - if (activity != null) - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - updateCapabilities.setText("{fa-bluetooth-b}"); - } - }); - - } - })).start(); - break; } } @@ -201,7 +170,6 @@ public class ComboFragment extends Fragment implements View.OnClickListener { lastCmdDurationText.setText(""); } } - tbrCapabilityText.setText(getPlugin().getPumpDescription().maxTempPercent + "%"); } }); } 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 9f0e227cc5..e0b9b4c632 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 @@ -31,7 +31,6 @@ import de.jotomo.ruffyscripter.commands.BolusCommand; import de.jotomo.ruffyscripter.commands.CancelTbrCommand; import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandResult; -import de.jotomo.ruffyscripter.commands.DetermineCapabilitiesCommand; import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommandAlt; @@ -695,29 +694,4 @@ public class ComboPlugin implements PluginBase, PumpInterface { public void onStatusEvent(final EventAppExit ignored) { unbindRuffyService(); } - - - public void updateCapabilities() { - // if Android is sluggish this might get called before ruffy is bound - if (ruffyScripter == null) { - log.warn("Rejecting call to RefreshDataFromPump: ruffy service not bound (yet)"); - ToastUtils.showToastInUiThread(MainApp.instance(), "Ruffy not initialized."); - return; - } - if (isBusy()) { - ToastUtils.showToastInUiThread(MainApp.instance(), "Pump busy!"); - return; - } - CommandResult result = runCommand(new DetermineCapabilitiesCommand()); - if (result.success) { - pumpDescription.maxTempPercent = (int) result.capabilities.maxTempPercent; - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(MainApp.instance()); - SharedPreferences.Editor editor = preferences.edit(); - editor.putInt(COMBO_MAX_TEMP_PERCENT_SP, pumpDescription.maxTempPercent); - editor.commit(); - MainApp.bus().post(new EventComboPumpUpdateGUI()); - } else { - ToastUtils.showToastInUiThread(MainApp.instance(), "No success."); - } - } } \ No newline at end of file diff --git a/app/src/main/res/layout/combopump_fragment.xml b/app/src/main/res/layout/combopump_fragment.xml index a4270240ef..b515ceda2f 100644 --- a/app/src/main/res/layout/combopump_fragment.xml +++ b/app/src/main/res/layout/combopump_fragment.xml @@ -418,60 +418,6 @@ - - - - - - - - - - - - - Date: Sun, 27 Aug 2017 14:12:47 +0200 Subject: [PATCH 38/50] Retry with current ruffy. --- .../d/ruffy/ruffy/driver/IRTHandler.aidl | 9 +++- .../d/ruffy/ruffy/driver/IRuffyService.aidl | 10 +++-- .../d/ruffy/ruffy/driver/package-info.java | 1 - .../jotomo/ruffyscripter/RuffyScripter.java | 42 +++++++++++++++---- 4 files changed, 47 insertions(+), 15 deletions(-) delete mode 100644 app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl index 996b10b666..b6a07226b8 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl @@ -10,12 +10,17 @@ interface IRTHandler { void fail(String message); void requestBluetooth(); + boolean canDisconnect(); void rtStopped(); void rtStarted(); void rtClearDisplay(); void rtUpdateDisplay(in byte[] quarter, int which); - void rtDisplayHandleMenu(in Menu menu); - void rtDisplayHandleNoMenu(); + void rtDisplayHandleMenu(in Menu menu, in int sequence); + void rtDisplayHandleNoMenu(in int sequence); + + void keySent(in int sequence); + + String getServiceIdentifier(); } diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl index 6c988aa038..f4879445b7 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl @@ -6,18 +6,22 @@ import org.monkey.d.ruffy.ruffy.driver.IRTHandler; interface IRuffyService { - void setHandler(IRTHandler handler); + void addHandler(IRTHandler handler); + void removeHandler(IRTHandler handler); /** Connect to the pump * * @return 0 if successful, -1 otherwise */ - int doRTConnect(); + int doRTConnect(IRTHandler handler); /** Disconnect from the pump */ - void doRTDisconnect(); + void doRTDisconnect(IRTHandler handler); + /*What's the meaning of 'changed'? + * changed means if a button state has been changed, like btton pressed is a change and button release another*/ void rtSendKey(byte keyCode, boolean changed); void resetPairing(); boolean isConnected(); + boolean isBoundToPump(); } diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java deleted file mode 100644 index ab1def7407..0000000000 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java +++ /dev/null @@ -1 +0,0 @@ -//b916a900c0899ef58ad58c7427d1c30d3c8731f4 \ No newline at end of file diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 7630907160..4546aa90c6 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -46,9 +46,11 @@ public class RuffyScripter { private final Object screenlock = new Object(); + private final Object keylock = new Object(); + private int keynotwait = 0; + public void start(IRuffyService newService) { try { -/* if (ruffyService != null) { try { ruffyService.removeHandler(mHandler); @@ -56,7 +58,6 @@ public class RuffyScripter { // ignore } } -*/ if (newService != null) { this.ruffyService = newService; // TODO this'll be done better in v2 via ConnectionManager @@ -64,7 +65,7 @@ public class RuffyScripter { idleDisconnectMonitorThread.start(); } started = true; - newService.setHandler(mHandler); + newService.addHandler(mHandler); } } catch (Exception e) { log.error("Unhandled exception starting RuffyScripter", e); @@ -77,6 +78,7 @@ public class RuffyScripter { } private volatile boolean connected = false; + private volatile boolean canDisconnect = false; private volatile long lastDisconnected = 0; private Thread idleDisconnectMonitorThread = new Thread(new Runnable() { @@ -92,7 +94,8 @@ public class RuffyScripter { && now > lastDisconnected + 15 * 1000) { log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout"); lastDisconnected = now; - ruffyService.doRTDisconnect(); + canDisconnect = true; + ruffyService.doRTDisconnect(mHandler); connected = false; // don't attempt anything fancy in the next 10s, let the pump settle SystemClock.sleep(10 * 1000); @@ -127,6 +130,11 @@ public class RuffyScripter { log.trace("Ruffy invoked requestBluetooth callback"); } + @Override + public boolean canDisconnect() throws RemoteException { + return canDisconnect; + } + @Override public void rtStopped() throws RemoteException { log.debug("rtStopped callback invoked"); @@ -149,7 +157,7 @@ public class RuffyScripter { } @Override - public void rtDisplayHandleMenu(Menu menu) throws RemoteException { + public void rtDisplayHandleMenu(Menu menu, int sequence) throws RemoteException { // method is called every ~500ms log.debug("rtDisplayHandleMenu: " + menu); @@ -172,9 +180,26 @@ public class RuffyScripter { } @Override - public void rtDisplayHandleNoMenu() throws RemoteException { + public void rtDisplayHandleNoMenu(int sequence) throws RemoteException { log.debug("rtDisplayHandleNoMenu callback invoked"); } + + + @Override + public void keySent(int sequence) throws RemoteException { + synchronized (keylock) { + if (keynotwait > 0) + keynotwait--; + else + keylock.notify(); + } + } + + @Override + public String getServiceIdentifier() throws RemoteException { + return this.toString(); + } + }; public boolean isPumpBusy() { @@ -182,14 +207,12 @@ public class RuffyScripter { } public void unbind() { - /* if (ruffyService != null) try { ruffyService.removeHandler(mHandler); } catch (Exception e) { // ignore } - */ this.ruffyService = null; } @@ -352,7 +375,8 @@ public class RuffyScripter { SystemClock.sleep(10 * 1000); } - boolean connectInitSuccessful = ruffyService.doRTConnect() == 0; + canDisconnect = false; + boolean connectInitSuccessful = ruffyService.doRTConnect(mHandler) == 0; log.debug("Connect init successful: " + connectInitSuccessful); log.debug("Waiting for first menu update to be sent"); // Note: there was an 'if(currentMenu == null)' around the next call, since From 07057553687a9ab1683dbd412b337ffeb3a080e6 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 14:27:48 +0200 Subject: [PATCH 39/50] Revert "Retry with current ruffy." This reverts commit f9281c1f996679a2c8065aa52cbb8cb4698353bc. --- .../d/ruffy/ruffy/driver/IRTHandler.aidl | 9 +--- .../d/ruffy/ruffy/driver/IRuffyService.aidl | 10 ++--- .../d/ruffy/ruffy/driver/package-info.java | 1 + .../jotomo/ruffyscripter/RuffyScripter.java | 42 ++++--------------- 4 files changed, 15 insertions(+), 47 deletions(-) create mode 100644 app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl index b6a07226b8..996b10b666 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRTHandler.aidl @@ -10,17 +10,12 @@ interface IRTHandler { void fail(String message); void requestBluetooth(); - boolean canDisconnect(); void rtStopped(); void rtStarted(); void rtClearDisplay(); void rtUpdateDisplay(in byte[] quarter, int which); - void rtDisplayHandleMenu(in Menu menu, in int sequence); - void rtDisplayHandleNoMenu(in int sequence); - - void keySent(in int sequence); - - String getServiceIdentifier(); + void rtDisplayHandleMenu(in Menu menu); + void rtDisplayHandleNoMenu(); } diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl index f4879445b7..6c988aa038 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl @@ -6,22 +6,18 @@ import org.monkey.d.ruffy.ruffy.driver.IRTHandler; interface IRuffyService { - void addHandler(IRTHandler handler); - void removeHandler(IRTHandler handler); + void setHandler(IRTHandler handler); /** Connect to the pump * * @return 0 if successful, -1 otherwise */ - int doRTConnect(IRTHandler handler); + int doRTConnect(); /** Disconnect from the pump */ - void doRTDisconnect(IRTHandler handler); + void doRTDisconnect(); - /*What's the meaning of 'changed'? - * changed means if a button state has been changed, like btton pressed is a change and button release another*/ void rtSendKey(byte keyCode, boolean changed); void resetPairing(); boolean isConnected(); - boolean isBoundToPump(); } diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java new file mode 100644 index 0000000000..ab1def7407 --- /dev/null +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/package-info.java @@ -0,0 +1 @@ +//b916a900c0899ef58ad58c7427d1c30d3c8731f4 \ No newline at end of file diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 4546aa90c6..7630907160 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -46,11 +46,9 @@ public class RuffyScripter { private final Object screenlock = new Object(); - private final Object keylock = new Object(); - private int keynotwait = 0; - public void start(IRuffyService newService) { try { +/* if (ruffyService != null) { try { ruffyService.removeHandler(mHandler); @@ -58,6 +56,7 @@ public class RuffyScripter { // ignore } } +*/ if (newService != null) { this.ruffyService = newService; // TODO this'll be done better in v2 via ConnectionManager @@ -65,7 +64,7 @@ public class RuffyScripter { idleDisconnectMonitorThread.start(); } started = true; - newService.addHandler(mHandler); + newService.setHandler(mHandler); } } catch (Exception e) { log.error("Unhandled exception starting RuffyScripter", e); @@ -78,7 +77,6 @@ public class RuffyScripter { } private volatile boolean connected = false; - private volatile boolean canDisconnect = false; private volatile long lastDisconnected = 0; private Thread idleDisconnectMonitorThread = new Thread(new Runnable() { @@ -94,8 +92,7 @@ public class RuffyScripter { && now > lastDisconnected + 15 * 1000) { log.debug("Disconnecting after " + (connectionTimeOutMs / 1000) + "s inactivity timeout"); lastDisconnected = now; - canDisconnect = true; - ruffyService.doRTDisconnect(mHandler); + ruffyService.doRTDisconnect(); connected = false; // don't attempt anything fancy in the next 10s, let the pump settle SystemClock.sleep(10 * 1000); @@ -130,11 +127,6 @@ public class RuffyScripter { log.trace("Ruffy invoked requestBluetooth callback"); } - @Override - public boolean canDisconnect() throws RemoteException { - return canDisconnect; - } - @Override public void rtStopped() throws RemoteException { log.debug("rtStopped callback invoked"); @@ -157,7 +149,7 @@ public class RuffyScripter { } @Override - public void rtDisplayHandleMenu(Menu menu, int sequence) throws RemoteException { + public void rtDisplayHandleMenu(Menu menu) throws RemoteException { // method is called every ~500ms log.debug("rtDisplayHandleMenu: " + menu); @@ -180,26 +172,9 @@ public class RuffyScripter { } @Override - public void rtDisplayHandleNoMenu(int sequence) throws RemoteException { + public void rtDisplayHandleNoMenu() throws RemoteException { log.debug("rtDisplayHandleNoMenu callback invoked"); } - - - @Override - public void keySent(int sequence) throws RemoteException { - synchronized (keylock) { - if (keynotwait > 0) - keynotwait--; - else - keylock.notify(); - } - } - - @Override - public String getServiceIdentifier() throws RemoteException { - return this.toString(); - } - }; public boolean isPumpBusy() { @@ -207,12 +182,14 @@ public class RuffyScripter { } public void unbind() { + /* if (ruffyService != null) try { ruffyService.removeHandler(mHandler); } catch (Exception e) { // ignore } + */ this.ruffyService = null; } @@ -375,8 +352,7 @@ public class RuffyScripter { SystemClock.sleep(10 * 1000); } - canDisconnect = false; - boolean connectInitSuccessful = ruffyService.doRTConnect(mHandler) == 0; + boolean connectInitSuccessful = ruffyService.doRTConnect() == 0; log.debug("Connect init successful: " + connectInitSuccessful); log.debug("Waiting for first menu update to be sent"); // Note: there was an 'if(currentMenu == null)' around the next call, since From 7bd7c7d03546700d3cf49389858eaac9cc408df5 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 14:45:06 +0200 Subject: [PATCH 40/50] Workaound for #27 (TBR issued twice). --- .../ruffyscripter/commands/SetTbrCommand.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index 9f390d87f5..cbda87a2c2 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -12,6 +12,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; +import de.jotomo.ruffyscripter.PumpState; + public class SetTbrCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(SetTbrCommand.class); @@ -53,11 +55,24 @@ public class SetTbrCommand extends BaseCommand { @Override public CommandResult execute() { try { + boolean cancellingTbr = percentage == 100; + PumpState pumpState = scripter.readPumpState(); + + // TODO hack, cancelling a TBR that isn't running is dealt with in CancelTbrCommand, + // this avoids setting a TBR twice until that AAPS bug is squished which calls this + // twice within a minute GL#27 + if (!cancellingTbr + && pumpState.tbrActive + && pumpState.tbrPercent == percentage + && (pumpState.tbrRemainingDuration == duration || pumpState.tbrRemainingDuration + 1 == duration)) { + return new CommandResult().success(true).enacted(false).message("Requested TBR already running"); + } + enterTbrMenu(); inputTbrPercentage(); verifyDisplayedTbrPercentage(); - if (percentage == 100) { + if (cancellingTbr) { cancelTbrAndConfirmCancellationWarning(); } else { // switch to TBR_DURATION menu by pressing menu key @@ -79,7 +94,7 @@ public class SetTbrCommand extends BaseCommand { "Check pump manually, the TBR might not have been set/cancelled."); // check main menu shows the same values we just set - if (percentage == 100) { + if (cancellingTbr) { verifyMainMenuShowsNoActiveTbr(); return new CommandResult().success(true).enacted(true).message("TBR was cancelled"); } else { From f70cbbc6c01a26d4a3dfa6641122e573b4a3adea Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 14:49:09 +0200 Subject: [PATCH 41/50] Try building against ruffy stable, 8dae0c0fedd5e371e85da3433a07aaab27b05db0 --- .../aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl | 6 +++++- .../main/java/de/jotomo/ruffyscripter/RuffyScripter.java | 4 +--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl index 6c988aa038..ded119c7b4 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl @@ -6,7 +6,8 @@ import org.monkey.d.ruffy.ruffy.driver.IRTHandler; interface IRuffyService { - void setHandler(IRTHandler handler); + void addHandler(IRTHandler handler); + void removeHandler(IRTHandler handler); /** Connect to the pump * @@ -17,7 +18,10 @@ interface IRuffyService { /** Disconnect from the pump */ void doRTDisconnect(); + /*What's the meaning of 'changed'? + * changed means if a button state has been changed, like btton pressed is a change and button release another*/ void rtSendKey(byte keyCode, boolean changed); void resetPairing(); boolean isConnected(); + boolean isBoundToPump(); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 7630907160..17f17d8534 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -48,7 +48,6 @@ public class RuffyScripter { public void start(IRuffyService newService) { try { -/* if (ruffyService != null) { try { ruffyService.removeHandler(mHandler); @@ -56,7 +55,6 @@ public class RuffyScripter { // ignore } } -*/ if (newService != null) { this.ruffyService = newService; // TODO this'll be done better in v2 via ConnectionManager @@ -64,7 +62,7 @@ public class RuffyScripter { idleDisconnectMonitorThread.start(); } started = true; - newService.setHandler(mHandler); + newService.addHandler(mHandler); } } catch (Exception e) { log.error("Unhandled exception starting RuffyScripter", e); From ad44b356c4b3e295a8527ec2d2a20b0f1417a5a1 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 15:29:25 +0200 Subject: [PATCH 42/50] Revert "Try building against ruffy stable, 8dae0c0fedd5e371e85da3433a07aaab27b05db0" This reverts commit 8720c08cdd4a7f89b77816d849da9c585fb8f1ef. --- .../aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl | 6 +----- .../main/java/de/jotomo/ruffyscripter/RuffyScripter.java | 4 +++- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl index ded119c7b4..6c988aa038 100644 --- a/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl +++ b/app/src/main/aidl/org/monkey/d/ruffy/ruffy/driver/IRuffyService.aidl @@ -6,8 +6,7 @@ import org.monkey.d.ruffy.ruffy.driver.IRTHandler; interface IRuffyService { - void addHandler(IRTHandler handler); - void removeHandler(IRTHandler handler); + void setHandler(IRTHandler handler); /** Connect to the pump * @@ -18,10 +17,7 @@ interface IRuffyService { /** Disconnect from the pump */ void doRTDisconnect(); - /*What's the meaning of 'changed'? - * changed means if a button state has been changed, like btton pressed is a change and button release another*/ void rtSendKey(byte keyCode, boolean changed); void resetPairing(); boolean isConnected(); - boolean isBoundToPump(); } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 17f17d8534..7630907160 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -48,6 +48,7 @@ public class RuffyScripter { public void start(IRuffyService newService) { try { +/* if (ruffyService != null) { try { ruffyService.removeHandler(mHandler); @@ -55,6 +56,7 @@ public class RuffyScripter { // ignore } } +*/ if (newService != null) { this.ruffyService = newService; // TODO this'll be done better in v2 via ConnectionManager @@ -62,7 +64,7 @@ public class RuffyScripter { idleDisconnectMonitorThread.start(); } started = true; - newService.addHandler(mHandler); + newService.setHandler(mHandler); } } catch (Exception e) { log.error("Unhandled exception starting RuffyScripter", e); From e399fac8dc4209e1ad935096798bf2a8ce97b4db Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 15:29:14 +0200 Subject: [PATCH 43/50] Try to be clever about slow screen updates when scrolling. --- .../ruffyscripter/commands/BolusCommand.java | 10 +++- .../ruffyscripter/commands/SetTbrCommand.java | 53 ++++++++++++------- .../interaction/actions/BolusActivity.java | 1 + 3 files changed, 45 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index cc096bdb00..6688f9197c 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -224,14 +224,22 @@ public class BolusCommand extends BaseCommand { private void verifyDisplayedBolusAmount() { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + + // wait up to 5s for any scrolling to finish double displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); + long timeout = System.currentTimeMillis() + 10 * 1000; + while (timeout > System.currentTimeMillis() && bolus - displayedBolus > 0.05) { + log.debug("Waiting for pump to process scrolling input for amount, current: " + displayedBolus + ", desired: " + bolus); + displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); + } + log.debug("Final bolus: " + displayedBolus); if (Math.abs(displayedBolus - bolus) > 0.05) { throw new CommandException().message("Failed to set correct bolus. Expected: " + bolus + ", actual: " + displayedBolus); } // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long - SystemClock.sleep(2000); + SystemClock.sleep(1000); scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); double refreshedDisplayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); if (Math.abs(displayedBolus - refreshedDisplayedBolus) > 0.05) { diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java index cbda87a2c2..bde829df9c 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommand.java @@ -69,8 +69,8 @@ public class SetTbrCommand extends BaseCommand { } enterTbrMenu(); - inputTbrPercentage(); - verifyDisplayedTbrPercentage(); + boolean increasingPercentage = inputTbrPercentage(); + verifyDisplayedTbrPercentage(increasingPercentage); if (cancellingTbr) { cancelTbrAndConfirmCancellationWarning(); @@ -81,8 +81,8 @@ public class SetTbrCommand extends BaseCommand { scripter.waitForMenuUpdate(); scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); - inputTbrDuration(); - verifyDisplayedTbrDuration(); + boolean increasingDuration = inputTbrDuration(); + verifyDisplayedTbrDuration(increasingDuration); // confirm TBR scripter.pressCheckKey(); @@ -117,7 +117,7 @@ public class SetTbrCommand extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); } - private void inputTbrPercentage() { + private boolean inputTbrPercentage() { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); long currentPercent = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); log.debug("Current TBR %: " + currentPercent); @@ -136,21 +136,29 @@ public class SetTbrCommand extends BaseCommand { else scripter.pressDownKey(); SystemClock.sleep(100); } - // Give the pump time to finish any scrolling that might still be going on, can take - // up to 1100ms. Plus some extra time to be sure - SystemClock.sleep(2000); + return increasePercentage; } - private void verifyDisplayedTbrPercentage() { + // TODO extract verification into a method TBR percentage, duration and bolus amount + private void verifyDisplayedTbrPercentage(boolean increasingPercentage) { scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); + // wait up to 5s for any scrolling to finish long displayedPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); + long timeout = System.currentTimeMillis() + 10 * 1000; + while (timeout > System.currentTimeMillis() + && ((increasingPercentage && displayedPercentage < percentage) + || (!increasingPercentage && displayedPercentage > percentage))) { + log.debug("Waiting for pump to process scrolling input for percentage, current: " + + displayedPercentage + ", desired: " + percentage + ", scrolling up: " + increasingPercentage); + displayedPercentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); + } + log.debug("Final displayed TBR percentage: " + displayedPercentage); if (displayedPercentage != percentage) { - log.debug("Final displayed TBR percentage: " + displayedPercentage); throw new CommandException().message("Failed to set TBR percentage, requested: " + percentage + ", actual: " + displayedPercentage); } // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long - SystemClock.sleep(2000); + SystemClock.sleep(1000); scripter.verifyMenuIsDisplayed(MenuType.TBR_SET); long refreshedDisplayedTbrPecentage = scripter.readBlinkingValue(Double.class, MenuAttribute.BASAL_RATE).longValue(); if (displayedPercentage != refreshedDisplayedTbrPecentage) { @@ -160,7 +168,7 @@ public class SetTbrCommand extends BaseCommand { } } - private void inputTbrDuration() { + private boolean inputTbrDuration() { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); long currentDuration = scripter.readDisplayedDuration(); if (currentDuration % 15 != 0) { @@ -190,21 +198,30 @@ public class SetTbrCommand extends BaseCommand { SystemClock.sleep(100); log.debug("Push #" + (i + 1)); } - // Give the pump time to finish any scrolling that might still be going on, can take - // up to 1100ms. Plus some extra time to be sure - SystemClock.sleep(2000); + return increaseDuration; } - private void verifyDisplayedTbrDuration() { + private void verifyDisplayedTbrDuration(boolean increasingPercentage) { scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); + + // wait up to 5s for any scrolling to finish long displayedDuration = scripter.readDisplayedDuration(); + long timeout = System.currentTimeMillis() + 10 * 1000; + while (timeout > System.currentTimeMillis() + && ((increasingPercentage && displayedDuration < duration) + || (!increasingPercentage && displayedDuration > duration))) { + log.debug("Waiting for pump to process scrolling input for duration, current: " + + displayedDuration + ", desired: " + duration + ", scrolling up: " + increasingPercentage); + displayedDuration = scripter.readDisplayedDuration(); + } + + log.debug("Final displayed TBR duration: " + displayedDuration); if (displayedDuration != duration) { - log.debug("Final displayed TBR duration: " + displayedDuration); throw new CommandException().message("Failed to set TBR duration, requested: " + duration + ", actual: " + displayedDuration); } // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long - SystemClock.sleep(2000); + SystemClock.sleep(1000); scripter.verifyMenuIsDisplayed(MenuType.TBR_DURATION); long refreshedDisplayedTbrDuration = scripter.readDisplayedDuration(); if (displayedDuration != refreshedDisplayedTbrDuration) { diff --git a/wear/src/main/java/info/nightscout/androidaps/interaction/actions/BolusActivity.java b/wear/src/main/java/info/nightscout/androidaps/interaction/actions/BolusActivity.java index 814020d742..4860cb3d56 100644 --- a/wear/src/main/java/info/nightscout/androidaps/interaction/actions/BolusActivity.java +++ b/wear/src/main/java/info/nightscout/androidaps/interaction/actions/BolusActivity.java @@ -70,6 +70,7 @@ public class BolusActivity extends ViewSelectorActivity { if (editInsulin != null){ def = SafeParse.stringToDouble(editInsulin.editText.getText().toString()); } + // TODO use pump supported stet size editInsulin = new PlusMinusEditText(view, R.id.amountfield, R.id.plusbutton, R.id.minusbutton, def, 0d, 30d, 0.1d, new DecimalFormat("#0.0"), false); setLabelToPlusMinusView(view, "insulin"); container.addView(view); From 95fda165a31a405e578d98b69c380694e118b41c Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 18:49:24 +0200 Subject: [PATCH 44/50] Merge fixes without changes to behaviour. --- .../de/jotomo/ruffyscripter/commands/BolusCommand.java | 5 +++++ .../androidaps/plugins/PumpCombo/ComboPlugin.java | 10 ---------- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index 6688f9197c..bf2b9f18e3 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -248,6 +248,11 @@ public class BolusCommand extends BaseCommand { } } + public void requestCancellation() { + cancelRequested = true; + progressReportCallback.report(STOPPING, 0, 0); + } + @Override public String toString() { return "BolusCommand{" + 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 e0b9b4c632..cf824d7224 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 @@ -5,13 +5,11 @@ import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.graphics.Color; import android.media.RingtoneManager; import android.net.Uri; import android.os.IBinder; import android.os.SystemClock; -import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; @@ -23,7 +21,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.Date; -import java.util.Objects; import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; @@ -33,22 +30,16 @@ import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandResult; import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; -import de.jotomo.ruffyscripter.commands.SetTbrCommandAlt; import info.nightscout.androidaps.BuildConfig; -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; import info.nightscout.androidaps.data.Profile; -import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.EventAppExit; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.ProfileInterface; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; @@ -56,7 +47,6 @@ import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProg import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateGUI; import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; -import info.nightscout.utils.ToastUtils; /** * Created by mike on 05.08.2016. From 3d2732a68e26cb184f93d06c84d67008a0107519 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 19:04:59 +0200 Subject: [PATCH 45/50] Restore bolus comands alongside. --- .../ruffyscripter/commands/BolusCommand.java | 173 +++-------- .../commands/CancellableBolusCommand.java | 272 ++++++++++++++++++ 2 files changed, 305 insertions(+), 140 deletions(-) create mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/CancellableBolusCommand.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index bf2b9f18e3..bc81be3942 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -11,23 +11,14 @@ import java.util.ArrayList; import java.util.List; import java.util.Locale; -import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; -import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.DELIVERING; -import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.STOPPED; -import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.STOPPING; -import static de.jotomo.ruffyscripter.commands.BolusCommand.ProgressReportCallback.State.DELIVERED; - public class BolusCommand extends BaseCommand { private static final Logger log = LoggerFactory.getLogger(BolusCommand.class); - private final double bolus; - private final ProgressReportCallback progressReportCallback; - private volatile boolean cancelRequested; + protected final double bolus; - public BolusCommand(double bolus, ProgressReportCallback progressReportCallback) { - this.progressReportCallback = progressReportCallback; + public BolusCommand(double bolus) { this.bolus = bolus; } @@ -45,103 +36,31 @@ public class BolusCommand extends BaseCommand { @Override public CommandResult execute() { try { - // TODO read reservoir level and reject request if reservoir < bolus - enterBolusMenu(); + enterBolusMenu(scripter); - inputBolusAmount(); - verifyDisplayedBolusAmount(); - - if (cancelRequested) { - progressReportCallback.report(STOPPING, 0, 0); - scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 30 * 1000); - progressReportCallback.report(STOPPED, 0, 0); - return new CommandResult().success(true).enacted(false) - .message("Bolus cancelled as per user request with no insulin delivered"); - } + inputBolusAmount(scripter); + verifyDisplayedBolusAmount(scripter); // confirm bolus scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); scripter.pressCheckKey(); - // the pump displays the entered bolus and waits a few seconds to let user check and cancel - while (scripter.getCurrentMenu().getType() == MenuType.BOLUS_ENTER) { - if (cancelRequested) { - progressReportCallback.report(STOPPING, 0, 0); - scripter.pressUpKey(); - // wait up to 1s for a BOLUS_CANCELLED alert, if it doesn't happen we missed - // the window, simply continue and let the next cancel attempt try its luck - boolean alertWasCancelled = confirmAlert("BOLUS CANCELLED", 1000); - if (alertWasCancelled) { - progressReportCallback.report(STOPPED, 0, 0); - return new CommandResult().success(true).enacted(false) - .message("Bolus cancelled as per user request with no insulin delivered"); - } - } - SystemClock.sleep(10); - } + // the pump displays the entered bolus and waits a bit to let user check and cancel + scripter.waitForMenuToBeLeft(MenuType.BOLUS_ENTER); + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, "Pump did not return to MAIN_MEU from BOLUS_ENTER to deliver bolus. " + "Check pump manually, the bolus might not have been delivered."); - progressReportCallback.report(DELIVERING, 0, 0); - Double bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); - double lastBolusReported = 0; - boolean lowCartdrigeAlarmTriggered = false; // wait for bolus delivery to complete; the remaining units to deliver are counted // down and are displayed on the main menu. - // TODO extract into method - - // TODO 'low cartrdige' alarm must be handled inside, since the bolus continues regardless; - // it must be claread so we can see the remaining bolus again; + Double bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); while (bolusRemaining != null) { - if (cancelRequested) { - progressReportCallback.report(STOPPING, 0, 0); - scripter.pressKeyMs(RuffyScripter.Key.UP, 3000); - progressReportCallback.report(STOPPED, 0, 0); - // if the bolus finished while we attempted to cancel it, there'll be no alarm - long timeout = System.currentTimeMillis() + 2000; - while (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR && System.currentTimeMillis() < timeout) { - SystemClock.sleep(10); - } - while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { - // TODO make this cleaner, extract method, needed below too - scripter.pressCheckKey(); - SystemClock.sleep(200); - } - break; - } - if (lastBolusReported != bolusRemaining) { - log.debug("Delivering bolus, remaining: " + bolusRemaining); - int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100)); - progressReportCallback.report(DELIVERING, percentDelivered, bolus - bolusRemaining); - lastBolusReported = bolusRemaining; - } - - if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { - String message = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE); - if (message.equals("LOW CARTRIDGE")) { - lowCartdrigeAlarmTriggered = true; - confirmAlert("LOW CARTRIDGE", 2000); - } else { - // any other alert - break; - } - } - SystemClock.sleep(50); + log.debug("Delivering bolus, remaining: " + bolusRemaining); + SystemClock.sleep(200); bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); } - // wait up to 2s for any possible warning to be raised, if not raised already - long minWait = System.currentTimeMillis() + 2 * 1000; - while (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { - SystemClock.sleep(50); - } - - // process warnings (confirm them, report back to AAPS about them) - while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { - // TODO - } - // TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus? // TODO how are error states reported back to the caller that occur outside of calls in genal? Low battery, low cartridge? @@ -150,9 +69,6 @@ public class BolusCommand extends BaseCommand { "Bolus delivery did not complete as expected. " + "Check pump manually, the bolus might not have been delivered."); - - // TODO report back what was read from history - // read last bolus record; those menus display static data and therefore // only a single menu update is sent scripter.navigateToMenu(MenuType.MY_DATA_MENU); @@ -167,8 +83,6 @@ public class BolusCommand extends BaseCommand { .message("Bolus was delivered, but unable to confirm it with history record"); } - // TODO check date so we don't pick a false record if the previous bolus had the same amount; - // also, report back partial bolus. Just call ReadHsstory(timestamp, boluses=true) cmd ... double lastBolusInHistory = (double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS); if (Math.abs(bolus - lastBolusInHistory) > 0.05) { throw new CommandException().success(false).enacted(true) @@ -177,13 +91,12 @@ public class BolusCommand extends BaseCommand { } log.debug("Bolus record in history confirms delivered bolus"); - if (!scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 15 * 1000)) { - throw new CommandException().success(false).enacted(true) - .message("Bolus was correctly delivered and checked against history, but we " - + "did not return the main menu successfully."); - } - - progressReportCallback.report(DELIVERED, 100, bolus); + // leave menu to go back to main menu + scripter.pressCheckKey(); + scripter.waitForMenuToBeLeft(MenuType.BOLUS_DATA); + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, + "Bolus was correctly delivered and checked against history, but we " + + "did not return the main menu successfully."); return new CommandResult().success(true).enacted(true) .message(String.format(Locale.US, "Delivered %02.1f U", bolus)); @@ -192,14 +105,7 @@ public class BolusCommand extends BaseCommand { } } - // TODO confirmAlarms? and report back which were cancelled? - - private boolean confirmAlert(String alertText, int maxWaitTillExpectedAlert) { - // TODO - return false; - } - - private void enterBolusMenu() { + private void enterBolusMenu(RuffyScripter scripter) { scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); scripter.navigateToMenu(MenuType.BOLUS_MENU); scripter.verifyMenuIsDisplayed(MenuType.BOLUS_MENU); @@ -208,7 +114,7 @@ public class BolusCommand extends BaseCommand { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); } - private void inputBolusAmount() { + private void inputBolusAmount(RuffyScripter scripter) { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); // press 'up' once for each 0.1 U increment long steps = Math.round(bolus * 10); @@ -222,35 +128,33 @@ public class BolusCommand extends BaseCommand { SystemClock.sleep(2000); } - private void verifyDisplayedBolusAmount() { + private void verifyDisplayedBolusAmount(RuffyScripter scripter) { scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); - - // wait up to 5s for any scrolling to finish - double displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); - long timeout = System.currentTimeMillis() + 10 * 1000; - while (timeout > System.currentTimeMillis() && bolus - displayedBolus > 0.05) { - log.debug("Waiting for pump to process scrolling input for amount, current: " + displayedBolus + ", desired: " + bolus); - displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); - } - + double displayedBolus = readDisplayedBolusAmount(scripter); log.debug("Final bolus: " + displayedBolus); if (Math.abs(displayedBolus - bolus) > 0.05) { throw new CommandException().message("Failed to set correct bolus. Expected: " + bolus + ", actual: " + displayedBolus); } // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long - SystemClock.sleep(1000); - scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); - double refreshedDisplayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); + SystemClock.sleep(2000); + double refreshedDisplayedBolus = readDisplayedBolusAmount(scripter); if (Math.abs(displayedBolus - refreshedDisplayedBolus) > 0.05) { throw new CommandException().message("Failed to set bolus: bolus changed after input stopped from " + displayedBolus + " -> " + refreshedDisplayedBolus); } } - public void requestCancellation() { - cancelRequested = true; - progressReportCallback.report(STOPPING, 0, 0); + private double readDisplayedBolusAmount(RuffyScripter scripter) { + // TODO v2 add timeout? Currently the command execution timeout would trigger if exceeded + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + // bolus amount is blinking, so we need to make sure we catch it at the right moment + Object amountObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS); + while (!(amountObj instanceof Double)) { + scripter.waitForMenuUpdate(); + amountObj = scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS); + } + return (double) amountObj; } @Override @@ -259,15 +163,4 @@ public class BolusCommand extends BaseCommand { "bolus=" + bolus + '}'; } - - public interface ProgressReportCallback { - enum State { - DELIVERING, - DELIVERED, - STOPPING, - STOPPED - } - - void report(State state, int percent, double delivered); - } } diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/CancellableBolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancellableBolusCommand.java new file mode 100644 index 0000000000..7d7283dce6 --- /dev/null +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/CancellableBolusCommand.java @@ -0,0 +1,272 @@ +package de.jotomo.ruffyscripter.commands; + +import android.os.SystemClock; + +import org.monkey.d.ruffy.ruffy.driver.display.MenuAttribute; +import org.monkey.d.ruffy.ruffy.driver.display.MenuType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import de.jotomo.ruffyscripter.PumpState; +import de.jotomo.ruffyscripter.RuffyScripter; + +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.DELIVERED; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.DELIVERING; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.STOPPED; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.STOPPING; + +public class CancellableBolusCommand extends BolusCommand { + private static final Logger log = LoggerFactory.getLogger(CancellableBolusCommand.class); + + private final ProgressReportCallback progressReportCallback; + private volatile boolean cancelRequested; + + public CancellableBolusCommand(double bolus, ProgressReportCallback progressReportCallback) { + super(bolus); + this.progressReportCallback = progressReportCallback; + } + + @Override + public List validateArguments() { + List violations = new ArrayList<>(); + + if (bolus <= 0 || bolus > 25) { + violations.add("Requested bolus " + bolus + " out of limits (0-25)"); + } + + return violations; + } + + @Override + public CommandResult execute() { + try { + // TODO read reservoir level and reject request if reservoir < bolus + enterBolusMenu(); + + inputBolusAmount(); + verifyDisplayedBolusAmount(); + + if (cancelRequested) { + progressReportCallback.report(STOPPING, 0, 0); + scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 30 * 1000); + progressReportCallback.report(STOPPED, 0, 0); + return new CommandResult().success(true).enacted(false) + .message("Bolus cancelled as per user request with no insulin delivered"); + } + + // confirm bolus + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + scripter.pressCheckKey(); + + // the pump displays the entered bolus and waits a few seconds to let user check and cancel + while (scripter.getCurrentMenu().getType() == MenuType.BOLUS_ENTER) { + if (cancelRequested) { + progressReportCallback.report(STOPPING, 0, 0); + scripter.pressUpKey(); + // wait up to 1s for a BOLUS_CANCELLED alert, if it doesn't happen we missed + // the window, simply continue and let the next cancel attempt try its luck + boolean alertWasCancelled = confirmAlert("BOLUS CANCELLED", 1000); + if (alertWasCancelled) { + progressReportCallback.report(STOPPED, 0, 0); + return new CommandResult().success(true).enacted(false) + .message("Bolus cancelled as per user request with no insulin delivered"); + } + } + SystemClock.sleep(10); + } + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, + "Pump did not return to MAIN_MEU from BOLUS_ENTER to deliver bolus. " + + "Check pump manually, the bolus might not have been delivered."); + + progressReportCallback.report(DELIVERING, 0, 0); + Double bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); + double lastBolusReported = 0; + boolean lowCartdrigeAlarmTriggered = false; + // wait for bolus delivery to complete; the remaining units to deliver are counted + // down and are displayed on the main menu. + // TODO extract into method + + // TODO 'low cartrdige' alarm must be handled inside, since the bolus continues regardless; + // it must be claread so we can see the remaining bolus again; + while (bolusRemaining != null) { + if (cancelRequested) { + progressReportCallback.report(STOPPING, 0, 0); + scripter.pressKeyMs(RuffyScripter.Key.UP, 3000); + progressReportCallback.report(STOPPED, 0, 0); + // if the bolus finished while we attempted to cancel it, there'll be no alarm + long timeout = System.currentTimeMillis() + 2000; + while (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR && System.currentTimeMillis() < timeout) { + SystemClock.sleep(10); + } + while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { + // TODO make this cleaner, extract method, needed below too + scripter.pressCheckKey(); + SystemClock.sleep(200); + } + break; + } + if (lastBolusReported != bolusRemaining) { + log.debug("Delivering bolus, remaining: " + bolusRemaining); + int percentDelivered = (int) (100 - (bolusRemaining / bolus * 100)); + progressReportCallback.report(DELIVERING, percentDelivered, bolus - bolusRemaining); + lastBolusReported = bolusRemaining; + } + + if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { + String message = (String) scripter.getCurrentMenu().getAttribute(MenuAttribute.MESSAGE); + if (message.equals("LOW CARTRIDGE")) { + lowCartdrigeAlarmTriggered = true; + confirmAlert("LOW CARTRIDGE", 2000); + } else { + // any other alert + break; + } + } + SystemClock.sleep(50); + bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); + } + + // wait up to 2s for any possible warning to be raised, if not raised already + long minWait = System.currentTimeMillis() + 2 * 1000; + while (scripter.getCurrentMenu().getType() != MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { + SystemClock.sleep(50); + } + + // process warnings (confirm them, report back to AAPS about them) + while (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR || System.currentTimeMillis() < minWait) { + // TODO + } + + // TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus? + // TODO how are error states reported back to the caller that occur outside of calls in genal? Low battery, low cartridge? + + // make sure no alert (occlusion, cartridge empty) has occurred. + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU, + "Bolus delivery did not complete as expected. " + + "Check pump manually, the bolus might not have been delivered."); + + + // TODO report back what was read from history + + // read last bolus record; those menus display static data and therefore + // only a single menu update is sent + scripter.navigateToMenu(MenuType.MY_DATA_MENU); + scripter.verifyMenuIsDisplayed(MenuType.MY_DATA_MENU); + scripter.pressCheckKey(); + if (scripter.getCurrentMenu().getType() != MenuType.BOLUS_DATA) { + scripter.waitForMenuUpdate(); + } + + if (!scripter.getCurrentMenu().attributes().contains(MenuAttribute.BOLUS)) { + throw new CommandException().success(false).enacted(true) + .message("Bolus was delivered, but unable to confirm it with history record"); + } + + // TODO check date so we don't pick a false record if the previous bolus had the same amount; + // also, report back partial bolus. Just call ReadHsstory(timestamp, boluses=true) cmd ... + double lastBolusInHistory = (double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS); + if (Math.abs(bolus - lastBolusInHistory) > 0.05) { + throw new CommandException().success(false).enacted(true) + .message("Last bolus shows " + lastBolusInHistory + + " U delievered, but " + bolus + " U were requested"); + } + log.debug("Bolus record in history confirms delivered bolus"); + + if (!scripter.goToMainTypeScreen(MenuType.MAIN_MENU, 15 * 1000)) { + throw new CommandException().success(false).enacted(true) + .message("Bolus was correctly delivered and checked against history, but we " + + "did not return the main menu successfully."); + } + + progressReportCallback.report(DELIVERED, 100, bolus); + + return new CommandResult().success(true).enacted(true) + .message(String.format(Locale.US, "Delivered %02.1f U", bolus)); + } catch (CommandException e) { + return e.toCommandResult(); + } + } + + // TODO confirmAlarms? and report back which were cancelled? + + private boolean confirmAlert(String alertText, int maxWaitTillExpectedAlert) { + // TODO + return false; + } + + private void enterBolusMenu() { + scripter.verifyMenuIsDisplayed(MenuType.MAIN_MENU); + scripter.navigateToMenu(MenuType.BOLUS_MENU); + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_MENU); + scripter.pressCheckKey(); + scripter.waitForMenuUpdate(); + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + } + + private void inputBolusAmount() { + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + // press 'up' once for each 0.1 U increment + long steps = Math.round(bolus * 10); + for (int i = 0; i < steps; i++) { + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + scripter.pressUpKey(); + SystemClock.sleep(100); + } + // Give the pump time to finish any scrolling that might still be going on, can take + // up to 1100ms. Plus some extra time to be sure + SystemClock.sleep(2000); + } + + private void verifyDisplayedBolusAmount() { + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + + // wait up to 5s for any scrolling to finish + double displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); + long timeout = System.currentTimeMillis() + 10 * 1000; + while (timeout > System.currentTimeMillis() && bolus - displayedBolus > 0.05) { + log.debug("Waiting for pump to process scrolling input for amount, current: " + displayedBolus + ", desired: " + bolus); + displayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); + } + + log.debug("Final bolus: " + displayedBolus); + if (Math.abs(displayedBolus - bolus) > 0.05) { + throw new CommandException().message("Failed to set correct bolus. Expected: " + bolus + ", actual: " + displayedBolus); + } + + // check again to ensure the displayed value hasn't change due to due scrolling taking extremely long + SystemClock.sleep(1000); + scripter.verifyMenuIsDisplayed(MenuType.BOLUS_ENTER); + double refreshedDisplayedBolus = scripter.readBlinkingValue(Double.class, MenuAttribute.BOLUS); + if (Math.abs(displayedBolus - refreshedDisplayedBolus) > 0.05) { + throw new CommandException().message("Failed to set bolus: bolus changed after input stopped from " + + displayedBolus + " -> " + refreshedDisplayedBolus); + } + } + + public void requestCancellation() { + cancelRequested = true; + progressReportCallback.report(STOPPING, 0, 0); + } + + @Override + public String toString() { + return "BolusCommand{" + + "bolus=" + bolus + + '}'; + } + + public interface ProgressReportCallback { + enum State { + DELIVERING, + DELIVERED, + STOPPING, + STOPPED + } + + void report(State state, int percent, double delivered); + } +} From fea1309fa3cabc80a3c6ac39d4516a6b681a7cb9 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 19:05:33 +0200 Subject: [PATCH 46/50] Cleanup merge. --- .../ruffyscripter/commands/DetermineCapabilitiesCommand.java | 0 .../java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java delete mode 100644 app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/DetermineCapabilitiesCommand.java deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/SetTbrCommandAlt.java deleted file mode 100644 index e69de29bb2..0000000000 From b53db22ae14952656906d4e70d87630ac9e72584 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 19:08:27 +0200 Subject: [PATCH 47/50] Report bolus delivered if the pump raised a warning/error during delivery. Most likely this is due to a low cartridge warning, but might also be an occlusion alert. This lets the alarm ring and asks the user to check it. The treatment is also recorded in the db as enacted. (cherry picked from commit 6cc017a) --- .../de/jotomo/ruffyscripter/commands/BolusCommand.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java index bc81be3942..84f56e62e7 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/commands/BolusCommand.java @@ -58,9 +58,16 @@ public class BolusCommand extends BaseCommand { while (bolusRemaining != null) { log.debug("Delivering bolus, remaining: " + bolusRemaining); SystemClock.sleep(200); + if (scripter.getCurrentMenu().getType() == MenuType.WARNING_OR_ERROR) { + throw new CommandException().success(false).enacted(true) + .message("Warning/error raised after bolus delivery started. " + + "The treatment has been recorded, please check it against the " + + "pumps records and delete it if it hasn't finished successfully."); + } bolusRemaining = (Double) scripter.getCurrentMenu().getAttribute(MenuAttribute.BOLUS_REMAINING); } + // TODO what if we hit 'cartridge low' alert here? is it immediately displayed or after the bolus? // TODO how are error states reported back to the caller that occur outside of calls in genal? Low battery, low cartridge? From ecd05bef2d80d531079e3ffb1d2dd39d4d8d22e4 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 19:11:17 +0200 Subject: [PATCH 48/50] Make new BolusCommand configurable. --- .../java/info/nightscout/androidaps/Config.java | 3 +++ .../plugins/PumpCombo/ComboPlugin.java | 16 +++++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 7f3aad2f93..21b32f6a15 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -47,4 +47,7 @@ public class Config { public static final boolean logDanaBTComm = true; public static final boolean logDanaMessageDetail = true; public static final boolean logDanaSerialEngine = true; + + // Combo specific + public static final boolean comboExperimentalBolus = false; } 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 cf824d7224..466a11585e 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 @@ -26,11 +26,13 @@ import de.jotomo.ruffyscripter.PumpState; import de.jotomo.ruffyscripter.RuffyScripter; import de.jotomo.ruffyscripter.commands.BolusCommand; import de.jotomo.ruffyscripter.commands.CancelTbrCommand; +import de.jotomo.ruffyscripter.commands.CancellableBolusCommand; import de.jotomo.ruffyscripter.commands.Command; import de.jotomo.ruffyscripter.commands.CommandResult; import de.jotomo.ruffyscripter.commands.GetPumpStateCommand; import de.jotomo.ruffyscripter.commands.SetTbrCommand; import info.nightscout.androidaps.BuildConfig; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.DetailedBolusInfo; @@ -48,6 +50,11 @@ import info.nightscout.androidaps.plugins.PumpCombo.events.EventComboPumpUpdateG import info.nightscout.utils.DateUtil; import info.nightscout.utils.SP; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.DELIVERED; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.DELIVERING; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.STOPPED; +import static de.jotomo.ruffyscripter.commands.CancellableBolusCommand.ProgressReportCallback.State.STOPPING; + /** * Created by mike on 05.08.2016. */ @@ -356,9 +363,10 @@ public class ComboPlugin implements PluginBase, PumpInterface { return basal; } - private static BolusCommand.ProgressReportCallback bolusProgressReportCallback = new BolusCommand.ProgressReportCallback() { + private static CancellableBolusCommand.ProgressReportCallback bolusProgressReportCallback = + new CancellableBolusCommand.ProgressReportCallback() { @Override - public void report(BolusCommand.ProgressReportCallback.State state, int percent, double delivered) { + public void report(CancellableBolusCommand.ProgressReportCallback.State state, int percent, double delivered) { EventOverviewBolusProgress enent = EventOverviewBolusProgress.getInstance(); switch (state) { case DELIVERING: @@ -391,7 +399,9 @@ public class ComboPlugin implements PluginBase, PumpInterface { // Note that the BolusCommand sends progress updates to the bolusProgressReporterCallback, // which then posts appropriate events on the bus, so in this branch no posts are needed - runningBolusCommand = new BolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback); + runningBolusCommand = Config.comboExperimentalBolus + ? new CancellableBolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback) + : new BolusCommand(detailedBolusInfo.insulin); CommandResult bolusCmdResult = runCommand(runningBolusCommand); runningBolusCommand = null; PumpEnactResult pumpEnactResult = new PumpEnactResult(); From b85f5324de1879292e4d3f2bb90684a49da7c4b4 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Thu, 17 Aug 2017 11:21:16 +0200 Subject: [PATCH 49/50] Restore bolus splitting hack. --- .../jotomo/ruffyscripter/RuffyScripter.java | 2 +- .../info/nightscout/androidaps/Config.java | 6 +- .../plugins/PumpCombo/ComboPlugin.java | 86 +++++++++++++------ 3 files changed, 66 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 7630907160..8a7c9ecaaf 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -212,8 +212,8 @@ public class RuffyScripter { synchronized (RuffyScripter.class) { try { - long connectStart = System.currentTimeMillis(); activeCmd = cmd; + long connectStart = System.currentTimeMillis(); ensureConnected(); final RuffyScripter scripter = this; final Returnable returnable = new Returnable(); diff --git a/app/src/main/java/info/nightscout/androidaps/Config.java b/app/src/main/java/info/nightscout/androidaps/Config.java index 21b32f6a15..285e4e6895 100644 --- a/app/src/main/java/info/nightscout/androidaps/Config.java +++ b/app/src/main/java/info/nightscout/androidaps/Config.java @@ -49,5 +49,9 @@ public class Config { public static final boolean logDanaSerialEngine = true; // Combo specific - public static final boolean comboExperimentalBolus = false; + /** enable the UNFINISHED and currently BROKEN bolus cammand that reports progress and can be cancelled */ + public static final boolean comboExperimentalBolus = true; + /** very quick hack to split up bolus into 2 U parts, spaced roughly 45s apart. + * Don't combine with experimental bolus */ + public static final boolean comboSplitBoluses = false && !comboExperimentalBolus; } 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 466a11585e..9b2861ced0 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 @@ -10,6 +10,7 @@ import android.media.RingtoneManager; import android.net.Uri; import android.os.IBinder; import android.os.SystemClock; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; @@ -224,7 +225,7 @@ public class ComboPlugin implements PluginBase, PumpInterface { } if (!boundSucceeded) { - pump.stateSummary = "No connection to ruffy. Pump control not available."; + pump.stateSummary = "No connection to ruffy. Pump control unavailable."; } return true; } @@ -393,36 +394,41 @@ public class ComboPlugin implements PluginBase, PumpInterface { if (detailedBolusInfo.insulin > 0 || detailedBolusInfo.carbs > 0) { if (detailedBolusInfo.insulin > 0) { // bolus needed, ask pump to deliver it - - // TODO read history to ensure there are no boluses delivered on the pump we aren't - // aware of and haven't included in the bolus calulation - - // Note that the BolusCommand sends progress updates to the bolusProgressReporterCallback, - // which then posts appropriate events on the bus, so in this branch no posts are needed - runningBolusCommand = Config.comboExperimentalBolus - ? new CancellableBolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback) - : new BolusCommand(detailedBolusInfo.insulin); - CommandResult bolusCmdResult = runCommand(runningBolusCommand); - runningBolusCommand = null; - PumpEnactResult pumpEnactResult = new PumpEnactResult(); - pumpEnactResult.success = bolusCmdResult.success; - pumpEnactResult.enacted = bolusCmdResult.enacted; - pumpEnactResult.comment = bolusCmdResult.message; - - // if enacted by pump, add bolus and carbs to treatment history - if (pumpEnactResult.enacted) { - pumpEnactResult.bolusDelivered = detailedBolusInfo.insulin; + if (!Config.comboSplitBoluses) { + return deliverBolus(detailedBolusInfo); + } else { + // split up bolus into 2 U parts + PumpEnactResult pumpEnactResult = new PumpEnactResult(); + pumpEnactResult.success = true; + pumpEnactResult.enacted = true; + pumpEnactResult.bolusDelivered = 0d; pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; - detailedBolusInfo.date = bolusCmdResult.completionTime; + double remainingBolus = detailedBolusInfo.insulin; + int split = 1; + while (remainingBolus > 0.05) { + double bolus = remainingBolus > 2 ? 2 : remainingBolus; + DetailedBolusInfo bolusInfo = new DetailedBolusInfo(); + bolusInfo.insulin = bolus; + bolusInfo.isValid = false; + log.debug("Delivering split bolus #" + split + " with " + bolus + " U"); + PumpEnactResult bolusResult = deliverBolus(bolusInfo); + if (!bolusResult.success) { + return bolusResult; + } + pumpEnactResult.bolusDelivered += bolus; + remainingBolus -= 2; + split++; + } MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); - } else { - pumpEnactResult.bolusDelivered = 0d; - pumpEnactResult.carbsDelivered = 0d; + return pumpEnactResult; } - return pumpEnactResult; } else { // no bolus required, carb only treatment + + // TODO the ui freezes when the calculator issues a carb-only treatment + // so just wait, yeah, this is dumb. for now; proper fix via GL#10 + // info.nightscout.androidaps.plugins.Overview.Dialogs.BolusProgressDialog.scheduleDismiss() SystemClock.sleep(6000); PumpEnactResult pumpEnactResult = new PumpEnactResult(); pumpEnactResult.success = true; @@ -450,6 +456,35 @@ public class ComboPlugin implements PluginBase, PumpInterface { } } + @NonNull + private PumpEnactResult deliverBolus(DetailedBolusInfo detailedBolusInfo) { + runningBolusCommand = Config.comboExperimentalBolus + ? new CancellableBolusCommand(detailedBolusInfo.insulin, bolusProgressReportCallback) + : new BolusCommand(detailedBolusInfo.insulin); + CommandResult bolusCmdResult = runCommand(runningBolusCommand); + PumpEnactResult pumpEnactResult = new PumpEnactResult(); + pumpEnactResult.success = bolusCmdResult.success; + pumpEnactResult.enacted = bolusCmdResult.enacted; + pumpEnactResult.comment = bolusCmdResult.message; + + // if enacted, add bolus and carbs to treatment history + if (pumpEnactResult.enacted) { + // TODO if no error occurred, the requested bolus is what the pump delievered, + // that has been checked. If an error occurred, we should check how much insulin + // was delivered, e.g. when the cartridge went empty mid-bolus + // For the first iteration, the alert the pump raises must suffice + pumpEnactResult.bolusDelivered = detailedBolusInfo.insulin; + pumpEnactResult.carbsDelivered = detailedBolusInfo.carbs; + + detailedBolusInfo.date = bolusCmdResult.completionTime; + MainApp.getConfigBuilder().addToHistoryTreatment(detailedBolusInfo); + } else { + pumpEnactResult.bolusDelivered = 0d; + pumpEnactResult.carbsDelivered = 0d; + } + return pumpEnactResult; + } + @Override public void stopBolusDelivering() { BolusCommand localRunningBolusCommand = runningBolusCommand; @@ -553,7 +588,6 @@ public class ComboPlugin implements PluginBase, PumpInterface { @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer durationInMinutes) { - // TODO GL#70 return OPERATION_NOT_SUPPORTED; } From e3a732d53d499b669ad328ca6c5ebdc2e2345399 Mon Sep 17 00:00:00 2001 From: Johannes Mockenhaupt Date: Sun, 27 Aug 2017 20:30:58 +0200 Subject: [PATCH 50/50] Small refactoring. --- app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java index 8a7c9ecaaf..2934ee7eed 100644 --- a/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java +++ b/app/src/main/java/de/jotomo/ruffyscripter/RuffyScripter.java @@ -311,8 +311,7 @@ public class RuffyScripter { returnable.cmdResult.state = readPumpState(); } long connectDurationSec = (executionStart - connectStart) / 1000; - long now = System.currentTimeMillis(); - long executionDurationSec = (now - executionStart) / 1000; + long executionDurationSec = (System.currentTimeMillis() - executionStart) / 1000; returnable.cmdResult.duration = "Connect: " + connectDurationSec + "s, execution: " + executionDurationSec + "s"; log.debug("Command result: " + returnable.cmdResult); return returnable.cmdResult;