diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index 5c5c8a8335..11b3b77f39 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -162,6 +162,7 @@ public class MainApp extends DaggerApplication { @Inject TreatmentsPlugin treatmentsPlugin; @Inject VirtualPumpPlugin virtualPumpPlugin; @Inject VersionCheckerPlugin versionCheckerPlugin; + @Inject WearPlugin wearPlugin; @Override public void onCreate() { @@ -259,7 +260,7 @@ public class MainApp extends DaggerApplication { if (!Config.NSCLIENT) pluginsList.add(smsCommunicatorPlugin); pluginsList.add(FoodPlugin.getPlugin()); - pluginsList.add(WearPlugin.initPlugin(this)); + pluginsList.add(wearPlugin); pluginsList.add(statusLinePlugin); pluginsList.add(PersistentNotificationPlugin.getPlugin()); pluginsList.add(NSClientPlugin.getPlugin()); diff --git a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.java b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.java index 5744310d94..923e667865 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.java @@ -74,6 +74,7 @@ public class MyPreferenceFragment extends PreferenceFragment implements HasAndro @Inject StatusLinePlugin statusLinePlugin; @Inject TidepoolPlugin tidepoolPlugin; @Inject VirtualPumpPlugin virtualPumpPlugin; + @Inject WearPlugin wearPlugin; @Override public void setArguments(Bundle args) { @@ -157,7 +158,7 @@ public class MyPreferenceFragment extends PreferenceFragment implements HasAndro addPreferencesFromResource(R.xml.pref_others); addPreferencesFromResource(R.xml.pref_datachoices); - addPreferencesFromResourceIfEnabled(WearPlugin.getPlugin(), PluginType.GENERAL); + addPreferencesFromResourceIfEnabled(wearPlugin, PluginType.GENERAL); addPreferencesFromResourceIfEnabled(statusLinePlugin, PluginType.GENERAL); } diff --git a/app/src/main/java/info/nightscout/androidaps/logging/L.kt b/app/src/main/java/info/nightscout/androidaps/logging/L.kt index 2ec1473c08..ad13015378 100644 --- a/app/src/main/java/info/nightscout/androidaps/logging/L.kt +++ b/app/src/main/java/info/nightscout/androidaps/logging/L.kt @@ -31,6 +31,7 @@ object L { const val UI = "UI" const val LOCATION = "LOCATION" const val SMS = "SMS" + const val WEAR = "WEAR" init { logElements.add(LogElement(APS, defaultValue = true)) @@ -58,6 +59,7 @@ object L { logElements.add(LogElement(PUMPQUEUE, true)) logElements.add(LogElement(SMS, true)) logElements.add(LogElement(UI, true)) + logElements.add(LogElement(WEAR, true)) } private fun findByName(name: String): LogElement { @@ -145,5 +147,6 @@ enum class LTag(val tag: String) { CONFIGBUILDER("CONFIGBUILDER"), UI("UI"), LOCATION("LOCATION"), + WEAR("WEAR"), SMS("SMS"), } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java index e6ff69ba39..13845568c3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopPlugin.java @@ -78,6 +78,7 @@ public class LoopPlugin extends PluginBase { private final ConfigBuilderPlugin configBuilderPlugin; private final TreatmentsPlugin treatmentsPlugin; private final VirtualPumpPlugin virtualPumpPlugin; + private final ActionStringHandler actionStringHandler; private CompositeDisposable disposable = new CompositeDisposable(); @@ -111,6 +112,7 @@ public class LoopPlugin extends PluginBase { public Date lastOpenModeAccept; } + @Deprecated static public LastRun lastRun = null; @Inject @@ -124,7 +126,8 @@ public class LoopPlugin extends PluginBase { MainApp mainApp, ConfigBuilderPlugin configBuilderPlugin, TreatmentsPlugin treatmentsPlugin, - VirtualPumpPlugin virtualPumpPlugin + VirtualPumpPlugin virtualPumpPlugin, + ActionStringHandler actionStringHandler ) { super(new PluginDescription() .mainType(PluginType.LOOP) @@ -145,6 +148,7 @@ public class LoopPlugin extends PluginBase { this.configBuilderPlugin = configBuilderPlugin; this.treatmentsPlugin = treatmentsPlugin; this.virtualPumpPlugin = virtualPumpPlugin; + this.actionStringHandler = actionStringHandler; loopSuspendedTill = sp.getLong("loopSuspendedTill", 0L); isSuperBolus = sp.getBoolean("isSuperBolus", false); @@ -471,13 +475,13 @@ public class LoopPlugin extends PluginBase { rxBus.send(new EventNewOpenLoopNotification()); // Send to Wear - ActionStringHandler.handleInitiate("changeRequest"); + actionStringHandler.handleInitiate("changeRequest"); } else if (allowNotification) { // dismiss notifications NotificationManager notificationManager = (NotificationManager) mainApp.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(Constants.notificationID); - ActionStringHandler.handleInitiate("cancelChangeRequest"); + actionStringHandler.handleInitiate("cancelChangeRequest"); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java index ccb02124e0..c70cbedfc7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/OverviewFragment.java @@ -141,6 +141,7 @@ public class OverviewFragment extends DaggerFragment implements View.OnClickList @Inject DexcomPlugin dexcomPlugin; @Inject XdripPlugin xdripPlugin; @Inject NotificationStore notificationStore; + @Inject ActionStringHandler actionStringHandler; private CompositeDisposable disposable = new CompositeDisposable(); @@ -968,7 +969,7 @@ public class OverviewFragment extends DaggerFragment implements View.OnClickList (NotificationManager) mainApp.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel(Constants.notificationID); - ActionStringHandler.handleInitiate("cancelChangeRequest"); + actionStringHandler.handleInitiate("cancelChangeRequest"); } private void updatePumpStatus(String status) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java deleted file mode 100644 index 2dc275f9d8..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.java +++ /dev/null @@ -1,758 +0,0 @@ -package info.nightscout.androidaps.plugins.general.wear; - -import android.app.NotificationManager; -import android.content.Context; - -import androidx.annotation.NonNull; - -import java.text.DateFormat; -import java.text.DecimalFormat; -import java.text.SimpleDateFormat; -import java.util.Collections; -import java.util.Comparator; -import java.util.Date; -import java.util.LinkedList; -import java.util.List; - -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.db.BgReading; -import info.nightscout.androidaps.db.CareportalEvent; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.db.ProfileSwitch; -import info.nightscout.androidaps.db.Source; -import info.nightscout.androidaps.db.TDD; -import info.nightscout.androidaps.db.TempTarget; -import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; -import info.nightscout.androidaps.plugins.bus.RxBus; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker; -import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog; -import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.CobInfo; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; -import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin; -import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; -import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin; -import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin; -import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin; -import info.nightscout.androidaps.plugins.treatments.CarbsGenerator; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.queue.Callback; -import info.nightscout.androidaps.utils.BolusWizard; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.HardLimits; -import info.nightscout.androidaps.utils.SP; -import info.nightscout.androidaps.utils.SafeParse; -import info.nightscout.androidaps.utils.ToastUtils; - -/** - * Created by adrian on 09/02/17. - */ - -public class ActionStringHandler { - - public static final int TIMEOUT = 65 * 1000; - - private static long lastSentTimestamp = 0; - private static String lastConfirmActionString = null; - private static BolusWizard lastBolusWizard = null; - - public synchronized static void handleInitiate(String actionstring) { - - if (!SP.getBoolean("wearcontrol", false)) return; - - lastBolusWizard = null; - - String rTitle = "CONFIRM"; //TODO: i18n - String rMessage = ""; - String rAction = ""; - - - // do the parsing and check constraints - String[] act = actionstring.split("\\s+"); - - if ("fillpreset".equals(act[0])) { - ///////////////////////////////////// PRIME/FILL - double amount = 0d; - if ("1".equals(act[1])) { - amount = SP.getDouble("fill_button1", 0.3); - } else if ("2".equals(act[1])) { - amount = SP.getDouble("fill_button2", 0d); - } else if ("3".equals(act[1])) { - amount = SP.getDouble("fill_button3", 0d); - } else { - return; - } - Double insulinAfterConstraints = ConstraintChecker.getInstance().applyBolusConstraints(new Constraint<>(amount)).value(); - rMessage += MainApp.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"; - if (insulinAfterConstraints - amount != 0) - rMessage += "\n" + MainApp.gs(R.string.constraintapllied); - - rAction += "fill " + insulinAfterConstraints; - - } else if ("fill".equals(act[0])) { - ////////////////////////////////////////////// PRIME/FILL - double amount = SafeParse.stringToDouble(act[1]); - - Double insulinAfterConstraints = ConstraintChecker.getInstance().applyBolusConstraints(new Constraint<>(amount)).value(); - rMessage += MainApp.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U"; - if (insulinAfterConstraints - amount != 0) - rMessage += "\n" + MainApp.gs(R.string.constraintapllied); - - rAction += "fill " + insulinAfterConstraints; - - } else if ("bolus".equals(act[0])) { - ////////////////////////////////////////////// BOLUS - double insulin = SafeParse.stringToDouble(act[1]); - int carbs = SafeParse.stringToInt(act[2]); - Double insulinAfterConstraints = ConstraintChecker.getInstance().applyBolusConstraints(new Constraint<>(insulin)).value(); - Integer carbsAfterConstraints = ConstraintChecker.getInstance().applyCarbsConstraints(new Constraint<>(carbs)).value(); - rMessage += MainApp.gs(R.string.bolus) + ": " + insulinAfterConstraints + "U\n"; - rMessage += MainApp.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - - if ((insulinAfterConstraints - insulin != 0) || (carbsAfterConstraints - carbs != 0)) { - rMessage += "\n" + MainApp.gs(R.string.constraintapllied); - } - rAction += "bolus " + insulinAfterConstraints + " " + carbsAfterConstraints; - - } else if ("temptarget".equals(act[0])) { - ///////////////////////////////////////////////////////// TEMPTARGET - boolean isMGDL = Boolean.parseBoolean(act[1]); - - if (ProfileFunctions.getSystemUnits().equals(Constants.MGDL) != isMGDL) { - sendError("Different units used on watch and phone!"); - return; - } - - int duration = SafeParse.stringToInt(act[2]); - if (duration == 0) { - rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?"; - rAction = "temptarget true 0 0 0"; - } else { - double low = SafeParse.stringToDouble(act[3]); - double high = SafeParse.stringToDouble(act[4]); - if (!isMGDL) { - low *= Constants.MMOLL_TO_MGDL; - high *= Constants.MMOLL_TO_MGDL; - } - if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) { - sendError("Min-BG out of range!"); - return; - } - if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) { - sendError("Max-BG out of range!"); - return; - } - rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2]; - rAction = actionstring; - - } - - } else if ("status".equals(act[0])) { - ////////////////////////////////////////////// STATUS - rTitle = "STATUS"; - rAction = "statusmessage"; - if ("pump".equals(act[1])) { - rTitle += " PUMP"; - rMessage = getPumpStatus(); - } else if ("loop".equals(act[1])) { - rTitle += " LOOP"; - rMessage = "TARGETS:\n" + getTargetsStatus(); - rMessage += "\n\n" + getLoopStatus(); - rMessage += "\n\nOAPS RESULT:\n" + getOAPSResultStatus(); - } - - } else if ("wizard".equals(act[0])) { - sendError("Update APP on Watch!"); - return; - } else if ("wizard2".equals(act[0])) { - ////////////////////////////////////////////// WIZARD - Integer carbsBeforeConstraints = SafeParse.stringToInt(act[1]); - Integer carbsAfterConstraints = ConstraintChecker.getInstance().applyCarbsConstraints(new Constraint<>(carbsBeforeConstraints)).value(); - - if (carbsAfterConstraints - carbsBeforeConstraints != 0) { - sendError("Carb constraint violation!"); - return; - } - - boolean useBG = SP.getBoolean(R.string.key_wearwizard_bg, true); - boolean useTT = SP.getBoolean(R.string.key_wearwizard_tt, false); - boolean useBolusIOB = SP.getBoolean(R.string.key_wearwizard_bolusiob, true); - boolean useBasalIOB = SP.getBoolean(R.string.key_wearwizard_basaliob, true); - boolean useCOB = SP.getBoolean(R.string.key_wearwizard_cob, true); - boolean useTrend = SP.getBoolean(R.string.key_wearwizard_trend, false); - int percentage = Integer.parseInt(act[2]); - - Profile profile = ProfileFunctions.getInstance().getProfile(); - String profileName = ProfileFunctions.getInstance().getProfileName(); - if (profile == null) { - sendError("No profile found!"); - return; - } - - BgReading bgReading = DatabaseHelper.actualBg(); - if (bgReading == null && useBG) { - sendError("No recent BG to base calculation on!"); - return; - } - - CobInfo cobInfo = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "Wizard wear"); - if (useCOB && (cobInfo == null || cobInfo.displayCob == null)) { - sendError("Unknown COB! BG reading missing or recent app restart?"); - return; - } - - DecimalFormat format = new DecimalFormat("0.00"); - DecimalFormat formatInt = new DecimalFormat("0"); - BolusWizard bolusWizard = new BolusWizard(profile, profileName, TreatmentsPlugin.getPlugin().getTempTargetFromHistory(), - carbsAfterConstraints, cobInfo.displayCob, bgReading.valueToUnits(ProfileFunctions.getSystemUnits()), - 0d, percentage, useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend); - - if (Math.abs(bolusWizard.getInsulinAfterConstraints() - bolusWizard.getCalculatedTotalInsulin()) >= 0.01) { - sendError("Insulin constraint violation!" + - "\nCannot deliver " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "!"); - return; - } - - if (bolusWizard.getCalculatedTotalInsulin() <= 0 && bolusWizard.getCarbs() <= 0) { - rAction = "info"; - rTitle = "INFO"; - } else { - rAction = actionstring; - } - rMessage += "Carbs: " + bolusWizard.getCarbs() + "g"; - rMessage += "\nBolus: " + format.format(bolusWizard.getCalculatedTotalInsulin()) + "U"; - rMessage += "\n_____________"; - rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.getIc()) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.getSens()) + "): "; - rMessage += "\nFrom Carbs: " + format.format(bolusWizard.getInsulinFromCarbs()) + "U"; - if (useCOB) - rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.getInsulinFromCOB()) + "U"; - if (useBG) - rMessage += "\nFrom BG: " + format.format(bolusWizard.getInsulinFromBG()) + "U"; - if (useBolusIOB) - rMessage += "\nBolus IOB: " + format.format(bolusWizard.getInsulinFromBolusIOB()) + "U"; - if (useBasalIOB) - rMessage += "\nBasal IOB: " + format.format(bolusWizard.getInsulinFromBasalsIOB()) + "U"; - if (useTrend) - rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.getInsulinFromTrend()) + "U"; - if (percentage != 100) { - rMessage += "\nPercentage: " + format.format(bolusWizard.getTotalBeforePercentageAdjustment()) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.getCalculatedTotalInsulin()) + "U"; - } - - lastBolusWizard = bolusWizard; - - } else if ("opencpp".equals(act[0])) { - ProfileSwitch activeProfileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis()); - if (activeProfileSwitch == null) { - sendError("No active profile switch!"); - return; - } else { - // read CPP values - rTitle = "opencpp"; - rMessage = "opencpp"; - rAction = "opencpp" + " " + activeProfileSwitch.percentage + " " + activeProfileSwitch.timeshift; - } - - } else if ("cppset".equals(act[0])) { - ProfileSwitch activeProfileSwitch = TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(System.currentTimeMillis()); - if (activeProfileSwitch == null) { - sendError("No active profile switch!"); - return; - } else { - // read CPP values - rMessage = "CPP:" + "\n\n" + - "Timeshift: " + act[1] + "\n" + - "Percentage: " + act[2] + "%"; - rAction = actionstring; - } - - } else if ("tddstats".equals(act[0])) { - Object activePump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (activePump != null) { - // check if DB up to date - List dummies = new LinkedList(); - List historyList = getTDDList(dummies); - - if (isOldData(historyList)) { - rTitle = "TDD"; - rAction = "statusmessage"; - rMessage = "OLD DATA - "; - - //if pump is not busy: try to fetch data - final PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (pump.isBusy()) { - rMessage += MainApp.gs(R.string.pumpbusy); - } else { - rMessage += "trying to fetch data from pump."; - - ConfigBuilderPlugin.getPlugin().getCommandQueue().loadTDDs(new Callback() { - @Override - public void run() { - List dummies = new LinkedList(); - List historyList = getTDDList(dummies); - if (isOldData(historyList)) { - sendStatusmessage("TDD", "TDD: Still old data! Cannot load from pump.\n" + generateTDDMessage(historyList, dummies)); - } else { - sendStatusmessage("TDD", generateTDDMessage(historyList, dummies)); - } - } - }); - } - } else { - // if up to date: prepare, send (check if CPP is activated -> add CPP stats) - rTitle = "TDD"; - rAction = "statusmessage"; - rMessage = generateTDDMessage(historyList, dummies); - } - } - - } else if ("ecarbs".equals(act[0])) { - ////////////////////////////////////////////// ECARBS - int carbs = SafeParse.stringToInt(act[1]); - int starttime = SafeParse.stringToInt(act[2]); - int duration = SafeParse.stringToInt(act[3]); - long starttimestamp = System.currentTimeMillis() + starttime * 60 * 1000; - Integer carbsAfterConstraints = ConstraintChecker.getInstance().applyCarbsConstraints(new Constraint<>(carbs)).value(); - rMessage += MainApp.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g"; - rMessage += "\n" + MainApp.gs(R.string.time) + ": " + DateUtil.timeString(starttimestamp); - rMessage += "\n" + MainApp.gs(R.string.duration) + ": " + duration + "h"; - - - if ((carbsAfterConstraints - carbs != 0)) { - rMessage += "\n" + MainApp.gs(R.string.constraintapllied); - } - if (carbsAfterConstraints <= 0) { - sendError("Carbs = 0! No action taken!"); - return; - } - rAction += "ecarbs " + carbsAfterConstraints + " " + starttimestamp + " " + duration; - - } else if ("changeRequest".equals(act[0])) { - ////////////////////////////////////////////// CHANGE REQUEST - rTitle = MainApp.gs(R.string.openloop_newsuggestion); - rAction = "changeRequest"; - final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; - rMessage += finalLastRun.constraintsProcessed; - - WearPlugin.getPlugin().requestChangeConfirmation(rTitle, rMessage, rAction); - lastSentTimestamp = System.currentTimeMillis(); - lastConfirmActionString = rAction; - return; - } else if ("cancelChangeRequest".equals(act[0])) { - ////////////////////////////////////////////// CANCEL CHANGE REQUEST NOTIFICATION - rAction = "cancelChangeRequest"; - - WearPlugin.getPlugin().requestNotificationCancel(rAction); - return; - } else return; - - - // send result - WearPlugin.getPlugin().requestActionConfirmation(rTitle, rMessage, rAction); - lastSentTimestamp = System.currentTimeMillis(); - lastConfirmActionString = rAction; - } - - private static String generateTDDMessage(List historyList, List dummies) { - - Profile profile = ProfileFunctions.getInstance().getProfile(); - - if (profile == null) { - return "No profile loaded :("; - } - - if (historyList.isEmpty()) { - return "No history data!"; - } - - DateFormat df = new SimpleDateFormat("dd.MM."); - String message = ""; - - double refTDD = profile.baseBasalSum() * 2; - - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - if (df.format(new Date(historyList.get(0).date)).equals(df.format(new Date()))) { - double tdd = historyList.get(0).getTotal(); - historyList.remove(0); - message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n"; - message += "\n"; - } else if (pump != null && pump instanceof DanaRPlugin) { - double tdd = DanaRPump.getInstance().dailyTotalUnits; - message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n"; - message += "\n"; - } - - int i = 0; - double sum = 0d; - double weighted03 = 0d; - double weighted05 = 0d; - double weighted07 = 0d; - - Collections.reverse(historyList); - for (TDD record : historyList) { - double tdd = record.getTotal(); - if (i == 0) { - weighted03 = tdd; - weighted05 = tdd; - weighted07 = tdd; - - } else { - weighted07 = (weighted07 * 0.3 + tdd * 0.7); - weighted05 = (weighted05 * 0.5 + tdd * 0.5); - weighted03 = (weighted03 * 0.7 + tdd * 0.3); - } - i++; - } - message += "weighted:\n"; - message += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (DecimalFormatter.to0Decimal(100 * weighted03 / refTDD) + "%") + "\n"; - message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (DecimalFormatter.to0Decimal(100 * weighted05 / refTDD) + "%") + "\n"; - message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (DecimalFormatter.to0Decimal(100 * weighted07 / refTDD) + "%") + "\n"; - message += "\n"; - Collections.reverse(historyList); - - //add TDDs: - for (TDD record : historyList) { - double tdd = record.getTotal(); - message += df.format(new Date(record.date)) + " " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + (dummies.contains(record) ? "x" : "") + "\n"; - } - return message; - } - - public static boolean isOldData(List historyList) { - Object activePump = ConfigBuilderPlugin.getPlugin().getActivePump(); - PumpInterface dana = DanaRPlugin.getPlugin(); - PumpInterface danaRS = DanaRSPlugin.getPlugin(); - PumpInterface danaV2 = DanaRv2Plugin.getPlugin(); - PumpInterface danaKorean = DanaRKoreanPlugin.getPlugin(); - PumpInterface insight = LocalInsightPlugin.getPlugin(); - - boolean startsYesterday = activePump == dana || activePump == danaRS || activePump == danaV2 || activePump == danaKorean || activePump == insight; - - DateFormat df = new SimpleDateFormat("dd.MM."); - return (historyList.size() < 3 || !(df.format(new Date(historyList.get(0).date)).equals(df.format(new Date(System.currentTimeMillis() - (startsYesterday ? 1000 * 60 * 60 * 24 : 0)))))); - } - - @NonNull - public static List getTDDList(List returnDummies) { - List historyList = MainApp.getDbHelper().getTDDs(); - - historyList = historyList.subList(0, Math.min(10, historyList.size())); - - //fill single gaps - only needed for Dana*R data - List dummies = (returnDummies != null) ? returnDummies : (new LinkedList()); - DateFormat df = new SimpleDateFormat("dd.MM."); - for (int i = 0; i < historyList.size() - 1; i++) { - TDD elem1 = historyList.get(i); - TDD elem2 = historyList.get(i + 1); - - if (!df.format(new Date(elem1.date)).equals(df.format(new Date(elem2.date + 25 * 60 * 60 * 1000)))) { - TDD dummy = new TDD(); - dummy.date = elem1.date - 24 * 60 * 60 * 1000; - dummy.basal = elem1.basal / 2; - dummy.bolus = elem1.bolus / 2; - dummies.add(dummy); - elem1.basal /= 2; - elem1.bolus /= 2; - - - } - } - historyList.addAll(dummies); - Collections.sort(historyList, new Comparator() { - @Override - public int compare(TDD lhs, TDD rhs) { - return (int) (rhs.date - lhs.date); - } - }); - - return historyList; - } - - @NonNull - private static String getPumpStatus() { - return ConfigBuilderPlugin.getPlugin().getActivePump().shortStatus(false); - } - - @NonNull - private static String getLoopStatus() { - String ret = ""; - // decide if enabled/disabled closed/open; what Plugin as APS? - final LoopPlugin loopPlugin = LoopPlugin.getPlugin(); - if (loopPlugin.isEnabled(loopPlugin.getType())) { - if (ConstraintChecker.getInstance().isClosedLoopAllowed().value()) { - ret += "CLOSED LOOP\n"; - } else { - ret += "OPEN LOOP\n"; - } - final APSInterface aps = ConfigBuilderPlugin.getPlugin().getActiveAPS(); - ret += "APS: " + ((aps == null) ? "NO APS SELECTED!" : ((PluginBase) aps).getName()); - if (LoopPlugin.lastRun != null) { - if (LoopPlugin.lastRun.lastAPSRun != null) - ret += "\nLast Run: " + DateUtil.timeString(LoopPlugin.lastRun.lastAPSRun); - - if (LoopPlugin.lastRun.lastEnact != null) - ret += "\nLast Enact: " + DateUtil.timeString(LoopPlugin.lastRun.lastEnact); - - } - - - } else { - ret += "LOOP DISABLED\n"; - } - return ret; - - } - - @NonNull - private static String getTargetsStatus() { - String ret = ""; - if (!Config.APS) { - return "Targets only apply in APS mode!"; - } - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile == null) { - return "No profile set :("; - } - - //Check for Temp-Target: - TempTarget tempTarget = TreatmentsPlugin.getPlugin().getTempTargetFromHistory(); - if (tempTarget != null) { - ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.low, tempTarget.low, Constants.MGDL, ProfileFunctions.getSystemUnits()); - ret += "\nuntil: " + DateUtil.timeString(tempTarget.originalEnd()); - ret += "\n\n"; - } - - ret += "DEFAULT RANGE: "; - ret += Profile.fromMgdlToUnits(profile.getTargetLowMgdl(), ProfileFunctions.getSystemUnits()) + " - " + Profile.fromMgdlToUnits(profile.getTargetHighMgdl(), ProfileFunctions.getSystemUnits()); - ret += " target: " + Profile.fromMgdlToUnits(profile.getTargetMgdl(), ProfileFunctions.getSystemUnits()); - return ret; - } - - private static String getOAPSResultStatus() { - String ret = ""; - if (!Config.APS) { - return "Only apply in APS mode!"; - } - Profile profile = ProfileFunctions.getInstance().getProfile(); - if (profile == null) { - return "No profile set :("; - } - - APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS(); - if (usedAPS == null) { - return "No active APS :(!"; - } - - APSResult result = usedAPS.getLastAPSResult(); - if (result == null) { - return "Last result not available!"; - } - - if (!result.isChangeRequested()) { - ret += MainApp.gs(R.string.nochangerequested) + "\n"; - } else if (result.rate == 0 && result.duration == 0) { - ret += MainApp.gs(R.string.canceltemp) + "\n"; - } else { - ret += MainApp.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(result.rate) + " U/h " + - "(" + DecimalFormatter.to2Decimal(result.rate / ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate() * 100) + "%)\n" + - MainApp.gs(R.string.duration) + ": " + DecimalFormatter.to0Decimal(result.duration) + " min\n"; - } - ret += "\n" + MainApp.gs(R.string.reason) + ": " + result.reason; - - return ret; - } - - - public synchronized static void handleConfirmation(String actionString) { - - if (!SP.getBoolean("wearcontrol", false)) return; - - - //Guard from old or duplicate confirmations - if (lastConfirmActionString == null) return; - if (!lastConfirmActionString.equals(actionString)) return; - if (System.currentTimeMillis() - lastSentTimestamp > TIMEOUT) return; - lastConfirmActionString = null; - - // do the parsing, check constraints and enact! - String[] act = actionString.split("\\s+"); - - if ("fill".equals(act[0])) { - Double amount = SafeParse.stringToDouble(act[1]); - Double insulinAfterConstraints = ConstraintChecker.getInstance().applyBolusConstraints(new Constraint<>(amount)).value(); - if (amount - insulinAfterConstraints != 0) { - ToastUtils.showToastInUiThread(MainApp.instance(), "aborting: previously applied constraint changed"); - sendError("aborting: previously applied constraint changed"); - return; - } - doFillBolus(amount); - } else if ("temptarget".equals(act[0])) { - int duration = SafeParse.stringToInt(act[2]); - double low = SafeParse.stringToDouble(act[3]); - double high = SafeParse.stringToDouble(act[4]); - boolean isMGDL = Boolean.parseBoolean(act[1]); - if (!isMGDL) { - low *= Constants.MMOLL_TO_MGDL; - high *= Constants.MMOLL_TO_MGDL; - } - generateTempTarget(duration, low, high); - } else if ("wizard2".equals(act[0])) { - if (lastBolusWizard != null) { - //use last calculation as confirmed string matches - - doBolus(lastBolusWizard.getCalculatedTotalInsulin(), lastBolusWizard.getCarbs()); - lastBolusWizard = null; - } - } else if ("bolus".equals(act[0])) { - double insulin = SafeParse.stringToDouble(act[1]); - int carbs = SafeParse.stringToInt(act[2]); - doBolus(insulin, carbs); - } else if ("cppset".equals(act[0])) { - int timeshift = SafeParse.stringToInt(act[1]); - int percentage = SafeParse.stringToInt(act[2]); - setCPP(timeshift, percentage); - } else if ("ecarbs".equals(act[0])) { - int carbs = SafeParse.stringToInt(act[1]); - long starttime = SafeParse.stringToLong(act[2]); - int duration = SafeParse.stringToInt(act[3]); - - doECarbs(carbs, starttime, duration); - } else if ("dismissoverviewnotification".equals(act[0])) { - RxBus.Companion.getINSTANCE().send(new EventDismissNotification(SafeParse.stringToInt(act[1]))); - } else if ("changeRequest".equals(act[0])) { - LoopPlugin.getPlugin().acceptChangeRequest(); - NotificationManager notificationManager = - (NotificationManager) MainApp.instance().getSystemService(Context.NOTIFICATION_SERVICE); - notificationManager.cancel(Constants.notificationID); - } - lastBolusWizard = null; - } - - private static void doECarbs(int carbs, long time, int duration) { - if (carbs > 0) { - if (duration == 0) { - CarbsGenerator.createCarb(carbs, time, CareportalEvent.CARBCORRECTION, "watch"); - } else { - CarbsGenerator.generateCarbs(carbs, time, duration, "watch eCarbs"); - } - } - } - - private static void setCPP(int timeshift, int percentage) { - - String msg = ""; - - - //check for validity - if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { - msg += String.format(MainApp.gs(R.string.valueoutofrange), "Profile-Percentage") + "\n"; - } - if (timeshift < 0 || timeshift > 23) { - msg += String.format(MainApp.gs(R.string.valueoutofrange), "Profile-Timeshift") + "\n"; - } - final Profile profile = ProfileFunctions.getInstance().getProfile(); - - if (profile == null) { - msg += MainApp.gs(R.string.notloadedplugins) + "\n"; - } - if (!"".equals(msg)) { - msg += MainApp.gs(R.string.valuesnotstored); - String rTitle = "STATUS"; - String rAction = "statusmessage"; - WearPlugin.getPlugin().requestActionConfirmation(rTitle, msg, rAction); - lastSentTimestamp = System.currentTimeMillis(); - lastConfirmActionString = rAction; - return; - } - - //send profile to pumpe - TreatmentsPlugin.getPlugin().doProfileSwitch(0, percentage, timeshift); - } - - private static void generateTempTarget(int duration, double low, double high) { - TempTarget tempTarget = new TempTarget() - .date(System.currentTimeMillis()) - .duration(duration) - .reason("WearPlugin") - .source(Source.USER); - if (tempTarget.durationInMinutes != 0) { - tempTarget.low(low).high(high); - } else { - tempTarget.low(0).high(0); - } - TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); - } - - private static void doFillBolus(final Double amount) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = amount; - detailedBolusInfo.isValid = false; - detailedBolusInfo.source = Source.USER; - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - sendError(MainApp.gs(R.string.treatmentdeliveryerror) + - "\n" + - result.comment); - } - } - }); - } - - private static void doBolus(final Double amount, final Integer carbs) { - DetailedBolusInfo detailedBolusInfo = new DetailedBolusInfo(); - detailedBolusInfo.insulin = amount; - detailedBolusInfo.carbs = carbs; - detailedBolusInfo.source = Source.USER; - if (detailedBolusInfo.insulin > 0 || ConfigBuilderPlugin.getPlugin().getActivePump().getPumpDescription().storesCarbInfo) { - ConfigBuilderPlugin.getPlugin().getCommandQueue().bolus(detailedBolusInfo, new Callback() { - @Override - public void run() { - if (!result.success) { - sendError(MainApp.gs(R.string.treatmentdeliveryerror) + - "\n" + - result.comment); - } - } - }); - } else { - TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, false); - } - } - - private synchronized static void sendError(String errormessage) { - WearPlugin.getPlugin().requestActionConfirmation("ERROR", errormessage, "error"); - lastSentTimestamp = System.currentTimeMillis(); - lastConfirmActionString = null; - lastBolusWizard = null; - } - - private synchronized static void sendStatusmessage(String title, String message) { - WearPlugin.getPlugin().requestActionConfirmation(title, message, "statusmessage"); - lastSentTimestamp = System.currentTimeMillis(); - lastConfirmActionString = null; - lastBolusWizard = null; - } - - public synchronized static void expectNotificationAction(String message, int id) { - String actionstring = "dismissoverviewnotification " + id; - WearPlugin.getPlugin().requestActionConfirmation("DISMISS", message, actionstring); - lastSentTimestamp = System.currentTimeMillis(); - lastConfirmActionString = actionstring; - lastBolusWizard = null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt new file mode 100644 index 0000000000..3093500878 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/ActionStringHandler.kt @@ -0,0 +1,619 @@ +package info.nightscout.androidaps.plugins.general.wear + +import android.app.NotificationManager +import android.content.Context +import dagger.Lazy +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.db.CareportalEvent +import info.nightscout.androidaps.db.DatabaseHelper +import info.nightscout.androidaps.db.Source +import info.nightscout.androidaps.db.TDD +import info.nightscout.androidaps.db.TempTarget +import info.nightscout.androidaps.interfaces.Constraint +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PumpInterface +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.configBuilder.ConstraintChecker +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin +import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump +import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin +import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin +import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin +import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin +import info.nightscout.androidaps.plugins.treatments.CarbsGenerator +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin +import info.nightscout.androidaps.queue.Callback +import info.nightscout.androidaps.utils.* +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import java.text.DateFormat +import java.text.DecimalFormat +import java.text.SimpleDateFormat +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class ActionStringHandler @Inject constructor( + private val sp: SP, + private val rxBus: RxBusWrapper, + private val resourceHelper: ResourceHelper, + private val constraintChecker: ConstraintChecker, + private val profileFunction: ProfileFunction, + private val mainApp: MainApp, + private val loopPlugin: Lazy, + private val wearPlugin: WearPlugin, + private val treatmentsPlugin: TreatmentsPlugin, + private val configBuilderPlugin: ConfigBuilderPlugin, + private val iobCobCalculatorPlugin: IobCobCalculatorPlugin, + private val danaRPlugin: DanaRPlugin, + private val danaRKoreanPlugin: DanaRKoreanPlugin, + private val danaRv2Plugin: DanaRv2Plugin, + private val danaRSPlugin: DanaRSPlugin +) { + + private val TIMEOUT = 65 * 1000 + private var lastSentTimestamp: Long = 0 + private var lastConfirmActionString: String? = null + private var lastBolusWizard: BolusWizard? = null + @Synchronized + fun handleInitiate(actionString: String) { + if (!sp.getBoolean("wearcontrol", false)) return + lastBolusWizard = null + var rTitle = "CONFIRM" //TODO: i18n + var rMessage = "" + var rAction = "" + // do the parsing and check constraints + val act = actionString.split("\\s+").toTypedArray() + if ("fillpreset" == act[0]) { ///////////////////////////////////// PRIME/FILL + val amount: Double = if ("1" == act[1]) { + sp.getDouble("fill_button1", 0.3) + } else if ("2" == act[1]) { + sp.getDouble("fill_button2", 0.0) + } else if ("3" == act[1]) { + sp.getDouble("fill_button3", 0.0) + } else { + return + } + val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value() + rMessage += resourceHelper.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U" + if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + resourceHelper.gs(R.string.constraintapllied) + rAction += "fill $insulinAfterConstraints" + } else if ("fill" == act[0]) { ////////////////////////////////////////////// PRIME/FILL + val amount = SafeParse.stringToDouble(act[1]) + val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value() + rMessage += resourceHelper.gs(R.string.primefill) + ": " + insulinAfterConstraints + "U" + if (insulinAfterConstraints - amount != 0.0) rMessage += "\n" + resourceHelper.gs(R.string.constraintapllied) + rAction += "fill $insulinAfterConstraints" + } else if ("bolus" == act[0]) { ////////////////////////////////////////////// BOLUS + val insulin = SafeParse.stringToDouble(act[1]) + val carbs = SafeParse.stringToInt(act[2]) + val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(insulin)).value() + val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value() + rMessage += resourceHelper.gs(R.string.bolus) + ": " + insulinAfterConstraints + "U\n" + rMessage += resourceHelper.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g" + if (insulinAfterConstraints - insulin != 0.0 || carbsAfterConstraints - carbs != 0) { + rMessage += "\n" + resourceHelper.gs(R.string.constraintapllied) + } + rAction += "bolus $insulinAfterConstraints $carbsAfterConstraints" + } else if ("temptarget" == act[0]) { ///////////////////////////////////////////////////////// TEMPTARGET + val isMGDL = java.lang.Boolean.parseBoolean(act[1]) + if (profileFunction.getUnits() == Constants.MGDL != isMGDL) { + sendError("Different units used on watch and phone!") + return + } + val duration = SafeParse.stringToInt(act[2]) + if (duration == 0) { + rMessage += "Zero-Temp-Target - cancelling running Temp-Targets?" + rAction = "temptarget true 0 0 0" + } else { + var low = SafeParse.stringToDouble(act[3]) + var high = SafeParse.stringToDouble(act[4]) + if (!isMGDL) { + low *= Constants.MMOLL_TO_MGDL + high *= Constants.MMOLL_TO_MGDL + } + if (low < HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[0] || low > HardLimits.VERY_HARD_LIMIT_TEMP_MIN_BG[1]) { + sendError("Min-BG out of range!") + return + } + if (high < HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[0] || high > HardLimits.VERY_HARD_LIMIT_TEMP_MAX_BG[1]) { + sendError("Max-BG out of range!") + return + } + rMessage += "Temptarget:\nMin: " + act[3] + "\nMax: " + act[4] + "\nDuration: " + act[2] + rAction = actionString + } + } else if ("status" == act[0]) { ////////////////////////////////////////////// STATUS + rTitle = "STATUS" + rAction = "statusmessage" + if ("pump" == act[1]) { + rTitle += " PUMP" + rMessage = pumpStatus + } else if ("loop" == act[1]) { + rTitle += " LOOP" + rMessage = "TARGETS:\n$targetsStatus" + rMessage += "\n\n" + loopStatus + rMessage += "\n\nOAPS RESULT:\n$oAPSResultStatus" + } + } else if ("wizard" == act[0]) { + sendError("Update APP on Watch!") + return + } else if ("wizard2" == act[0]) { ////////////////////////////////////////////// WIZARD + val carbsBeforeConstraints = SafeParse.stringToInt(act[1]) + val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbsBeforeConstraints)).value() + if (carbsAfterConstraints - carbsBeforeConstraints != 0) { + sendError("Carb constraint violation!") + return + } + val useBG = sp.getBoolean(R.string.key_wearwizard_bg, true) + val useTT = sp.getBoolean(R.string.key_wearwizard_tt, false) + val useBolusIOB = sp.getBoolean(R.string.key_wearwizard_bolusiob, true) + val useBasalIOB = sp.getBoolean(R.string.key_wearwizard_basaliob, true) + val useCOB = sp.getBoolean(R.string.key_wearwizard_cob, true) + val useTrend = sp.getBoolean(R.string.key_wearwizard_trend, false) + val percentage = act[2].toInt() + val profile = profileFunction.getProfile() + val profileName = profileFunction.getProfileName() + if (profile == null) { + sendError("No profile found!") + return + } + val bgReading = DatabaseHelper.actualBg() + if (bgReading == null && useBG) { + sendError("No recent BG to base calculation on!") + return + } + val cobInfo = iobCobCalculatorPlugin.getCobInfo(false, "Wizard wear") + if (useCOB && (cobInfo.displayCob == null)) { + sendError("Unknown COB! BG reading missing or recent app restart?") + return + } + val format = DecimalFormat("0.00") + val formatInt = DecimalFormat("0") + val bolusWizard = BolusWizard(profile, profileName, treatmentsPlugin.tempTargetFromHistory, + carbsAfterConstraints, cobInfo.displayCob!!, bgReading!!.valueToUnits(profileFunction.getUnits()), + 0.0, percentage.toDouble(), useBG, useCOB, useBolusIOB, useBasalIOB, false, useTT, useTrend) + if (Math.abs(bolusWizard.insulinAfterConstraints - bolusWizard.calculatedTotalInsulin) >= 0.01) { + sendError("Insulin constraint violation!" + + "\nCannot deliver " + format.format(bolusWizard.calculatedTotalInsulin) + "!") + return + } + if (bolusWizard.calculatedTotalInsulin <= 0 && bolusWizard.carbs <= 0) { + rAction = "info" + rTitle = "INFO" + } else { + rAction = actionString + } + rMessage += "Carbs: " + bolusWizard.carbs + "g" + rMessage += "\nBolus: " + format.format(bolusWizard.calculatedTotalInsulin) + "U" + rMessage += "\n_____________" + rMessage += "\nCalc (IC:" + DecimalFormatter.to1Decimal(bolusWizard.ic) + ", " + "ISF:" + DecimalFormatter.to1Decimal(bolusWizard.sens) + "): " + rMessage += "\nFrom Carbs: " + format.format(bolusWizard.insulinFromCarbs) + "U" + if (useCOB) rMessage += "\nFrom" + formatInt.format(cobInfo.displayCob) + "g COB : " + format.format(bolusWizard.insulinFromCOB) + "U" + if (useBG) rMessage += "\nFrom BG: " + format.format(bolusWizard.insulinFromBG) + "U" + if (useBolusIOB) rMessage += "\nBolus IOB: " + format.format(bolusWizard.insulinFromBolusIOB) + "U" + if (useBasalIOB) rMessage += "\nBasal IOB: " + format.format(bolusWizard.insulinFromBasalsIOB) + "U" + if (useTrend) rMessage += "\nFrom 15' trend: " + format.format(bolusWizard.insulinFromTrend) + "U" + if (percentage != 100) { + rMessage += "\nPercentage: " + format.format(bolusWizard.totalBeforePercentageAdjustment) + "U * " + percentage + "% -> ~" + format.format(bolusWizard.calculatedTotalInsulin) + "U" + } + lastBolusWizard = bolusWizard + } else if ("opencpp" == act[0]) { + val activeProfileSwitch = treatmentsPlugin.getProfileSwitchFromHistory(System.currentTimeMillis()) + if (activeProfileSwitch == null) { + sendError("No active profile switch!") + return + } else { // read CPP values + rTitle = "opencpp" + rMessage = "opencpp" + rAction = "opencpp" + " " + activeProfileSwitch.percentage + " " + activeProfileSwitch.timeshift + } + } else if ("cppset" == act[0]) { + val activeProfileSwitch = treatmentsPlugin.getProfileSwitchFromHistory(System.currentTimeMillis()) + if (activeProfileSwitch == null) { + sendError("No active profile switch!") + return + } else { // read CPP values + rMessage = "CPP:" + "\n\n" + + "Timeshift: " + act[1] + "\n" + + "Percentage: " + act[2] + "%" + rAction = actionString + } + } else if ("tddstats" == act[0]) { + val activePump: Any? = configBuilderPlugin.activePump + if (activePump != null) { // check if DB up to date + val dummies: MutableList = LinkedList() + val historyList = getTDDList(dummies) + if (isOldData(historyList)) { + rTitle = "TDD" + rAction = "statusmessage" + rMessage = "OLD DATA - " + //if pump is not busy: try to fetch data + val pump = configBuilderPlugin.activePump + if (pump!!.isBusy) { + rMessage += resourceHelper.gs(R.string.pumpbusy) + } else { + rMessage += "trying to fetch data from pump." + configBuilderPlugin.commandQueue.loadTDDs(object : Callback() { + override fun run() { + val dummies1: MutableList = LinkedList() + val historyList1 = getTDDList(dummies1) + if (isOldData(historyList1)) { + sendStatusMessage("TDD: Still old data! Cannot load from pump.\n" + generateTDDMessage(historyList1, dummies1)) + } else { + sendStatusMessage(generateTDDMessage(historyList1, dummies1)) + } + } + }) + } + } else { // if up to date: prepare, send (check if CPP is activated -> add CPP stats) + rTitle = "TDD" + rAction = "statusmessage" + rMessage = generateTDDMessage(historyList, dummies) + } + } + } else if ("ecarbs" == act[0]) { ////////////////////////////////////////////// ECARBS + val carbs = SafeParse.stringToInt(act[1]) + val starttime = SafeParse.stringToInt(act[2]) + val duration = SafeParse.stringToInt(act[3]) + val starttimestamp = System.currentTimeMillis() + starttime * 60 * 1000 + val carbsAfterConstraints = constraintChecker.applyCarbsConstraints(Constraint(carbs)).value() + rMessage += resourceHelper.gs(R.string.carbs) + ": " + carbsAfterConstraints + "g" + rMessage += "\n" + resourceHelper.gs(R.string.time) + ": " + DateUtil.timeString(starttimestamp) + rMessage += "\n" + resourceHelper.gs(R.string.duration) + ": " + duration + "h" + if (carbsAfterConstraints - carbs != 0) { + rMessage += "\n" + resourceHelper.gs(R.string.constraintapllied) + } + if (carbsAfterConstraints <= 0) { + sendError("Carbs = 0! No action taken!") + return + } + rAction += "ecarbs $carbsAfterConstraints $starttimestamp $duration" + } else if ("changeRequest" == act[0]) { ////////////////////////////////////////////// CHANGE REQUEST + rTitle = resourceHelper.gs(R.string.openloop_newsuggestion) + rAction = "changeRequest" + val finalLastRun = LoopPlugin.lastRun + rMessage += finalLastRun.constraintsProcessed + wearPlugin.requestChangeConfirmation(rTitle, rMessage, rAction) + lastSentTimestamp = System.currentTimeMillis() + lastConfirmActionString = rAction + return + } else if ("cancelChangeRequest" == act[0]) { ////////////////////////////////////////////// CANCEL CHANGE REQUEST NOTIFICATION + rAction = "cancelChangeRequest" + wearPlugin.requestNotificationCancel(rAction) + return + } else return + // send result + wearPlugin.requestActionConfirmation(rTitle, rMessage, rAction) + lastSentTimestamp = System.currentTimeMillis() + lastConfirmActionString = rAction + } + + private fun generateTDDMessage(historyList: MutableList, dummies: MutableList): String { + val profile = profileFunction.getProfile() ?: return "No profile loaded :(" + if (historyList.isEmpty()) { + return "No history data!" + } + val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault()) + var message = "" + val refTDD = profile.baseBasalSum() * 2 + val pump = configBuilderPlugin.activePump + if (df.format(Date(historyList[0].date)) == df.format(Date())) { + val tdd = historyList[0].getTotal() + historyList.removeAt(0) + message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n" + message += "\n" + } else if (pump != null && pump is DanaRPlugin) { + val tdd = DanaRPump.getInstance().dailyTotalUnits + message += "Today: " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + "\n" + message += "\n" + } + var i = 0 + var weighted03 = 0.0 + var weighted05 = 0.0 + var weighted07 = 0.0 + Collections.reverse(historyList) + for (record in historyList) { + val tdd = record.getTotal() + if (i == 0) { + weighted03 = tdd + weighted05 = tdd + weighted07 = tdd + } else { + weighted07 = weighted07 * 0.3 + tdd * 0.7 + weighted05 = weighted05 * 0.5 + tdd * 0.5 + weighted03 = weighted03 * 0.7 + tdd * 0.3 + } + i++ + } + message += "weighted:\n" + message += "0.3: " + DecimalFormatter.to2Decimal(weighted03) + "U " + (DecimalFormatter.to0Decimal(100 * weighted03 / refTDD) + "%") + "\n" + message += "0.5: " + DecimalFormatter.to2Decimal(weighted05) + "U " + (DecimalFormatter.to0Decimal(100 * weighted05 / refTDD) + "%") + "\n" + message += "0.7: " + DecimalFormatter.to2Decimal(weighted07) + "U " + (DecimalFormatter.to0Decimal(100 * weighted07 / refTDD) + "%") + "\n" + message += "\n" + Collections.reverse(historyList) + //add TDDs: + for (record in historyList) { + val tdd = record.getTotal() + message += df.format(Date(record.date)) + " " + DecimalFormatter.to2Decimal(tdd) + "U " + (DecimalFormatter.to0Decimal(100 * tdd / refTDD) + "%") + (if (dummies.contains(record)) "x" else "") + "\n" + } + return message + } + + private fun isOldData(historyList: List): Boolean { + val activePump: Any? = configBuilderPlugin.activePump + val insight: PumpInterface = LocalInsightPlugin.getPlugin() + val startsYesterday = activePump === danaRPlugin || activePump === danaRSPlugin || activePump === danaRv2Plugin || activePump === danaRKoreanPlugin || activePump === insight + val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault()) + return historyList.size < 3 || df.format(Date(historyList[0].date)) != df.format(Date(System.currentTimeMillis() - if (startsYesterday) 1000 * 60 * 60 * 24 else 0)) + } + + private fun getTDDList(returnDummies: MutableList): MutableList { + var historyList = MainApp.getDbHelper().tdDs + historyList = historyList.subList(0, Math.min(10, historyList.size)) + //fill single gaps - only needed for Dana*R data + val dummies: MutableList = returnDummies + val df: DateFormat = SimpleDateFormat("dd.MM.", Locale.getDefault()) + for (i in 0 until historyList.size - 1) { + val elem1 = historyList[i] + val elem2 = historyList[i + 1] + if (df.format(Date(elem1!!.date)) != df.format(Date(elem2!!.date + 25 * 60 * 60 * 1000))) { + val dummy = TDD() + dummy.date = elem1.date - 24 * 60 * 60 * 1000 + dummy.basal = elem1.basal / 2 + dummy.bolus = elem1.bolus / 2 + dummies.add(dummy) + elem1.basal /= 2.0 + elem1.bolus /= 2.0 + } + } + historyList.addAll(dummies) + Collections.sort(historyList) { lhs, rhs -> (rhs.date - lhs.date).toInt() } + return historyList + } + + private val pumpStatus: String + get() = configBuilderPlugin.activePump?.shortStatus(false) ?: "" + + // decide if enabled/disabled closed/open; what Plugin as APS? + private val loopStatus: String + get() { + var ret = "" + // decide if enabled/disabled closed/open; what Plugin as APS? + if (loopPlugin.get().isEnabled(loopPlugin.get().getType())) { + ret += if (constraintChecker.isClosedLoopAllowed().value()) { + "CLOSED LOOP\n" + } else { + "OPEN LOOP\n" + } + val aps = configBuilderPlugin.activeAPS + ret += "APS: " + if (aps == null) "NO APS SELECTED!" else (aps as PluginBase).name + if (LoopPlugin.lastRun != null) { + if (LoopPlugin.lastRun.lastAPSRun != null) ret += "\nLast Run: " + DateUtil.timeString(LoopPlugin.lastRun.lastAPSRun) + if (LoopPlugin.lastRun.lastEnact != null) ret += "\nLast Enact: " + DateUtil.timeString(LoopPlugin.lastRun.lastEnact) + } + } else { + ret += "LOOP DISABLED\n" + } + return ret + } + + //Check for Temp-Target: + private val targetsStatus: String + get() { + var ret = "" + if (!Config.APS) { + return "Targets only apply in APS mode!" + } + val profile = profileFunction.getProfile() ?: return "No profile set :(" + //Check for Temp-Target: + val tempTarget = treatmentsPlugin.tempTargetFromHistory + if (tempTarget != null) { + ret += "Temp Target: " + Profile.toTargetRangeString(tempTarget.low, tempTarget.low, Constants.MGDL, profileFunction.getUnits()) + ret += "\nuntil: " + DateUtil.timeString(tempTarget.originalEnd()) + ret += "\n\n" + } + ret += "DEFAULT RANGE: " + ret += Profile.fromMgdlToUnits(profile.targetLowMgdl, profileFunction.getUnits()).toString() + " - " + Profile.fromMgdlToUnits(profile.targetHighMgdl, profileFunction.getUnits()) + ret += " target: " + Profile.fromMgdlToUnits(profile.targetMgdl, profileFunction.getUnits()) + return ret + } + + private val oAPSResultStatus: String + get() { + var ret = "" + if (!Config.APS) { + return "Only apply in APS mode!" + } + val usedAPS = configBuilderPlugin.activeAPS ?: return "No active APS :(!" + val result = usedAPS.lastAPSResult ?: return "Last result not available!" + ret += if (!result.isChangeRequested) { + resourceHelper.gs(R.string.nochangerequested) + "\n" + } else if (result.rate == 0.0 && result.duration == 0) { + resourceHelper.gs(R.string.canceltemp) + "\n" + } else { + resourceHelper.gs(R.string.rate) + ": " + DecimalFormatter.to2Decimal(result.rate) + " U/h " + + "(" + DecimalFormatter.to2Decimal(result.rate / configBuilderPlugin.activePump!!.baseBasalRate * 100) + "%)\n" + + resourceHelper.gs(R.string.duration) + ": " + DecimalFormatter.to0Decimal(result.duration.toDouble()) + " min\n" + } + ret += "\n" + resourceHelper.gs(R.string.reason) + ": " + result.reason + return ret + } + + @Synchronized + fun handleConfirmation(actionString: String) { + if (!sp.getBoolean("wearcontrol", false)) return + //Guard from old or duplicate confirmations + if (lastConfirmActionString == null) return + if (lastConfirmActionString != actionString) return + if (System.currentTimeMillis() - lastSentTimestamp > TIMEOUT) return + lastConfirmActionString = null + // do the parsing, check constraints and enact! + val act = actionString.split("\\s+").toTypedArray() + if ("fill" == act[0]) { + val amount = SafeParse.stringToDouble(act[1]) + val insulinAfterConstraints = constraintChecker.applyBolusConstraints(Constraint(amount)).value() + if (amount - insulinAfterConstraints != 0.0) { + ToastUtils.showToastInUiThread(mainApp, "aborting: previously applied constraint changed") + sendError("aborting: previously applied constraint changed") + return + } + doFillBolus(amount) + } else if ("temptarget" == act[0]) { + val duration = SafeParse.stringToInt(act[2]) + var low = SafeParse.stringToDouble(act[3]) + var high = SafeParse.stringToDouble(act[4]) + val isMGDL = java.lang.Boolean.parseBoolean(act[1]) + if (!isMGDL) { + low *= Constants.MMOLL_TO_MGDL + high *= Constants.MMOLL_TO_MGDL + } + generateTempTarget(duration, low, high) + } else if ("wizard2" == act[0]) { + if (lastBolusWizard != null) { //use last calculation as confirmed string matches + doBolus(lastBolusWizard!!.calculatedTotalInsulin, lastBolusWizard!!.carbs) + lastBolusWizard = null + } + } else if ("bolus" == act[0]) { + val insulin = SafeParse.stringToDouble(act[1]) + val carbs = SafeParse.stringToInt(act[2]) + doBolus(insulin, carbs) + } else if ("cppset" == act[0]) { + val timeshift = SafeParse.stringToInt(act[1]) + val percentage = SafeParse.stringToInt(act[2]) + setCPP(timeshift, percentage) + } else if ("ecarbs" == act[0]) { + val carbs = SafeParse.stringToInt(act[1]) + val starttime = SafeParse.stringToLong(act[2]) + val duration = SafeParse.stringToInt(act[3]) + doECarbs(carbs, starttime, duration) + } else if ("dismissoverviewnotification" == act[0]) { + rxBus.send(EventDismissNotification(SafeParse.stringToInt(act[1]))) + } else if ("changeRequest" == act[0]) { + loopPlugin.get().acceptChangeRequest() + val notificationManager = mainApp.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + notificationManager.cancel(Constants.notificationID) + } + lastBolusWizard = null + } + + private fun doECarbs(carbs: Int, time: Long, duration: Int) { + if (carbs > 0) { + if (duration == 0) { + CarbsGenerator.createCarb(carbs, time, CareportalEvent.CARBCORRECTION, "watch") + } else { + CarbsGenerator.generateCarbs(carbs, time, duration, "watch eCarbs") + } + } + } + + private fun setCPP(timeshift: Int, percentage: Int) { + var msg = "" + //check for validity + if (percentage < Constants.CPP_MIN_PERCENTAGE || percentage > Constants.CPP_MAX_PERCENTAGE) { + msg += String.format(resourceHelper.gs(R.string.valueoutofrange), "Profile-Percentage") + "\n" + } + if (timeshift < 0 || timeshift > 23) { + msg += String.format(resourceHelper.gs(R.string.valueoutofrange), "Profile-Timeshift") + "\n" + } + val profile = profileFunction.getProfile() + if (profile == null) { + msg += resourceHelper.gs(R.string.notloadedplugins) + "\n" + } + if ("" != msg) { + msg += resourceHelper.gs(R.string.valuesnotstored) + val rTitle = "STATUS" + val rAction = "statusmessage" + wearPlugin.requestActionConfirmation(rTitle, msg, rAction) + lastSentTimestamp = System.currentTimeMillis() + lastConfirmActionString = rAction + return + } + //send profile to pumpe + treatmentsPlugin.doProfileSwitch(0, percentage, timeshift) + } + + private fun generateTempTarget(duration: Int, low: Double, high: Double) { + val tempTarget = TempTarget() + .date(System.currentTimeMillis()) + .duration(duration) + .reason("WearPlugin") + .source(Source.USER) + if (tempTarget.durationInMinutes != 0) { + tempTarget.low(low).high(high) + } else { + tempTarget.low(0.0).high(0.0) + } + treatmentsPlugin.addToHistoryTempTarget(tempTarget) + } + + private fun doFillBolus(amount: Double) { + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.insulin = amount + detailedBolusInfo.isValid = false + detailedBolusInfo.source = Source.USER + configBuilderPlugin.commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + if (!result.success) { + sendError(resourceHelper.gs(R.string.treatmentdeliveryerror) + + "\n" + + result.comment) + } + } + }) + } + + private fun doBolus(amount: Double, carbs: Int) { + val detailedBolusInfo = DetailedBolusInfo() + detailedBolusInfo.insulin = amount + detailedBolusInfo.carbs = carbs.toDouble() + detailedBolusInfo.source = Source.USER + if (detailedBolusInfo.insulin > 0 || configBuilderPlugin.activePump!!.pumpDescription.storesCarbInfo) { + configBuilderPlugin.commandQueue.bolus(detailedBolusInfo, object : Callback() { + override fun run() { + if (!result.success) { + sendError(resourceHelper.gs(R.string.treatmentdeliveryerror) + + "\n" + + result.comment) + } + } + }) + } else { + treatmentsPlugin.addToHistoryTreatment(detailedBolusInfo, false) + } + } + + @Synchronized private fun sendError(errormessage: String) { + wearPlugin.requestActionConfirmation("ERROR", errormessage, "error") + lastSentTimestamp = System.currentTimeMillis() + lastConfirmActionString = null + lastBolusWizard = null + } + + @Synchronized + private fun sendStatusMessage(message: String) { + wearPlugin.requestActionConfirmation("TDD", message, "statusmessage") + lastSentTimestamp = System.currentTimeMillis() + lastConfirmActionString = null + lastBolusWizard = null + } /* + public synchronized static void expectNotificationAction(String message, int id) { + String actionstring = "dismissoverviewnotification " + id; + WearPlugin.getPlugin().requestActionConfirmation("DISMISS", message, actionstring); + lastSentTimestamp = System.currentTimeMillis(); + lastConfirmActionString = actionstring; + lastBolusWizard = null; + } +*/ +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java deleted file mode 100644 index 9eb157de24..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.java +++ /dev/null @@ -1,39 +0,0 @@ -package info.nightscout.androidaps.plugins.general.wear; - -import android.os.Bundle; -import androidx.fragment.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import info.nightscout.androidaps.R; - -/** - * Created by adrian on 17/11/16. - */ - -public class WearFragment extends Fragment { - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.wear_fragment, container, false); - - view.findViewById(R.id.wear_resend).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - WearPlugin.getPlugin().resendDataToWatch(); - } - }); - - view.findViewById(R.id.wear_opensettings).setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - WearPlugin.getPlugin().openSettings(); - } - }); - - return view; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.kt new file mode 100644 index 0000000000..105e2589c0 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearFragment.kt @@ -0,0 +1,25 @@ +package info.nightscout.androidaps.plugins.general.wear + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import dagger.android.support.DaggerFragment +import info.nightscout.androidaps.R +import kotlinx.android.synthetic.main.wear_fragment.* +import javax.inject.Inject + +class WearFragment : DaggerFragment() { + @Inject lateinit var wearPlugin: WearPlugin + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.wear_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + wear_resend.setOnClickListener { wearPlugin.resendDataToWatch() } + wear_opensettings.setOnClickListener { wearPlugin.openSettings() } + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.java deleted file mode 100644 index c509794d88..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.java +++ /dev/null @@ -1,244 +0,0 @@ -package info.nightscout.androidaps.plugins.general.wear; - -import android.content.Context; -import android.content.Intent; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.events.EventBolusRequested; -import info.nightscout.androidaps.events.EventExtendedBolusChange; -import info.nightscout.androidaps.events.EventNewBasalProfile; -import info.nightscout.androidaps.events.EventPreferenceChange; -import info.nightscout.androidaps.events.EventRefreshOverview; -import info.nightscout.androidaps.events.EventTempBasalChange; -import info.nightscout.androidaps.events.EventTreatmentChange; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; -import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui; -import info.nightscout.androidaps.plugins.bus.RxBus; -import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning; -import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; -import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService; -import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; -import info.nightscout.androidaps.utils.FabricPrivacy; -import info.nightscout.androidaps.utils.SP; -import io.reactivex.disposables.CompositeDisposable; -import io.reactivex.schedulers.Schedulers; - -/** - * Created by adrian on 17/11/16. - */ - -public class WearPlugin extends PluginBase { - - private static WatchUpdaterService watchUS; - private final Context ctx; - - private static WearPlugin wearPlugin; - private static String TAG = "WearPlugin"; - - private CompositeDisposable disposable = new CompositeDisposable(); - - @Deprecated - public static WearPlugin getPlugin() { - return wearPlugin; - } - - public static WearPlugin initPlugin(Context ctx) { - - if (wearPlugin == null) { - wearPlugin = new WearPlugin(ctx); - } - - return wearPlugin; - } - - WearPlugin(Context ctx) { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(WearFragment.class.getName()) - .pluginName(R.string.wear) - .shortName(R.string.wear_shortname) - .preferencesId(R.xml.pref_wear) - .description(R.string.description_wear) - ); - this.ctx = ctx; - } - - @Override - protected void onStart() { - if (watchUS != null) { - watchUS.setSettings(); - } - super.onStart(); - - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventOpenAPSUpdateGui.class) - .observeOn(Schedulers.io()) - .subscribe(event -> sendDataToWatch(true, true, false), - FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventExtendedBolusChange.class) - .observeOn(Schedulers.io()) - .subscribe(event -> sendDataToWatch(true, true, false), - FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventTempBasalChange.class) - .observeOn(Schedulers.io()) - .subscribe(event -> sendDataToWatch(true, true, false), - FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventTreatmentChange.class) - .observeOn(Schedulers.io()) - .subscribe(event -> sendDataToWatch(true, true, false), - FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventNewBasalProfile.class) - .observeOn(Schedulers.io()) - .subscribe(event -> sendDataToWatch(false, true, false), - FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventAutosensCalculationFinished.class) - .observeOn(Schedulers.io()) - .subscribe(event -> sendDataToWatch(true, true, true), - FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventPreferenceChange.class) - .observeOn(Schedulers.io()) - .subscribe(event -> { - // possibly new high or low mark - resendDataToWatch(); - // status may be formated differently - sendDataToWatch(true, false, false); - }, FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventRefreshOverview.class) - .observeOn(Schedulers.io()) - .subscribe(event -> { - if (WatchUpdaterService.shouldReportLoopStatus(LoopPlugin.getPlugin().isEnabled(PluginType.LOOP))) - sendDataToWatch(true, false, false); - }, FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventBolusRequested.class) - .observeOn(Schedulers.io()) - .subscribe(event -> { - String status = String.format(MainApp.gs(R.string.bolusrequested), event.getAmount()); - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); - intent.putExtra("progresspercent", 0); - intent.putExtra("progressstatus", status); - ctx.startService(intent); - }, FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventDismissBolusProgressIfRunning.class) - .observeOn(Schedulers.io()) - .subscribe(event -> { - if (event.getResult() == null) return; - String status; - if (event.getResult().success) { - status = MainApp.gs(R.string.success); - } else { - status = MainApp.gs(R.string.nosuccess); - } - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); - intent.putExtra("progresspercent", 100); - intent.putExtra("progressstatus", status); - ctx.startService(intent); - }, FabricPrivacy::logException - )); - disposable.add(RxBus.Companion.getINSTANCE() - .toObservable(EventOverviewBolusProgress.class) - .observeOn(Schedulers.io()) - .subscribe(event -> { - if (!event.isSMB() || SP.getBoolean("wear_notifySMB", true)) { - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS); - intent.putExtra("progresspercent", event.getPercent()); - intent.putExtra("progressstatus", event.getStatus()); - ctx.startService(intent); - } - }, FabricPrivacy::logException - )); - } - - - @Override - protected void onStop() { - disposable.clear(); - super.onStop(); - } - - private void sendDataToWatch(boolean status, boolean basals, boolean bgValue) { - - //Log.d(TAG, "WR: WearPlugin:sendDataToWatch (status=" + status + ",basals=" + basals + ",bgValue=" + bgValue + ")"); - - if (isEnabled(getType())) { // only start service when this plugin is enabled - - if (bgValue) { - ctx.startService(new Intent(ctx, WatchUpdaterService.class)); - } - - if (basals) { - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_BASALS)); - } - - if (status) { - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_STATUS)); - } - } - } - - void resendDataToWatch() { - //Log.d(TAG, "WR: WearPlugin:resendDataToWatch"); - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_RESEND)); - } - - void openSettings() { - //Log.d(TAG, "WR: WearPlugin:openSettings"); - ctx.startService(new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS)); - } - - void requestNotificationCancel(String actionstring) { - //Log.d(TAG, "WR: WearPlugin:requestNotificationCancel"); - - Intent intent = new Intent(ctx, WatchUpdaterService.class) - .setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION); - intent.putExtra("actionstring", actionstring); - ctx.startService(intent); - } - - public void requestActionConfirmation(String title, String message, String actionstring) { - - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST); - intent.putExtra("title", title); - intent.putExtra("message", message); - intent.putExtra("actionstring", actionstring); - ctx.startService(intent); - } - - public void requestChangeConfirmation(String title, String message, String actionstring) { - - Intent intent = new Intent(ctx, WatchUpdaterService.class).setAction(WatchUpdaterService.ACTION_SEND_CHANGECONFIRMATIONREQUEST); - intent.putExtra("title", title); - intent.putExtra("message", message); - intent.putExtra("actionstring", actionstring); - ctx.startService(intent); - } - - public static void registerWatchUpdaterService(WatchUpdaterService wus) { - watchUS = wus; - } - - public static void unRegisterWatchUpdaterService() { - watchUS = null; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt new file mode 100644 index 0000000000..342b023343 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/WearPlugin.kt @@ -0,0 +1,173 @@ +package info.nightscout.androidaps.plugins.general.wear + +import android.content.Intent +import dagger.Lazy +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.events.* +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin +import info.nightscout.androidaps.plugins.aps.openAPSMA.events.EventOpenAPSUpdateGui +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.general.overview.events.EventDismissBolusProgressIfRunning +import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress +import info.nightscout.androidaps.plugins.general.wear.wearintegration.WatchUpdaterService +import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import io.reactivex.schedulers.Schedulers +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class WearPlugin internal @Inject constructor( + private val rxBus: RxBusWrapper, + private val resourceHelper: ResourceHelper, + private val sp: SP, + private val mainApp: MainApp, + private val loopPlugin: Lazy +) : PluginBase(PluginDescription() + .mainType(PluginType.GENERAL) + .fragmentClass(WearFragment::class.java.name) + .pluginName(R.string.wear) + .shortName(R.string.wear_shortname) + .preferencesId(R.xml.pref_wear) + .description(R.string.description_wear) +) { + + private val disposable = CompositeDisposable() + override fun onStart() { + super.onStart() + disposable.add(rxBus + .toObservable(EventOpenAPSUpdateGui::class.java) + .observeOn(Schedulers.io()) + .subscribe({ sendDataToWatch(true, true, false) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventExtendedBolusChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ sendDataToWatch(true, true, false) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventTempBasalChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventTempBasalChange? -> sendDataToWatch(true, true, false) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventTreatmentChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ sendDataToWatch(true, true, false) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventNewBasalProfile::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventNewBasalProfile? -> sendDataToWatch(false, true, false) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventAutosensCalculationFinished::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventAutosensCalculationFinished? -> sendDataToWatch(true, true, true) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventPreferenceChange::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventPreferenceChange? -> + // possibly new high or low mark + resendDataToWatch() + // status may be formated differently + sendDataToWatch(true, false, false) + }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventRefreshOverview::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventRefreshOverview? -> if (WatchUpdaterService.shouldReportLoopStatus(loopPlugin.get().isEnabled(PluginType.LOOP))) sendDataToWatch(true, false, false) }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventBolusRequested::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventBolusRequested -> + val status = String.format(resourceHelper.gs(R.string.bolusrequested), event.amount) + val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) + intent.putExtra("progresspercent", 0) + intent.putExtra("progressstatus", status) + mainApp.startService(intent) + }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventDismissBolusProgressIfRunning::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventDismissBolusProgressIfRunning -> + if (event.result == null) return@subscribe + val status: String = if (event.result.success) { + resourceHelper.gs(R.string.success) + } else { + resourceHelper.gs(R.string.nosuccess) + } + val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) + intent.putExtra("progresspercent", 100) + intent.putExtra("progressstatus", status) + mainApp.startService(intent) + }) { FabricPrivacy.logException(it) }) + disposable.add(rxBus + .toObservable(EventOverviewBolusProgress::class.java) + .observeOn(Schedulers.io()) + .subscribe({ event: EventOverviewBolusProgress -> + if (!event.isSMB() || sp.getBoolean("wear_notifySMB", true)) { + val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BOLUSPROGRESS) + intent.putExtra("progresspercent", event.percent) + intent.putExtra("progressstatus", event.status) + mainApp.startService(intent) + } + }) { FabricPrivacy.logException(it) }) + } + + override fun onStop() { + disposable.clear() + super.onStop() + } + + private fun sendDataToWatch(status: Boolean, basals: Boolean, bgValue: Boolean) { + //Log.d(TAG, "WR: WearPlugin:sendDataToWatch (status=" + status + ",basals=" + basals + ",bgValue=" + bgValue + ")"); + if (isEnabled(getType())) { + // only start service when this plugin is enabled + if (bgValue) { + mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java)) + } + if (basals) { + mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_BASALS)) + } + if (status) { + mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_STATUS)) + } + } + } + + fun resendDataToWatch() { + //Log.d(TAG, "WR: WearPlugin:resendDataToWatch"); + mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_RESEND)) + } + + fun openSettings() { + //Log.d(TAG, "WR: WearPlugin:openSettings"); + mainApp.startService(Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_OPEN_SETTINGS)) + } + + fun requestNotificationCancel(actionstring: String?) { //Log.d(TAG, "WR: WearPlugin:requestNotificationCancel"); + val intent = Intent(mainApp, WatchUpdaterService::class.java) + .setAction(WatchUpdaterService.ACTION_CANCEL_NOTIFICATION) + intent.putExtra("actionstring", actionstring) + mainApp.startService(intent) + } + + fun requestActionConfirmation(title: String, message: String, actionString: String) { + val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_ACTIONCONFIRMATIONREQUEST) + intent.putExtra("title", title) + intent.putExtra("message", message) + intent.putExtra("actionstring", actionString) + mainApp.startService(intent) + } + + fun requestChangeConfirmation(title: String, message: String, actionString: String) { + val intent = Intent(mainApp, WatchUpdaterService::class.java).setAction(WatchUpdaterService.ACTION_SEND_CHANGECONFIRMATIONREQUEST) + intent.putExtra("title", title) + intent.putExtra("message", message) + intent.putExtra("actionstring", actionString) + mainApp.startService(intent) + } +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java index 39676f17b4..c02a0a953e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java @@ -3,13 +3,11 @@ package info.nightscout.androidaps.plugins.general.wear.wearintegration; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.SharedPreferences; import android.os.AsyncTask; import android.os.BatteryManager; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; -import android.preference.PreferenceManager; import android.util.Log; import androidx.annotation.NonNull; @@ -26,13 +24,13 @@ import com.google.android.gms.wearable.PutDataRequest; import com.google.android.gms.wearable.Wearable; import com.google.android.gms.wearable.WearableListenerService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.ArrayList; import java.util.List; import java.util.Set; +import javax.inject.Inject; + +import dagger.android.AndroidInjection; import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; @@ -43,9 +41,11 @@ import info.nightscout.androidaps.db.BgReading; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.TreatmentsInterface; +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; import info.nightscout.androidaps.plugins.general.overview.OverviewPlugin; @@ -56,10 +56,21 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorP import info.nightscout.androidaps.plugins.treatments.Treatment; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DecimalFormatter; -import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.ToastUtils; +import info.nightscout.androidaps.utils.resources.ResourceHelper; +import info.nightscout.androidaps.utils.sharedPreferences.SP; public class WatchUpdaterService extends WearableListenerService implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { + @Inject public AAPSLogger aapsLogger; + @Inject public WearPlugin wearPlugin; + @Inject public ResourceHelper resourceHelper; + @Inject public SP sp; + @Inject public ConfigBuilderPlugin configBuilderPlugin; + @Inject public ProfileFunction profileFunction; + @Inject public LoopPlugin loopPlugin; + @Inject public IobCobCalculatorPlugin iobCobCalculatorPlugin; + @Inject public TreatmentsPlugin treatmentsPlugin; + @Inject public ActionStringHandler actionStringHandler; public static final String ACTION_RESEND = WatchUpdaterService.class.getName().concat(".Resend"); public static final String ACTION_OPEN_SETTINGS = WatchUpdaterService.class.getName().concat(".OpenSettings"); @@ -87,11 +98,8 @@ public class WatchUpdaterService extends WearableListenerService implements Goog public static final String ACTION_CANCELNOTIFICATION_REQUEST_PATH = "/nightscout_watch_cancelnotificationrequest"; - boolean wear_integration = false; private static boolean lastLoopStatus; - private static Logger log = LoggerFactory.getLogger(WatchUpdaterService.class); - private Handler handler; // Phone @@ -100,16 +108,12 @@ public class WatchUpdaterService extends WearableListenerService implements Goog // Wear private static final String CAPABILITY_WEAR_APP = "wear_app_sync_bgs"; private static final String MESSAGE_PATH_WEAR = "/wear_message_path"; - private String mWearNodeId = null; - private String localnode = null; - private String logPrefix = ""; // "WR: " @Override public void onCreate() { - listenForChangeInSettings(); - setSettings(); - if (wear_integration) { + AndroidInjection.inject(this); + if (wearIntegration()) { googleApiConnect(); } if (handler == null) { @@ -119,19 +123,10 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } } - public void listenForChangeInSettings() { - WearPlugin.registerWatchUpdaterService(this); + private boolean wearIntegration() { + return wearPlugin.isEnabled(PluginType.GENERAL); } - public void setSettings() { - wear_integration = WearPlugin.getPlugin().isEnabled(PluginType.GENERAL); - // Log.d(TAG, "WR: wear_integration=" + wear_integration); - if (wear_integration) { - googleApiConnect(); - } - } - - private void googleApiConnect() { if (googleApiClient != null && (googleApiClient.isConnected() || googleApiClient.isConnecting())) { googleApiClient.disconnect(); @@ -140,7 +135,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog .addOnConnectionFailedListener(this).addApi(Wearable.API).build(); Wearable.MessageApi.addListener(googleApiClient, this); if (googleApiClient.isConnected()) { - log.debug(logPrefix + "API client is connected"); + aapsLogger.debug(LTag.WEAR, "API client is connected"); } else { // Log.d("WatchUpdater", logPrefix + "API client is not connected and is trying to connect"); googleApiClient.connect(); @@ -153,7 +148,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog // Log.d(TAG, logPrefix + "onStartCommand: " + action); - if (wear_integration) { + if (wearIntegration()) { handler.post(() -> { if (googleApiClient.isConnected()) { if (ACTION_RESEND.equals(action)) { @@ -193,9 +188,9 @@ public class WatchUpdaterService extends WearableListenerService implements Goog private void updateWearSyncBgsCapability(CapabilityInfo capabilityInfo) { - Log.d("WatchUpdaterService", logPrefix + "CabilityInfo: " + capabilityInfo); + Log.d("WatchUpdaterService", "CabilityInfo: " + capabilityInfo); Set connectedNodes = capabilityInfo.getNodes(); - mWearNodeId = pickBestNodeId(connectedNodes); + String mWearNodeId = pickBestNodeId(connectedNodes); } @@ -240,7 +235,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog String id = peer.getId(); String name = peer.getDisplayName(); // Log.d(TAG, logPrefix + "onPeerDisconnected peer name & ID: " + name + "|" + id); - SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(getApplicationContext()); } @@ -249,7 +243,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog // Log.d(TAG, logPrefix + "onMessageRecieved: " + event); - if (wear_integration) { + if (wearIntegration()) { if (event != null && event.getPath().equals(WEARABLE_RESEND_PATH)) { resendData(); } @@ -260,20 +254,20 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (event != null && event.getPath().equals(WEARABLE_INITIATE_ACTIONSTRING_PATH)) { String actionstring = new String(event.getData()); - log.debug("Wear: " + actionstring); - ActionStringHandler.handleInitiate(actionstring); + aapsLogger.debug(LTag.WEAR, "Wear: " + actionstring); + actionStringHandler.handleInitiate(actionstring); } if (event != null && event.getPath().equals(WEARABLE_CONFIRM_ACTIONSTRING_PATH)) { String actionstring = new String(event.getData()); - log.debug("Wear Confirm: " + actionstring); - ActionStringHandler.handleConfirmation(actionstring); + aapsLogger.debug(LTag.WEAR, "Wear Confirm: " + actionstring); + actionStringHandler.handleConfirmation(actionstring); } } } private void cancelBolus() { - ConfigBuilderPlugin.getPlugin().getActivePump().stopBolusDelivering(); + configBuilderPlugin.getActivePump().stopBolusDelivering(); } private void sendData() { @@ -286,11 +280,11 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (googleApiClient != null && !googleApiClient.isConnected() && !googleApiClient.isConnecting()) { googleApiConnect(); } - if (wear_integration) { + if (wearIntegration()) { final DataMap dataMap = dataMapSingleBG(lastBG, glucoseStatus); if (dataMap == null) { - ToastUtils.showToastInUiThread(this, MainApp.gs(R.string.noprofile)); + ToastUtils.showToastInUiThread(this, resourceHelper.gs(R.string.noprofile)); return; } @@ -356,7 +350,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog deltastring += "-"; } - boolean detailed = SP.getBoolean("wear_detailed_delta", false); + boolean detailed = sp.getBoolean(R.string.key_wear_detailed_delta, false); if (units.equals(Constants.MGDL)) { if (detailed) { deltastring += DecimalFormatter.to1Decimal(Math.abs(deltaMGDL)); @@ -407,7 +401,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (!graph_bgs.isEmpty()) { DataMap entries = dataMapSingleBG(last_bg, glucoseStatus); if (entries == null) { - ToastUtils.showToastInUiThread(this, MainApp.gs(R.string.noprofile)); + ToastUtils.showToastInUiThread(this, resourceHelper.gs(R.string.noprofile)); return; } final ArrayList dataMaps = new ArrayList<>(graph_bgs.size()); @@ -440,7 +434,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog ArrayList predictions = new ArrayList<>(); - Profile profile = ProfileFunctions.getInstance().getProfile(); + Profile profile = profileFunction.getProfile(); if (profile == null) { return; @@ -452,8 +446,8 @@ public class WatchUpdaterService extends WearableListenerService implements Goog double beginBasalValue = profile.getBasal(beginBasalSegmentTime); double endBasalValue = beginBasalValue; - TemporaryBasal tb1 = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(runningTime); - TemporaryBasal tb2 = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(runningTime); + TemporaryBasal tb1 = treatmentsPlugin.getTempBasalFromHistory(runningTime); + TemporaryBasal tb2 = treatmentsPlugin.getTempBasalFromHistory(runningTime); double tb_before = beginBasalValue; double tb_amount = beginBasalValue; long tb_start = runningTime; @@ -469,7 +463,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog for (; runningTime < now; runningTime += 5 * 60 * 1000) { - Profile profileTB = ProfileFunctions.getInstance().getProfile(runningTime); + Profile profileTB = profileFunction.getProfile(runningTime); if (profileTB == null) return; //basal rate @@ -484,7 +478,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } //temps - tb2 = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(runningTime); + tb2 = treatmentsPlugin.getTempBasalFromHistory(runningTime); if (tb1 == null && tb2 == null) { //no temp stays no temp @@ -517,13 +511,13 @@ public class WatchUpdaterService extends WearableListenerService implements Goog basals.add(basalMap(beginBasalSegmentTime, runningTime, beginBasalValue)); } if (tb1 != null) { - tb2 = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); //use "now" to express current situation + tb2 = treatmentsPlugin.getTempBasalFromHistory(now); //use "now" to express current situation if (tb2 == null) { //express the cancelled temp by painting it down one minute early temps.add(tempDatamap(tb_start, tb_before, now - 1 * 60 * 1000, endBasalValue, tb_amount)); } else { //express currently running temp by painting it a bit into the future - Profile profileNow = ProfileFunctions.getInstance().getProfile(now); + Profile profileNow = profileFunction.getProfile(now); double currentAmount = tb2.tempBasalConvertedToAbsolute(now, profileNow); if (currentAmount != tb_amount) { temps.add(tempDatamap(tb_start, tb_before, now, tb_amount, tb_amount)); @@ -536,13 +530,13 @@ public class WatchUpdaterService extends WearableListenerService implements Goog tb2 = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(now); //use "now" to express current situation if (tb2 != null) { //onset at the end - Profile profileTB = ProfileFunctions.getInstance().getProfile(runningTime); + Profile profileTB = profileFunction.getProfile(runningTime); double currentAmount = tb2.tempBasalConvertedToAbsolute(runningTime, profileTB); temps.add(tempDatamap(now - 1 * 60 * 1000, endBasalValue, runningTime + 5 * 60 * 1000, currentAmount, currentAmount)); } } - List treatments = TreatmentsPlugin.getPlugin().getTreatmentsFromHistory(); + List treatments = treatmentsPlugin.getTreatmentsFromHistory(); for (Treatment treatment : treatments) { if (treatment.date > startTimeWindow) { boluses.add(treatmentMap(treatment.date, treatment.insulin, treatment.carbs, treatment.isSMB, treatment.isValid)); @@ -550,8 +544,8 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } - final LoopPlugin.LastRun finalLastRun = LoopPlugin.lastRun; - if (SP.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.request.hasPredictions && finalLastRun.constraintsProcessed != null) { + final LoopPlugin.LastRun finalLastRun = loopPlugin.lastRun; + if (sp.getBoolean("wear_predictions", true) && finalLastRun != null && finalLastRun.request.hasPredictions && finalLastRun.constraintsProcessed != null) { List predArray = finalLastRun.constraintsProcessed.getPredictions(); if (!predArray.isEmpty()) { @@ -649,7 +643,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog dataMapRequest.getDataMap().putString("message", message); dataMapRequest.getDataMap().putString("actionstring", actionstring); - log.debug("Requesting confirmation from wear: " + actionstring); + aapsLogger.debug(LTag.WEAR, "Requesting confirmation from wear: " + actionstring); PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest(); debugData("sendActionConfirmationRequest", putDataRequest); @@ -669,7 +663,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog dataMapRequest.getDataMap().putString("message", message); dataMapRequest.getDataMap().putString("actionstring", actionstring); - log.debug("Requesting confirmation from wear: " + actionstring); + aapsLogger.debug(LTag.WEAR, "Requesting confirmation from wear: " + actionstring); PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest(); debugData("sendChangeConfirmationRequest", putDataRequest); @@ -687,7 +681,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog dataMapRequest.getDataMap().putString("cancelNotificationRequest", "cancelNotificationRequest"); dataMapRequest.getDataMap().putString("actionstring", actionstring); - log.debug("Canceling notification on wear: " + actionstring); + aapsLogger.debug(LTag.WEAR, "Canceling notification on wear: " + actionstring); PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest(); debugData("sendCancelNotificationRequest", putDataRequest); @@ -700,26 +694,25 @@ public class WatchUpdaterService extends WearableListenerService implements Goog private void sendStatus() { if (googleApiClient.isConnected()) { - Profile profile = ProfileFunctions.getInstance().getProfile(); - String status = MainApp.gs(R.string.noprofile); + Profile profile = profileFunction.getProfile(); + String status = resourceHelper.gs(R.string.noprofile); String iobSum, iobDetail, cobString, currentBasal, bgiString; iobSum = iobDetail = cobString = currentBasal = bgiString = ""; if (profile != null) { - TreatmentsInterface treatmentsInterface = TreatmentsPlugin.getPlugin(); - treatmentsInterface.updateTotalIOBTreatments(); - IobTotal bolusIob = treatmentsInterface.getLastCalculationTreatments().round(); - treatmentsInterface.updateTotalIOBTempBasals(); - IobTotal basalIob = treatmentsInterface.getLastCalculationTempBasals().round(); + treatmentsPlugin.updateTotalIOBTreatments(); + IobTotal bolusIob = treatmentsPlugin.getLastCalculationTreatments().round(); + treatmentsPlugin.updateTotalIOBTempBasals(); + IobTotal basalIob = treatmentsPlugin.getLastCalculationTempBasals().round(); iobSum = DecimalFormatter.to2Decimal(bolusIob.iob + basalIob.basaliob); iobDetail = "(" + DecimalFormatter.to2Decimal(bolusIob.iob) + "|" + DecimalFormatter.to2Decimal(basalIob.basaliob) + ")"; - cobString = IobCobCalculatorPlugin.getPlugin().getCobInfo(false, "WatcherUpdaterService").generateCOBString(); - currentBasal = generateBasalString(treatmentsInterface); + cobString = iobCobCalculatorPlugin.getCobInfo(false, "WatcherUpdaterService").generateCOBString(); + currentBasal = generateBasalString(); //bgi - double bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.fromMgdlToUnits(profile.getIsfMgdl(), ProfileFunctions.getSystemUnits()); + double bgi = -(bolusIob.activity + basalIob.activity) * 5 * Profile.fromMgdlToUnits(profile.getIsfMgdl(), profileFunction.getUnits()); bgiString = "" + ((bgi >= 0) ? "+" : "") + DecimalFormatter.to1Decimal(bgi); status = generateStatusString(profile, currentBasal, iobSum, iobDetail, bgiString); @@ -731,11 +724,11 @@ public class WatchUpdaterService extends WearableListenerService implements Goog String rigBattery = NSDeviceStatus.getInstance().getUploaderStatus().trim(); - long openApsStatus = -1; + long openApsStatus; //OpenAPS status if (Config.APS) { //we are AndroidAPS - openApsStatus = LoopPlugin.lastRun != null && LoopPlugin.lastRun.lastEnact != null && LoopPlugin.lastRun.lastEnact.getTime() != 0 ? LoopPlugin.lastRun.lastEnact.getTime() : -1; + openApsStatus = loopPlugin.lastRun != null && loopPlugin.lastRun.lastEnact != null && loopPlugin.lastRun.lastEnact.getTime() != 0 ? loopPlugin.lastRun.lastEnact.getTime() : -1; } else { //NSClient or remote openApsStatus = NSDeviceStatus.getOpenApsTimestamp(); @@ -746,14 +739,14 @@ public class WatchUpdaterService extends WearableListenerService implements Goog dataMapRequest.getDataMap().putString("externalStatusString", status); dataMapRequest.getDataMap().putString("iobSum", iobSum); dataMapRequest.getDataMap().putString("iobDetail", iobDetail); - dataMapRequest.getDataMap().putBoolean("detailedIob", SP.getBoolean(R.string.key_wear_detailediob, false)); + dataMapRequest.getDataMap().putBoolean("detailedIob", sp.getBoolean(R.string.key_wear_detailediob, false)); dataMapRequest.getDataMap().putString("cob", cobString); dataMapRequest.getDataMap().putString("currentBasal", currentBasal); dataMapRequest.getDataMap().putString("battery", "" + phoneBattery); dataMapRequest.getDataMap().putString("rigBattery", rigBattery); dataMapRequest.getDataMap().putLong("openApsStatus", openApsStatus); dataMapRequest.getDataMap().putString("bgi", bgiString); - dataMapRequest.getDataMap().putBoolean("showBgi", SP.getBoolean(R.string.key_wear_showbgi, false)); + dataMapRequest.getDataMap().putBoolean("showBgi", sp.getBoolean(R.string.key_wear_showbgi, false)); dataMapRequest.getDataMap().putInt("batteryLevel", (phoneBattery >= 30) ? 1 : 0); PutDataRequest putDataRequest = dataMapRequest.asPutDataRequest(); debugData("sendStatus", putDataRequest); @@ -766,7 +759,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog private void sendPreferences() { if (googleApiClient.isConnected()) { - boolean wearcontrol = SP.getBoolean("wearcontrol", false); + boolean wearcontrol = sp.getBoolean("wearcontrol", false); PutDataMapRequest dataMapRequest = PutDataMapRequest.create(NEW_PREFERENCES_PATH); //unique content @@ -785,7 +778,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog // Log.d(TAG, "WR: " + source + " " + data); } - private void executeTask(AsyncTask task, DataMap... parameters) { task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Object[]) parameters); // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { @@ -802,21 +794,19 @@ public class WatchUpdaterService extends WearableListenerService implements Goog String status = ""; if (profile == null) { - status = MainApp.gs(R.string.noprofile); + status = resourceHelper.gs(R.string.noprofile); return status; } - LoopPlugin activeloop = LoopPlugin.getPlugin(); - - if (!activeloop.isEnabled(PluginType.LOOP)) { - status += MainApp.gs(R.string.disabledloop) + "\n"; + if (!loopPlugin.isEnabled(PluginType.LOOP)) { + status += resourceHelper.gs(R.string.disabledloop) + "\n"; lastLoopStatus = false; } else { lastLoopStatus = true; } - String iobString = ""; - if (SP.getBoolean(R.string.key_wear_detailediob, false)) { + String iobString; + if (sp.getBoolean(R.string.key_wear_detailediob, false)) { iobString = iobSum + " " + iobDetail; } else { iobString = iobSum + "U"; @@ -825,7 +815,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog status += currentBasal + " " + iobString; //add BGI if shown, otherwise return - if (SP.getBoolean(R.string.key_wear_showbgi, false)) { + if (sp.getBoolean(R.string.key_wear_showbgi, false)) { status += " " + bgiString; } @@ -833,19 +823,19 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } @NonNull - private String generateBasalString(TreatmentsInterface treatmentsInterface) { + private String generateBasalString() { String basalStringResult; - Profile profile = ProfileFunctions.getInstance().getProfile(); + Profile profile = profileFunction.getProfile(); if (profile == null) return ""; - TemporaryBasal activeTemp = treatmentsInterface.getTempBasalFromHistory(System.currentTimeMillis()); + TemporaryBasal activeTemp = treatmentsPlugin.getTempBasalFromHistory(System.currentTimeMillis()); if (activeTemp != null) { basalStringResult = activeTemp.toStringShort(); } else { - if (SP.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) { + if (sp.getBoolean(R.string.key_danar_visualizeextendedaspercentage, false)) { basalStringResult = "100%"; } else { basalStringResult = DecimalFormatter.to2Decimal(profile.getBasal()) + "U/h"; @@ -859,7 +849,6 @@ public class WatchUpdaterService extends WearableListenerService implements Goog if (googleApiClient != null && googleApiClient.isConnected()) { googleApiClient.disconnect(); } - WearPlugin.unRegisterWatchUpdaterService(); } @Override @@ -867,7 +856,7 @@ public class WatchUpdaterService extends WearableListenerService implements Goog } @Override - public void onConnectionFailed(ConnectionResult connectionResult) { + public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { } public static boolean shouldReportLoopStatus(boolean enabled) { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 80656e4881..7aa83b8300 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1689,5 +1689,6 @@ Clear queue? All data in queue will be lost! xdripstatus_detailediob xdripstatus_showbgi + wear_detailed_delta diff --git a/app/src/main/res/xml/pref_wear.xml b/app/src/main/res/xml/pref_wear.xml index be74ee986a..e2cb0197ef 100644 --- a/app/src/main/res/xml/pref_wear.xml +++ b/app/src/main/res/xml/pref_wear.xml @@ -67,7 +67,7 @@