From a186ce6468c1be8c1e279f48589da7a287ad0e3a Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 10 Nov 2017 00:27:18 +0100 Subject: [PATCH] more command queue code --- .../androidaps/interfaces/PumpInterface.java | 10 +- .../ConfigBuilder/ConfigBuilderPlugin.java | 48 ++- .../plugins/ProfileNS/NSProfilePlugin.java | 3 +- .../plugins/PumpDanaR/DanaRPlugin.java | 34 +- .../PumpDanaR/Dialogs/ProfileViewDialog.java | 6 +- .../plugins/PumpDanaR/comm/MsgCheckValue.java | 2 +- .../PumpDanaR/comm/MsgInitConnStatusTime.java | 2 +- .../PumpDanaRKorean/DanaRKoreanPlugin.java | 34 +- .../PumpDanaRKorean/comm/MsgCheckValue_k.java | 2 +- .../comm/MsgInitConnStatusTime_k.java | 2 +- .../plugins/PumpDanaRS/CommandQueue.java | 347 ------------------ .../plugins/PumpDanaRS/DanaRSPlugin.java | 35 +- .../plugins/PumpDanaRS/services/BLEComm.java | 30 -- .../plugins/PumpDanaRv2/DanaRv2Plugin.java | 34 +- .../PumpDanaRv2/comm/MsgCheckValue_v2.java | 4 +- .../androidaps/plugins/PumpMDI/MDIPlugin.java | 24 +- .../PumpVirtual/VirtualPumpPlugin.java | 26 +- .../nightscout/androidaps/queue/Callback.java | 24 ++ .../nightscout/androidaps/queue/Command.java | 21 ++ .../androidaps/queue/CommandBolus.java | 31 ++ .../queue/CommandCancelExtendedBolus.java | 28 ++ .../queue/CommandCancelTempBasal.java | 30 ++ .../queue/CommandExtendedBolus.java | 32 ++ .../androidaps/queue/CommandQueue.java | 235 ++++++++++++ .../androidaps/queue/CommandReadStatus.java | 25 ++ .../androidaps/queue/CommandSetProfile.java | 31 ++ .../queue/CommandTempBasalAbsolute.java | 34 ++ .../queue/CommandTempBasalPercent.java | 32 ++ .../androidaps/queue/QueueThread.java | 69 ++++ 29 files changed, 786 insertions(+), 449 deletions(-) delete mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/CommandQueue.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/Callback.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/Command.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandBolus.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandCancelExtendedBolus.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandCancelTempBasal.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandExtendedBolus.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandReadStatus.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandSetProfile.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalAbsolute.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalPercent.java create mode 100644 app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java index eb04ce85fb..070189cb66 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpInterface.java @@ -16,12 +16,14 @@ public interface PumpInterface { boolean isInitialized(); boolean isSuspended(); boolean isBusy(); + boolean isConnected(); + boolean isConnecting(); + + void connect(String reason); + void disconnect(String reason); // Upload to pump new basal profile - int SUCCESS = 0; - int FAILED = 1; - int NOT_NEEDED = 2; - int setNewBasalProfile(Profile profile); + PumpEnactResult setNewBasalProfile(Profile profile); boolean isThisProfileSet(Profile profile); Date lastDataTime(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java index 12f1f46c1c..a2d513c8c5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ConfigBuilder/ConfigBuilderPlugin.java @@ -52,6 +52,7 @@ import info.nightscout.androidaps.plugins.Overview.events.EventDismissBolusprogr import info.nightscout.androidaps.plugins.Overview.events.EventDismissNotification; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.PumpVirtual.VirtualPumpPlugin; +import info.nightscout.androidaps.queue.CommandQueue; import info.nightscout.utils.NSUpload; import info.nightscout.utils.SP; @@ -79,6 +80,8 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain private PowerManager.WakeLock mWakeLock; + private static CommandQueue commandQueue = new CommandQueue(); + public ConfigBuilderPlugin() { MainApp.bus().register(this); PowerManager powerManager = (PowerManager) MainApp.instance().getApplicationContext().getSystemService(Context.POWER_SERVICE); @@ -197,6 +200,10 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain verifySelectionInCategories(); } + public static CommandQueue getCommandQueue() { + return commandQueue; + } + public static BgSourceInterface getActiveBgSource() { return activeBgSource; } @@ -384,7 +391,34 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain } @Override - public int setNewBasalProfile(Profile profile) { + public boolean isConnected() { + if (activePump != null) + return activePump.isConnected(); + return false; + } + + @Override + public boolean isConnecting() { + if (activePump != null) + return activePump.isConnecting(); + return false; + } + + @Override + public void connect(String reason) { + if (activePump != null) + activePump.connect(reason); + } + + @Override + public void disconnect(String reason) { + if (activePump != null) + activePump.disconnect(reason); + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); // Compare with pump limits Profile.BasalValue[] basalValues = profile.getBasalValues(); @@ -392,7 +426,9 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain if (basalValues[index].value < getPumpDescription().basalMinimumRate) { Notification notification = new Notification(Notification.BASAL_VALUE_BELOW_MINIMUM, MainApp.sResources.getString(R.string.basalvaluebelowminimum), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.success = false; + result.comment = MainApp.sResources.getString(R.string.basalvaluebelowminimum); + return result; } } @@ -400,11 +436,11 @@ public class ConfigBuilderPlugin implements PluginBase, PumpInterface, Constrain if (isThisProfileSet(profile)) { log.debug("Correct profile already set"); - return NOT_NEEDED; - } else if (activePump != null) { - return activePump.setNewBasalProfile(profile); + result.success = true; + result.enacted = false; + return result; } else - return SUCCESS; + return activePump.setNewBasalProfile(profile); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java index 3476d3682d..dec14b344d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/ProfileNS/NSProfilePlugin.java @@ -121,14 +121,13 @@ public class NSProfilePlugin implements PluginBase, ProfileInterface { storeNSProfile(); MainApp.bus().post(new EventNSProfileUpdateGUI()); if (SP.getBoolean("syncprofiletopump", false)) { - if (ConfigBuilderPlugin.getActivePump().setNewBasalProfile(MainApp.getConfigBuilder().getProfile()) == PumpInterface.SUCCESS) { + if (ConfigBuilderPlugin.getActivePump().setNewBasalProfile(MainApp.getConfigBuilder().getProfile()).enacted == true) { SmsCommunicatorPlugin smsCommunicatorPlugin = MainApp.getSpecificPlugin(SmsCommunicatorPlugin.class); if (smsCommunicatorPlugin != null && smsCommunicatorPlugin.isEnabled(PluginBase.GENERAL)) { smsCommunicatorPlugin.sendNotificationToAllNumbers(MainApp.sResources.getString(R.string.profile_set_ok)); } } } - } private static void storeNSProfile() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/DanaRPlugin.java index f7e1c6b92f..cdcab62f48 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 @@ -245,27 +245,35 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C // Pump interface @Override - public int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -297,7 +305,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C @Override public void refreshDataFromPump(String reason) { if (!isConnected() && !isConnecting()) { - doConnect(reason); + connect(reason); } } @@ -350,7 +358,7 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - doConnect("setTempBasalAbsolute old data"); + connect("setTempBasalAbsolute old data"); } PumpEnactResult result = new PumpEnactResult(); @@ -653,7 +661,8 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } } - public static void doConnect(String from) { + @Override + public void connect(String from) { if (sExecutionService != null) { sExecutionService.connect(from); pumpDescription.basalStep = pump.basalStep; @@ -661,15 +670,18 @@ public class DanaRPlugin implements PluginBase, PumpInterface, DanaRInterface, C } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return sExecutionService != null && sExecutionService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return sExecutionService != null && sExecutionService.isConnecting(); } - public static void doDisconnect(String from) { + @Override + public void disconnect(String from) { if (sExecutionService != null) sExecutionService.disconnect(from); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java index fc7a9a2411..9554e18164 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/Dialogs/ProfileViewDialog.java @@ -77,11 +77,11 @@ public class ProfileViewDialog extends DialogFragment { public void run() { DanaRPump.getInstance().lastSettingsRead = new Date(0); if (MainApp.getSpecificPlugin(DanaRPlugin.class).isEnabled(PluginBase.PUMP)) - DanaRPlugin.doConnect("ProfileViewDialog"); + DanaRPlugin.getPlugin().connect("ProfileViewDialog"); if (MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).isEnabled(PluginBase.PUMP)) - DanaRKoreanPlugin.doConnect("ProfileViewDialog"); + DanaRKoreanPlugin.getPlugin().connect("ProfileViewDialog"); if (MainApp.getSpecificPlugin(DanaRv2Plugin.class).isEnabled(PluginBase.PUMP)) - DanaRv2Plugin.doConnect("ProfileViewDialog"); + DanaRv2Plugin.getPlugin().connect("ProfileViewDialog"); } }); dismiss(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java index c05029caff..785e90650a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgCheckValue.java @@ -32,7 +32,7 @@ public class MsgCheckValue extends MessageBase { pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.EXPORT_MODEL) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model"); + ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).disconnect("Wrong Model"); log.debug("Wrong model selected"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java index dfd5788ec9..2b2667f92c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaR/comm/MsgInitConnStatusTime.java @@ -26,7 +26,7 @@ public class MsgInitConnStatusTime extends MessageBase { public void handleMessage(byte[] bytes) { if (bytes.length - 10 > 7) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).doDisconnect("Wrong Model"); + ((DanaRPlugin) MainApp.getSpecificPlugin(DanaRPlugin.class)).disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to Korean DanaR"); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, true); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, true); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java index cda438aded..d8fde0e3ba 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/DanaRKoreanPlugin.java @@ -247,27 +247,35 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf // Pump interface @Override - public int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -299,7 +307,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf @Override public void refreshDataFromPump(String reason) { if (!isConnected() && !isConnecting()) { - doConnect(reason); + connect(reason); } } @@ -353,7 +361,7 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - doConnect("setTempBasalAbsolute old data"); + connect("setTempBasalAbsolute old data"); } PumpEnactResult result = new PumpEnactResult(); @@ -650,7 +658,8 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } } - public static void doConnect(String from) { + @Override + public void connect(String from) { if (sExecutionService != null) { sExecutionService.connect(from); pumpDescription.basalStep = pump.basalStep; @@ -658,15 +667,18 @@ public class DanaRKoreanPlugin implements PluginBase, PumpInterface, DanaRInterf } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return sExecutionService != null && sExecutionService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return sExecutionService != null && sExecutionService.isConnecting(); } - public static void doDisconnect(String from) { + @Override + public void disconnect(String from) { if (sExecutionService != null) sExecutionService.disconnect(from); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java index 7536bd278c..f048c07f20 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgCheckValue_k.java @@ -33,7 +33,7 @@ public class MsgCheckValue_k extends MessageBase { pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.DOMESTIC_MODEL) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); + DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected"); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java index f54b8edb30..c72be877d4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRKorean/comm/MsgInitConnStatusTime_k.java @@ -28,7 +28,7 @@ public class MsgInitConnStatusTime_k extends MessageBase { if (bytes.length - 10 < 10) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - ((DanaRKoreanPlugin)MainApp.getSpecificPlugin(DanaRKoreanPlugin.class)).doDisconnect("Wrong Model"); + DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to export DanaR"); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentEnabled(PluginBase.PUMP, false); MainApp.getSpecificPlugin(DanaRKoreanPlugin.class).setFragmentVisible(PluginBase.PUMP, false); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/CommandQueue.java deleted file mode 100644 index d0651086ed..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/CommandQueue.java +++ /dev/null @@ -1,347 +0,0 @@ -package info.nightscout.androidaps.plugins.PumpDanaRS; - -import android.text.Html; -import android.text.Spanned; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.LinkedList; - -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.PumpEnactResult; -import info.nightscout.utils.DecimalFormatter; - -/** - * Created by mike on 08.11.2017. - */ - -public class CommandQueue { - private static Logger log = LoggerFactory.getLogger(CommandQueue.class); - - enum CommandType { - BOLUS, - TEMPBASALPERCENT, - TEMPBASALABSOLUTE, - CANCELTEMPBASAL, - EXTENDEDBOLUS, - CANCELEXTENDEDBOLUS, - SETBASALPROFILE - } - - public class Command { - CommandType commandType; - Callback callback; - - int durationInMinutes; - - // Bolus - DetailedBolusInfo detailedBolusInfo; - // Temp basal percent - int percent; - // Temp basal absolute - double absoluteRate; - boolean enforceNew; - // Extended bolus - double insulin; - // Basal profile - Profile profile; - - public String status() { - switch (commandType) { - case BOLUS: - return "BOLUS " + DecimalFormatter.to1Decimal(detailedBolusInfo.insulin) + "U"; - case TEMPBASALPERCENT: - return "TEMPBASAL " + percent + "% " + durationInMinutes + " min"; - case TEMPBASALABSOLUTE: - return "TEMPBASAL " + absoluteRate + " U/h " + durationInMinutes + " min"; - case CANCELTEMPBASAL: - return "CANCEL TEMPBASAL"; - case EXTENDEDBOLUS: - return "EXTENDEDBOLUS " + insulin + " U " + durationInMinutes + " min"; - case CANCELEXTENDEDBOLUS: - return "CANCEL EXTENDEDBOLUS"; - case SETBASALPROFILE: - return "SETPROFILE"; - default: - return ""; - } - } - } - - public class Callback { - public PumpEnactResult result; - Runnable runnable; - - public Callback(Runnable runnable) { - this.runnable = runnable; - } - - public Callback result(PumpEnactResult result) { - this.result = result; - return this; - } - - public void run() { - runnable.run(); - } - } - - private LinkedList queue = new LinkedList<>(); - private Command performing; - - private PumpEnactResult executingNowError() { - PumpEnactResult result = new PumpEnactResult(); - result.success = false; - result.enacted = false; - result.comment = MainApp.sResources.getString(R.string.executingrightnow); - return result; - } - - public boolean isRunningTempBasal() { - if (performing != null) - if (performing.commandType == CommandType.TEMPBASALABSOLUTE || performing.commandType == CommandType.TEMPBASALPERCENT || performing.commandType == CommandType.CANCELTEMPBASAL) - return true; - return false; - } - - public boolean isRunningBolus() { - if (performing != null) - if (performing.commandType == CommandType.BOLUS) - return true; - return false; - } - - public boolean isRunningExtendedBolus() { - if (performing != null) - if (performing.commandType == CommandType.EXTENDEDBOLUS || performing.commandType == CommandType.CANCELEXTENDEDBOLUS) - return true; - return false; - } - - public boolean isRunningProfile() { - if (performing != null) - if (performing.commandType == CommandType.SETBASALPROFILE) - return true; - return false; - } - - private synchronized void removeAll(CommandType type) { - for (int i = 0; i < queue.size(); i++) { - Command c = queue.get(i); - switch (type) { - case TEMPBASALABSOLUTE: - case TEMPBASALPERCENT: - case CANCELTEMPBASAL: - if (c.commandType == CommandType.TEMPBASALABSOLUTE || c.commandType == CommandType.TEMPBASALPERCENT || c.commandType == CommandType.CANCELTEMPBASAL) { - queue.remove(i); - } - break; - case BOLUS: - if (c.commandType == CommandType.BOLUS) { - queue.remove(i); - } - break; - case EXTENDEDBOLUS: - case CANCELEXTENDEDBOLUS: - if (c.commandType == CommandType.EXTENDEDBOLUS || c.commandType == CommandType.CANCELEXTENDEDBOLUS) { - queue.remove(i); - } - break; - case SETBASALPROFILE: - if (c.commandType == CommandType.SETBASALPROFILE) { - queue.remove(i); - } - break; - } - } - } - - private synchronized void add(Command command) { - queue.add(command); - } - - private synchronized void pickup() { - performing = queue.poll(); - } - - public void clear() { - queue.clear(); - } - - private void notifyAboutNewCommand() { - - } - - // returns true if command is queued - public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { - if (isRunningBolus()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.BOLUS); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.BOLUS; - command.detailedBolusInfo = detailedBolusInfo; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - // returns true if command is queued - public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) { - if (isRunningTempBasal()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.TEMPBASALABSOLUTE); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.TEMPBASALABSOLUTE; - command.absoluteRate = absoluteRate; - command.durationInMinutes = durationInMinutes; - command.enforceNew = enforceNew; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - // returns true if command is queued - public boolean tempBasalPercent(int percent, int durationInMinutes, Callback callback) { - if (isRunningTempBasal()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.TEMPBASALPERCENT); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.TEMPBASALPERCENT; - command.percent = percent; - command.durationInMinutes = durationInMinutes; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - // returns true if command is queued - public boolean extendedBolus(double insulin, int durationInMinutes, Callback callback) { - if (isRunningExtendedBolus()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.EXTENDEDBOLUS); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.EXTENDEDBOLUS; - command.insulin = insulin; - command.durationInMinutes = durationInMinutes; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - // returns true if command is queued - public boolean cancelTempBasal(boolean enforceNew, Callback callback) { - if (isRunningTempBasal()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.CANCELTEMPBASAL); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.CANCELTEMPBASAL; - command.enforceNew = enforceNew; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - // returns true if command is queued - public boolean cancelExtended(Callback callback) { - if (isRunningExtendedBolus()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.CANCELEXTENDEDBOLUS); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.CANCELEXTENDEDBOLUS; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - // returns true if command is queued - public boolean setProfile(Profile profile, Callback callback) { - if (isRunningProfile()) { - callback.result(executingNowError()).run(); - return false; - } - - // remove all unfinished boluese - removeAll(CommandType.SETBASALPROFILE); - - // add new command to queue - Command command = new Command(); - command.commandType = CommandType.SETBASALPROFILE; - command.profile = profile; - command.callback = callback; - add(command); - - notifyAboutNewCommand(); - - return true; - } - - Spanned spannedStatus() { - String s = ""; - if (performing != null) { - s += "" + performing.status() + "
"; - } - for (int i = 0; i < queue.size(); i++) { - s += queue.get(i).status() + "
"; - } - return Html.fromHtml(s); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java index 916213c270..bab828696f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/DanaRSPlugin.java @@ -219,12 +219,13 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, mDeviceName = SP.getString(R.string.key_danars_name, ""); } - public static void connectIfNotConnected(String from) { + public void connectIfNotConnected(String from) { if (!isConnected()) connect(from); } - public static void connect(String from) { + @Override + public void connect(String from) { log.debug("RS connect from: " + from); if (danaRSService != null && !mDeviceAddress.equals("") && !mDeviceName.equals("")) { final Object o = new Object(); @@ -249,15 +250,18 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return danaRSService != null && danaRSService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return danaRSService != null && danaRSService.isConnecting(); } - public static void disconnect(String from) { + @Override + public void disconnect(String from) { if (danaRSService != null) danaRSService.disconnect(from); } @@ -383,30 +387,35 @@ public class DanaRSPlugin implements PluginBase, PumpInterface, DanaRInterface, } @Override - public synchronized int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (danaRSService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } - connectIfNotConnected("updateBasalsInPump"); if (!danaRSService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - disconnect("SetNewBasalProfile"); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - disconnect("SetNewBasalProfile"); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java index 42f077887d..c2b11dbfb1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRS/services/BLEComm.java @@ -10,8 +10,6 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; -import android.os.Handler; -import android.os.HandlerThread; import android.os.SystemClock; import com.cozmo.danar.util.BleCommandUtil; @@ -33,7 +31,6 @@ import info.nightscout.androidaps.events.EventPumpStatusChanged; import info.nightscout.androidaps.plugins.PumpDanaR.DanaRPump; import info.nightscout.androidaps.plugins.PumpDanaRS.DanaRSPlugin; import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingHelperActivity; -import info.nightscout.androidaps.plugins.PumpDanaRS.activities.PairingProgressDialog; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRSMessageHashTable; import info.nightscout.androidaps.plugins.PumpDanaRS.comm.DanaRS_Packet; import info.nightscout.androidaps.plugins.PumpDanaRS.events.EventDanaRSPacket; @@ -70,19 +67,6 @@ public class BLEComm { private DanaRS_Packet processsedMessage = null; private ArrayList mSendQueue = new ArrayList<>(); - // Variables for connection progress (elapsed time) - private Handler sHandler; - private HandlerThread sHandlerThread; - private long connectionStartTime = 0; - private final Runnable updateProgress = new Runnable() { - @Override - public void run() { - long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); - sHandler.postDelayed(updateProgress, 1000); - } - }; - private BluetoothManager mBluetoothManager = null; private BluetoothAdapter mBluetoothAdapter = null; private BluetoothDevice mBluetoothDevice = null; @@ -101,12 +85,6 @@ public class BLEComm { BLEComm(DanaRSService service) { this.service = service; initialize(); - - if (sHandlerThread == null) { - sHandlerThread = new HandlerThread(PairingProgressDialog.class.getSimpleName()); - sHandlerThread.start(); - sHandler = new Handler(sHandlerThread.getLooper()); - } } private boolean initialize() { @@ -160,9 +138,6 @@ public class BLEComm { return false; } - connectionStartTime = System.currentTimeMillis(); - - MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING)); isConnecting = true; BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); @@ -171,7 +146,6 @@ public class BLEComm { return false; } - sHandler.post(updateProgress); mBluetoothGatt = device.connectGatt(service.getApplicationContext(), false, mGattCallback); setCharacteristicNotification(getUARTReadBTGattChar(), true); log.debug("Trying to create a new connection."); @@ -183,7 +157,6 @@ public class BLEComm { public void stopConnecting() { isConnecting = false; - sHandler.removeCallbacks(updateProgress); // just to be sure } public void disconnect(String from) { @@ -234,7 +207,6 @@ public class BLEComm { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { close(); isConnected = false; - sHandler.removeCallbacks(updateProgress); // just to be sure MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.DISCONNECTED)); log.debug("Device was disconnected " + gatt.getDevice().getName());//Device was disconnected } @@ -248,8 +220,6 @@ public class BLEComm { if (status == BluetoothGatt.GATT_SUCCESS) { findCharacteristic(); } - // stop sending connection progress - sHandler.removeCallbacks(updateProgress); SendPumpCheck(); // 1st message sent to pump after connect } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java index f2ad2fd659..8aed0780d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/DanaRv2Plugin.java @@ -232,27 +232,35 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, // Pump interface @Override - public int setNewBasalProfile(Profile profile) { + public PumpEnactResult setNewBasalProfile(Profile profile) { + PumpEnactResult result = new PumpEnactResult(); + if (sExecutionService == null) { log.error("setNewBasalProfile sExecutionService is null"); - return FAILED; + result.comment = "setNewBasalProfile sExecutionService is null"; + return result; } if (!isInitialized()) { log.error("setNewBasalProfile not initialized"); Notification notification = new Notification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED, MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.pumpNotInitializedProfileNotSet); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); } if (!sExecutionService.updateBasalsInPump(profile)) { Notification notification = new Notification(Notification.FAILED_UDPATE_PROFILE, MainApp.sResources.getString(R.string.failedupdatebasalprofile), Notification.URGENT); MainApp.bus().post(new EventNewNotification(notification)); - return FAILED; + result.comment = MainApp.sResources.getString(R.string.failedupdatebasalprofile); + return result; } else { MainApp.bus().post(new EventDismissNotification(Notification.PROFILE_NOT_SET_NOT_INITIALIZED)); MainApp.bus().post(new EventDismissNotification(Notification.FAILED_UDPATE_PROFILE)); - return SUCCESS; + result.success = true; + result.enacted = true; + result.comment = "OK"; + return result; } } @@ -284,7 +292,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, @Override public void refreshDataFromPump(String reason) { if (!isConnected() && !isConnecting()) { - doConnect(reason); + connect(reason); } } @@ -361,7 +369,7 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, boolean enforceNew) { // Recheck pump status if older than 30 min if (pump.lastConnection.getTime() + 30 * 60 * 1000L < System.currentTimeMillis()) { - doConnect("setTempBasalAbsolute old data"); + connect("setTempBasalAbsolute old data"); } PumpEnactResult result = new PumpEnactResult(); @@ -597,7 +605,8 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, } } - public static void doConnect(String from) { + @Override + public void connect(String from) { if (sExecutionService != null) { sExecutionService.connect(from); pumpDescription.basalStep = pump.basalStep; @@ -605,15 +614,18 @@ public class DanaRv2Plugin implements PluginBase, PumpInterface, DanaRInterface, } } - public static boolean isConnected() { + @Override + public boolean isConnected() { return sExecutionService != null && sExecutionService.isConnected(); } - public static boolean isConnecting() { + @Override + public boolean isConnecting() { return sExecutionService != null && sExecutionService.isConnecting(); } - public static void doDisconnect(String from) { + @Override + public void disconnect(String from) { if (sExecutionService != null) sExecutionService.disconnect(from); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java index d7b37a4b0f..e31a1a3443 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpDanaRv2/comm/MsgCheckValue_v2.java @@ -37,13 +37,13 @@ public class MsgCheckValue_v2 extends MessageBase { pump.productCode = intFromBuff(bytes, 2, 1); if (pump.model != DanaRPump.EXPORT_MODEL) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(), MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - DanaRv2Plugin.doDisconnect("Wrong Model"); + DanaRv2Plugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected"); } if (pump.protocol != 2) { ToastUtils.showToastInUiThread(MainApp.instance().getApplicationContext(),MainApp.sResources.getString(R.string.wrongpumpdriverselected), R.raw.error); - DanaRKoreanPlugin.doDisconnect("Wrong Model"); + DanaRKoreanPlugin.getPlugin().disconnect("Wrong Model"); log.debug("Wrong model selected. Switching to non APS DanaR"); (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentEnabled(PluginBase.PUMP, false); (MainApp.getSpecificPlugin(DanaRv2Plugin.class)).setFragmentVisible(PluginBase.PUMP, false); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java index da4ea8157d..f48f944886 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpMDI/MDIPlugin.java @@ -130,9 +130,29 @@ public class MDIPlugin implements PluginBase, PumpInterface { } @Override - public int setNewBasalProfile(Profile profile) { + public boolean isConnected() { + return true; + } + + @Override + public boolean isConnecting() { + return false; + } + + @Override + public void connect(String reason) { + } + + @Override + public void disconnect(String reason) { + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); - return SUCCESS; + PumpEnactResult result = new PumpEnactResult(); + result.success = true; + return result; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 2e3be7ab95..06b979c52b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -185,10 +185,30 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { } @Override - public int setNewBasalProfile(Profile profile) { - // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); + public boolean isConnected() { + return true; + } + + @Override + public boolean isConnecting() { + return false; + } + + @Override + public void connect(String reason) { + } + + @Override + public void disconnect(String reason) { + } + + @Override + public PumpEnactResult setNewBasalProfile(Profile profile) { lastDataTime = new Date(); - return SUCCESS; + // Do nothing here. we are using MainApp.getConfigBuilder().getActiveProfile().getProfile(); + PumpEnactResult result = new PumpEnactResult(); + result.success = true; + return result; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/queue/Callback.java b/app/src/main/java/info/nightscout/androidaps/queue/Callback.java new file mode 100644 index 0000000000..a4b458ed43 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/Callback.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; + +/** + * Created by mike on 09.11.2017. + */ +public class Callback { + public PumpEnactResult result; + Runnable runnable; + + public Callback(Runnable runnable) { + this.runnable = runnable; + } + + public Callback result(PumpEnactResult result) { + this.result = result; + return this; + } + + public void run() { + runnable.run(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/Command.java b/app/src/main/java/info/nightscout/androidaps/queue/Command.java new file mode 100644 index 0000000000..8971b1abf7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/Command.java @@ -0,0 +1,21 @@ +package info.nightscout.androidaps.queue; + +/** + * Created by mike on 09.11.2017. + */ +public abstract class Command { + enum CommandType { + BOLUS, + TEMPBASAL, + EXTENDEDBOLUS, + BASALPROFILE, + READSTATUS + } + + CommandType commandType; + Callback callback; + + public abstract void execute(); + + public abstract String status(); +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandBolus.java new file mode 100644 index 0000000000..ef9472c14e --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandBolus.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.DetailedBolusInfo; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; +import info.nightscout.utils.DecimalFormatter; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandBolus extends Command { + DetailedBolusInfo detailedBolusInfo; + + CommandBolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { + commandType = CommandType.BOLUS; + this.detailedBolusInfo = detailedBolusInfo; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().deliverTreatment(detailedBolusInfo); + if (callback != null) + callback.result(r).run(); + } + + public String status() { + return "BOLUS " + DecimalFormatter.to1Decimal(detailedBolusInfo.insulin) + "U"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandCancelExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandCancelExtendedBolus.java new file mode 100644 index 0000000000..4c50ab04b3 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandCancelExtendedBolus.java @@ -0,0 +1,28 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandCancelExtendedBolus extends Command { + + public CommandCancelExtendedBolus(Callback callback) { + commandType = CommandType.EXTENDEDBOLUS; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().cancelExtendedBolus(); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "CANCEL EXTENDEDBOLUS"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandCancelTempBasal.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandCancelTempBasal.java new file mode 100644 index 0000000000..dce8f53784 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandCancelTempBasal.java @@ -0,0 +1,30 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandCancelTempBasal extends Command { + boolean enforceNew; + + CommandCancelTempBasal(boolean enforceNew, Callback callback) { + commandType = CommandType.TEMPBASAL; + this.enforceNew = enforceNew; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().cancelTempBasal(enforceNew); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "CANCEL TEMPBASAL"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandExtendedBolus.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandExtendedBolus.java new file mode 100644 index 0000000000..85b3c70315 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandExtendedBolus.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandExtendedBolus extends Command { + double insulin; + int durationInMinutes; + + public CommandExtendedBolus(double insulin, int durationInMinutes, Callback callback) { + commandType = CommandType.EXTENDEDBOLUS; + this.insulin = insulin; + this.durationInMinutes = durationInMinutes; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setExtendedBolus(insulin, durationInMinutes); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "EXTENDEDBOLUS " + insulin + " U " + durationInMinutes + " min"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java new file mode 100644 index 0000000000..35b823f38d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandQueue.java @@ -0,0 +1,235 @@ +package info.nightscout.androidaps.queue; + +import android.text.Html; +import android.text.Spanned; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.LinkedList; + +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.PumpEnactResult; + +/** + * Created by mike on 08.11.2017. + */ + +public class CommandQueue { + private static Logger log = LoggerFactory.getLogger(CommandQueue.class); + + private LinkedList queue = new LinkedList<>(); + private Command performing; + + private QueueThread thread = new QueueThread(this); + + private PumpEnactResult executingNowError() { + PumpEnactResult result = new PumpEnactResult(); + result.success = false; + result.enacted = false; + result.comment = MainApp.sResources.getString(R.string.executingrightnow); + return result; + } + + public boolean isRunningTempBasal() { + if (performing != null && performing.commandType == Command.CommandType.TEMPBASAL) + return true; + return false; + } + + public boolean isRunningBolus() { + if (performing != null && performing.commandType == Command.CommandType.BOLUS) + return true; + return false; + } + + public boolean isRunningExtendedBolus() { + if (performing != null && performing.commandType == Command.CommandType.EXTENDEDBOLUS) + return true; + return false; + } + + public boolean isRunningProfile() { + if (performing != null && performing.commandType == Command.CommandType.BASALPROFILE) + return true; + return false; + } + + private synchronized void removeAll(Command.CommandType type) { + for (int i = 0; i < queue.size(); i++) { + if (queue.get(i).commandType == type) { + queue.remove(i); + } + } + } + + private synchronized void add(Command command) { + queue.add(command); + } + + protected synchronized void pickup() { + performing = queue.poll(); + } + + public void clear() { + queue.clear(); + } + + public int size() { + return queue.size(); + } + + public Command performing() { + return performing; + } + + public void resetPerforming() { + performing = null; + } + + private void notifyAboutNewCommand() { + if (!thread.isAlive()) + thread.start(); + } + + // returns true if command is queued + public boolean bolus(DetailedBolusInfo detailedBolusInfo, Callback callback) { + if (isRunningBolus()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluses + removeAll(Command.CommandType.BOLUS); + + // add new command to queue + add(new CommandBolus(detailedBolusInfo, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean tempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) { + if (isRunningTempBasal()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluese + removeAll(Command.CommandType.TEMPBASAL); + + // add new command to queue + add(new CommandTempBasalAbsolute(absoluteRate, durationInMinutes, enforceNew, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean tempBasalPercent(int percent, int durationInMinutes, Callback callback) { + if (isRunningTempBasal()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluese + removeAll(Command.CommandType.TEMPBASAL); + + // add new command to queue + add(new CommandTempBasalPercent(percent, durationInMinutes, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean extendedBolus(double insulin, int durationInMinutes, Callback callback) { + if (isRunningExtendedBolus()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluese + removeAll(Command.CommandType.EXTENDEDBOLUS); + + // add new command to queue + add(new CommandExtendedBolus(insulin, durationInMinutes, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean cancelTempBasal(boolean enforceNew, Callback callback) { + if (isRunningTempBasal()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluese + removeAll(Command.CommandType.TEMPBASAL); + + // add new command to queue + add(new CommandCancelTempBasal(enforceNew, callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean cancelExtended(Callback callback) { + if (isRunningExtendedBolus()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluese + removeAll(Command.CommandType.EXTENDEDBOLUS); + + // add new command to queue + add(new CommandCancelExtendedBolus(callback)); + + notifyAboutNewCommand(); + + return true; + } + + // returns true if command is queued + public boolean setProfile(Profile profile, Callback callback) { + if (isRunningProfile()) { + callback.result(executingNowError()).run(); + return false; + } + + // remove all unfinished boluese + removeAll(Command.CommandType.BASALPROFILE); + + // add new command to queue + add(new CommandSetProfile(profile, callback)); + + notifyAboutNewCommand(); + + return true; + } + + Spanned spannedStatus() { + String s = ""; + if (performing != null) { + s += "" + performing.status() + "
"; + } + for (int i = 0; i < queue.size(); i++) { + s += queue.get(i).status() + "
"; + } + return Html.fromHtml(s); + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandReadStatus.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandReadStatus.java new file mode 100644 index 0000000000..e8ceb84091 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandReadStatus.java @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.queue; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandReadStatus extends Command { + + CommandReadStatus(Callback callback) { + commandType = CommandType.READSTATUS; + this.callback = callback; + } + + @Override + public void execute() { + // do nothing by default. Status is read on connection + if (callback != null) + callback.result(null).run(); + } + + @Override + public String status() { + return "READ STATUS"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandSetProfile.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandSetProfile.java new file mode 100644 index 0000000000..273e3b344c --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandSetProfile.java @@ -0,0 +1,31 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandSetProfile extends Command { + Profile profile; + + CommandSetProfile(Profile profile, Callback callback) { + commandType = CommandType.BASALPROFILE; + this.profile = profile; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setNewBasalProfile(profile); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "SETPROFILE"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalAbsolute.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalAbsolute.java new file mode 100644 index 0000000000..136efe72be --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalAbsolute.java @@ -0,0 +1,34 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandTempBasalAbsolute extends Command { + int durationInMinutes; + double absoluteRate; + boolean enforceNew; + + CommandTempBasalAbsolute(double absoluteRate, int durationInMinutes, boolean enforceNew, Callback callback) { + commandType = CommandType.TEMPBASAL; + this.absoluteRate = absoluteRate; + this.durationInMinutes = durationInMinutes; + this.enforceNew = enforceNew; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalAbsolute(absoluteRate, durationInMinutes, enforceNew); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "TEMPBASAL " + absoluteRate + " U/h " + durationInMinutes + " min"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalPercent.java b/app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalPercent.java new file mode 100644 index 0000000000..a645f7a93a --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/CommandTempBasalPercent.java @@ -0,0 +1,32 @@ +package info.nightscout.androidaps.queue; + +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class CommandTempBasalPercent extends Command { + int durationInMinutes; + int percent; + + CommandTempBasalPercent(int percent, int durationInMinutes, Callback callback) { + commandType = CommandType.TEMPBASAL; + this.percent = percent; + this.durationInMinutes = durationInMinutes; + this.callback = callback; + } + + @Override + public void execute() { + PumpEnactResult r = ConfigBuilderPlugin.getActivePump().setTempBasalPercent(percent, durationInMinutes); + if (callback != null) + callback.result(r).run(); + } + + @Override + public String status() { + return "TEMPBASAL " + percent + "% " + durationInMinutes + " min"; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java new file mode 100644 index 0000000000..41c9f42434 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.java @@ -0,0 +1,69 @@ +package info.nightscout.androidaps.queue; + +import android.os.SystemClock; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.events.EventPumpStatusChanged; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.ConfigBuilder.ConfigBuilderPlugin; + +/** + * Created by mike on 09.11.2017. + */ + +public class QueueThread extends Thread { + private static Logger log = LoggerFactory.getLogger(QueueThread.class); + + CommandQueue queue; + boolean keepRunning = false; + + + private long connectionStartTime = 0; + + public QueueThread(CommandQueue queue) { + super(QueueThread.class.toString()); + + this.queue = queue; + keepRunning = true; + } + + @Override + public final void run() { + PumpInterface pump = ConfigBuilderPlugin.getActivePump(); + + while (keepRunning) { + if (pump.isConnecting()) { + long secondsElapsed = (System.currentTimeMillis() - connectionStartTime) / 1000; + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING, (int) secondsElapsed)); + SystemClock.sleep(1000); + } + + if (!pump.isConnected()) { + MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.CONNECTING)); + pump.connect("Not connected"); + connectionStartTime = System.currentTimeMillis(); + SystemClock.sleep(1000); + } + + if (queue.performing() == null) { + // Pickup 1st command and set performing variable + if (queue.size() > 0) { + queue.pickup(); + queue.performing().execute(); + queue.resetPerforming(); + } + + } + + if (queue.size() == 0 && queue.performing() == null) { + pump.disconnect("Queue empty"); + keepRunning = false; + } + } + } + + +}