diff --git a/app/build.gradle b/app/build.gradle index 7275218a57..fdc2d5ebc9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -109,7 +109,7 @@ android { targetSdkVersion 28 multiDexEnabled true versionCode 1500 - version "2.4-dev-e" + version "2.4-dev-f" buildConfigField "String", "VERSION", '"' + version + '"' buildConfigField "String", "BUILDVERSION", '"' + generateGitBuild() + '-' + generateDate() + '"' buildConfigField "String", "REMOTE", '"' + generateGitRemote() + '"' diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java index ac83e93307..89696ad12f 100644 --- a/app/src/main/java/info/nightscout/androidaps/MainApp.java +++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java @@ -40,7 +40,7 @@ import info.nightscout.androidaps.plugins.constraints.dstHelper.DstHelperPlugin; import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; import info.nightscout.androidaps.plugins.constraints.storage.StorageConstraintPlugin; -import info.nightscout.androidaps.plugins.general.actions.ActionsFragment; +import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin; import info.nightscout.androidaps.plugins.general.automation.AutomationPlugin; import info.nightscout.androidaps.plugins.general.careportal.CareportalPlugin; import info.nightscout.androidaps.plugins.general.food.FoodPlugin; @@ -172,7 +172,7 @@ public class MainApp extends Application { // Register all tabs in app here pluginsList.add(OverviewPlugin.getPlugin()); pluginsList.add(IobCobCalculatorPlugin.getPlugin()); - if (Config.ACTION) pluginsList.add(ActionsFragment.getPlugin()); + if (Config.ACTION) pluginsList.add(ActionsPlugin.INSTANCE); pluginsList.add(InsulinOrefRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefUltraRapidActingPlugin.getPlugin()); pluginsList.add(InsulinOrefFreePeakPlugin.getPlugin()); @@ -205,7 +205,7 @@ public class MainApp extends Application { if (Config.SAFETY) pluginsList.add(VersionCheckerPlugin.INSTANCE); if (Config.SAFETY) pluginsList.add(StorageConstraintPlugin.getPlugin()); if (Config.SAFETY) pluginsList.add(SignatureVerifier.getPlugin()); - if (Config.APS) pluginsList.add(ObjectivesPlugin.getPlugin()); + if (Config.APS) pluginsList.add(ObjectivesPlugin.INSTANCE); pluginsList.add(SourceXdripPlugin.getPlugin()); pluginsList.add(SourceNSClientPlugin.getPlugin()); pluginsList.add(SourceMM640gPlugin.getPlugin()); @@ -221,11 +221,9 @@ public class MainApp extends Application { pluginsList.add(StatuslinePlugin.initPlugin(this)); pluginsList.add(PersistentNotificationPlugin.getPlugin()); pluginsList.add(NSClientPlugin.getPlugin()); - if (engineeringMode) - pluginsList.add(TidepoolPlugin.INSTANCE); +// if (engineeringMode) pluginsList.add(TidepoolPlugin.INSTANCE); pluginsList.add(MaintenancePlugin.initPlugin(this)); - if (engineeringMode) - pluginsList.add(AutomationPlugin.INSTANCE); + pluginsList.add(AutomationPlugin.INSTANCE); pluginsList.add(ConfigBuilderPlugin.getPlugin()); diff --git a/app/src/main/java/info/nightscout/androidaps/data/Profile.java b/app/src/main/java/info/nightscout/androidaps/data/Profile.java index 626d5775e0..ea63605ceb 100644 --- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java +++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java @@ -11,6 +11,7 @@ import org.slf4j.LoggerFactory; import java.text.DecimalFormat; import java.util.TimeZone; +import info.nightscout.androidaps.Config; import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -228,8 +229,10 @@ public class Profile { for (int index = 0; index < basal_v.size(); index++) { long secondsFromMidnight = basal_v.keyAt(index); if (notify && secondsFromMidnight % 3600 != 0) { - Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); - MainApp.bus().post(new EventNewNotification(notification)); + if (Config.APS) { + Notification notification = new Notification(Notification.BASAL_PROFILE_NOT_ALIGNED_TO_HOURS, String.format(MainApp.gs(R.string.basalprofilenotaligned), from), Notification.NORMAL); + MainApp.bus().post(new EventNewNotification(notification)); + } } } } diff --git a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java index f0e70c0a25..40fadff684 100644 --- a/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java +++ b/app/src/main/java/info/nightscout/androidaps/db/CareportalEvent.java @@ -93,12 +93,22 @@ public class CareportalEvent implements DataPointWithLabelInterface, Interval { return (System.currentTimeMillis() - date) / (60 * 60 * 1000.0); } - public String age() { + public String age(boolean useShortText) { Map diff = computeDiff(date, System.currentTimeMillis()); - if (OverviewFragment.shorttextmode) - return diff.get(TimeUnit.DAYS) + "d" + diff.get(TimeUnit.HOURS) + "h"; - else - return diff.get(TimeUnit.DAYS) + " " + MainApp.gs(R.string.days) + " " + diff.get(TimeUnit.HOURS) + " " + MainApp.gs(R.string.hours); + + String days = " " + MainApp.gs(R.string.days) + " "; + String hours = " " + MainApp.gs(R.string.hours) + " "; + + if (useShortText) { + days = "d"; + hours = "h"; + } + + return diff.get(TimeUnit.DAYS) + days + diff.get(TimeUnit.HOURS) + hours; + } + + public String age() { + return age(OverviewFragment.shorttextmode); } public boolean isOlderThan(double hours) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt index 2ab594c2a2..b7549fcfed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt @@ -12,10 +12,7 @@ import info.nightscout.androidaps.interfaces.Constraint import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopSetLastRunGui import info.nightscout.androidaps.plugins.aps.loop.events.EventLoopUpdateGui import info.nightscout.androidaps.plugins.bus.RxBus -import info.nightscout.androidaps.utils.DateUtil -import info.nightscout.androidaps.utils.FabricPrivacy -import info.nightscout.androidaps.utils.HtmlHelper -import info.nightscout.androidaps.utils.plusAssign +import info.nightscout.androidaps.utils.* import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import kotlinx.android.synthetic.main.loop_fragment.* @@ -61,6 +58,7 @@ class LoopFragment : Fragment() { }) updateGUI() + SP.putBoolean(R.string.key_objectiveuseloop, true) } @Synchronized 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 0425190723..c9444acb33 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 @@ -51,7 +51,6 @@ import info.nightscout.androidaps.plugins.aps.loop.events.EventNewOpenLoopNotifi import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.wear.ActionStringHandler; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.events.EventAutosensCalculationFinished; @@ -291,7 +290,7 @@ public class LoopPlugin extends PluginBase { Profile profile = ProfileFunctions.getInstance().getProfile(); - if (!ProfileFunctions.getInstance().isProfileValid("Loop")) { + if (profile == null || !ProfileFunctions.getInstance().isProfileValid("Loop")) { if (L.isEnabled(L.APS)) log.debug(MainApp.gs(R.string.noprofileselected)); RxBus.INSTANCE.send(new EventLoopSetLastRunGui(MainApp.gs(R.string.noprofileselected))); @@ -471,11 +470,7 @@ public class LoopPlugin extends PluginBase { lastRun.lastEnact = new Date(); lastRun.lastOpenModeAccept = new Date(); NSUpload.uploadDeviceStatus(); - ObjectivesPlugin objectivesPlugin = MainApp.getSpecificPlugin(ObjectivesPlugin.class); - if (objectivesPlugin != null) { - ObjectivesPlugin.getPlugin().manualEnacts++; - ObjectivesPlugin.getPlugin().saveProgress(); - } + SP.incInt(R.string.key_ObjectivesmanualEnacts); } MainApp.bus().post(new EventAcceptOpenLoopChange()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java index 7a1c2ee16e..703dc4255b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/DetermineBasalAdapterAMAJS.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; +import javax.annotation.Nullable; + import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -60,6 +62,7 @@ public class DetermineBasalAdapterAMAJS { mScriptReader = scriptReader; } + @Nullable public DetermineBasalResultAMA invoke() { if (L.isEnabled(L.APS)) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java index f8c1bbcaf1..ef31ad599e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSAMA/OpenAPSAMAPlugin.java @@ -29,6 +29,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.HardLimits; import info.nightscout.androidaps.utils.Profiler; import info.nightscout.androidaps.utils.Round; @@ -193,7 +194,8 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { isTempTarget ); } catch (JSONException e) { - log.error("Unable to set data: " + e.toString()); + FabricPrivacy.logException(e); + return; } @@ -201,22 +203,30 @@ public class OpenAPSAMAPlugin extends PluginBase implements APSInterface { if (L.isEnabled(L.APS)) Profiler.log(log, "AMA calculation", start); // Fix bug determine basal - if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) - determineBasalResultAMA.tempBasalRequested = false; + if (determineBasalResultAMA == null) { + if (L.isEnabled(L.APS)) + log.error("SMB calculation returned null"); + lastDetermineBasalAdapterAMAJS = null; + lastAPSResult = null; + lastAPSRun = 0; + } else { + if (determineBasalResultAMA.rate == 0d && determineBasalResultAMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) + determineBasalResultAMA.tempBasalRequested = false; - determineBasalResultAMA.iob = iobArray[0]; + determineBasalResultAMA.iob = iobArray[0]; - long now = System.currentTimeMillis(); + long now = System.currentTimeMillis(); - try { - determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); + try { + determineBasalResultAMA.json.put("timestamp", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + + lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS; + lastAPSResult = determineBasalResultAMA; + lastAPSRun = now; } - - lastDetermineBasalAdapterAMAJS = determineBasalAdapterAMAJS; - lastAPSResult = determineBasalResultAMA; - lastAPSRun = now; RxBus.INSTANCE.send(new EventOpenAPSUpdateGui()); //deviceStatus.suggested = determineBasalResultAMA.json; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java index 853af9ca83..1ded34b7cb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/DetermineBasalAdapterMAJS.java @@ -16,6 +16,8 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; +import javax.annotation.Nullable; + import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; @@ -48,6 +50,7 @@ public class DetermineBasalAdapterMAJS { mScriptReader = scriptReader; } + @Nullable public DetermineBasalResultMA invoke() { DetermineBasalResultMA determineBasalResultMA = null; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java index c573c19af1..899c0151d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSMA/OpenAPSMAPlugin.java @@ -26,6 +26,7 @@ import info.nightscout.androidaps.plugins.configBuilder.ProfileFunctions; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.HardLimits; import info.nightscout.androidaps.utils.Profiler; import info.nightscout.androidaps.utils.Round; @@ -170,7 +171,8 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface { try { determineBasalAdapterMAJS.setData(profile, maxIob, maxBasal, minBg, maxBg, targetBg, ConfigBuilderPlugin.getPlugin().getActivePump().getBaseBasalRate(), iobTotal, glucoseStatus, mealData); } catch (JSONException e) { - log.error("Unhandled exception", e); + FabricPrivacy.logException(e); + return; } if (L.isEnabled(L.APS)) Profiler.log(log, "MA calculation", start); @@ -179,21 +181,29 @@ public class OpenAPSMAPlugin extends PluginBase implements APSInterface { long now = System.currentTimeMillis(); DetermineBasalResultMA determineBasalResultMA = determineBasalAdapterMAJS.invoke(); - // Fix bug determinef basal - if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) - determineBasalResultMA.tempBasalRequested = false; + if (determineBasalResultMA == null) { + if (L.isEnabled(L.APS)) + log.error("MA calculation returned null"); + lastDetermineBasalAdapterMAJS = null; + lastAPSResult = null; + lastAPSRun = 0; + } else { + // Fix bug determinef basal + if (determineBasalResultMA.rate == 0d && determineBasalResultMA.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) + determineBasalResultMA.tempBasalRequested = false; - determineBasalResultMA.iob = iobTotal; + determineBasalResultMA.iob = iobTotal; - try { - determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); + try { + determineBasalResultMA.json.put("timestamp", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + + lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS; + lastAPSResult = determineBasalResultMA; + lastAPSRun = now; } - - lastDetermineBasalAdapterMAJS = determineBasalAdapterMAJS; - lastAPSResult = determineBasalResultMA; - lastAPSRun = now; RxBus.INSTANCE.send(new EventOpenAPSUpdateGui()); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java index 09f2148f7f..b7b6d82e5e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/DetermineBasalAdapterSMBJS.java @@ -18,6 +18,8 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.nio.charset.StandardCharsets; +import javax.annotation.Nullable; + import info.nightscout.androidaps.Constants; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; @@ -69,6 +71,7 @@ public class DetermineBasalAdapterSMBJS { } + @Nullable public DetermineBasalResultSMB invoke() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java index 5f90e572f7..d410eba291 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/openAPSSMB/OpenAPSSMBPlugin.java @@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.iob.iobCobCalculator.GlucoseStatus; import info.nightscout.androidaps.plugins.iob.iobCobCalculator.IobCobCalculatorPlugin; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.FabricPrivacy; import info.nightscout.androidaps.utils.HardLimits; import info.nightscout.androidaps.utils.Profiler; import info.nightscout.androidaps.utils.Round; @@ -219,7 +220,7 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr advancedFiltering.value() ); } catch (JSONException e) { - log.error(e.getMessage()); + FabricPrivacy.logException(e); return; } @@ -228,24 +229,32 @@ public class OpenAPSSMBPlugin extends PluginBase implements APSInterface, Constr DetermineBasalResultSMB determineBasalResultSMB = determineBasalAdapterSMBJS.invoke(); if (L.isEnabled(L.APS)) Profiler.log(log, "SMB calculation", start); - // TODO still needed with oref1? - // Fix bug determine basal - if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) - determineBasalResultSMB.tempBasalRequested = false; + if (determineBasalResultSMB == null) { + if (L.isEnabled(L.APS)) + log.error("SMB calculation returned null"); + lastDetermineBasalAdapterSMBJS = null; + lastAPSResult = null; + lastAPSRun = 0; + } else { + // TODO still needed with oref1? + // Fix bug determine basal + if (determineBasalResultSMB.rate == 0d && determineBasalResultSMB.duration == 0 && !TreatmentsPlugin.getPlugin().isTempBasalInProgress()) + determineBasalResultSMB.tempBasalRequested = false; - determineBasalResultSMB.iob = iobArray[0]; + determineBasalResultSMB.iob = iobArray[0]; - try { - determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now)); - } catch (JSONException e) { - log.error("Unhandled exception", e); + try { + determineBasalResultSMB.json.put("timestamp", DateUtil.toISOString(now)); + } catch (JSONException e) { + log.error("Unhandled exception", e); + } + + determineBasalResultSMB.inputConstraints = inputConstraints; + + lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS; + lastAPSResult = determineBasalResultSMB; + lastAPSRun = now; } - - determineBasalResultSMB.inputConstraints = inputConstraints; - - lastDetermineBasalAdapterSMBJS = determineBasalAdapterSMBJS; - lastAPSResult = determineBasalResultSMB; - lastAPSRun = now; RxBus.INSTANCE.send(new EventOpenAPSUpdateGui()); //deviceStatus.suggested = determineBasalResultAMA.json; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java index 7c92cd98b3..b9276a5ac3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/configBuilder/ProfileFunctions.java @@ -27,6 +27,7 @@ import info.nightscout.androidaps.plugins.general.overview.dialogs.ErrorHelperAc import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; import info.nightscout.androidaps.queue.Callback; import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; public class ProfileFunctions { private static Logger log = LoggerFactory.getLogger(L.PROFILE); @@ -101,7 +102,8 @@ public class ProfileFunctions { } public boolean isProfileValid(String from) { - return getProfile() != null && getProfile().isValid(from); + Profile profile = getProfile(); + return profile != null && profile.isValid(from); } @Nullable @@ -159,6 +161,8 @@ public class ProfileFunctions { public static void doProfileSwitch(final ProfileStore profileStore, final String profileName, final int duration, final int percentage, final int timeshift) { ProfileSwitch profileSwitch = prepareProfileSwitch(profileStore, profileName, duration, percentage, timeshift, System.currentTimeMillis()); TreatmentsPlugin.getPlugin().addToHistoryProfileSwitch(profileSwitch); + if (percentage == 90 && duration == 10) + SP.putBoolean(R.string.key_objectiveuseprofileswitch, true); } public static void doProfileSwitch(final int duration, final int percentage, final int timeshift) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java deleted file mode 100644 index 7600c017c2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.java +++ /dev/null @@ -1,229 +0,0 @@ -package info.nightscout.androidaps.plugins.constraints.objectives; - -import android.app.Activity; -import android.os.Bundle; -import android.os.Handler; -import android.os.Looper; -import androidx.annotation.NonNull; -import androidx.cardview.widget.CardView; -import androidx.recyclerview.widget.LinearLayoutManager; -import androidx.recyclerview.widget.LinearSmoothScroller; -import androidx.recyclerview.widget.RecyclerView; -import android.text.Html; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.LinearLayout; -import android.widget.TextView; - -import java.util.Date; - -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.common.SubscriberFragment; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective; -import info.nightscout.androidaps.utils.FabricPrivacy; - -public class ObjectivesFragment extends SubscriberFragment { - RecyclerView recyclerView; - CheckBox enableFake; - TextView reset; - ObjectivesAdapter objectivesAdapter = new ObjectivesAdapter(); - Handler handler = new Handler(Looper.getMainLooper()); - - private Runnable objectiveUpdater = new Runnable() { - @Override - public void run() { - handler.postDelayed(this, 60 * 1000); - updateGUI(); - } - }; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, - Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.objectives_fragment, container, false); - - recyclerView = view.findViewById(R.id.objectives_recyclerview); - recyclerView.setLayoutManager(new LinearLayoutManager(view.getContext())); - recyclerView.setAdapter(objectivesAdapter); - enableFake = view.findViewById(R.id.objectives_fake); - reset = view.findViewById(R.id.objectives_reset); - enableFake.setOnClickListener(v -> updateGUI()); - reset.setOnClickListener(v -> { - ObjectivesPlugin.getPlugin().reset(); - ObjectivesPlugin.getPlugin().saveProgress(); - recyclerView.getAdapter().notifyDataSetChanged(); - scrollToCurrentObjective(); - }); - scrollToCurrentObjective(); - startUpdateTimer(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; - } - - @Override - public synchronized void onDestroyView() { - super.onDestroyView(); - handler.removeCallbacks(objectiveUpdater); - } - - private void startUpdateTimer() { - handler.removeCallbacks(objectiveUpdater); - for (Objective objective : ObjectivesPlugin.getPlugin().getObjectives()) { - if (objective.isStarted() && !objective.isAccomplished()) { - long timeTillNextMinute = (System.currentTimeMillis() - objective.getStartedOn().getTime()) % (60 * 1000); - handler.postDelayed(objectiveUpdater, timeTillNextMinute); - break; - } - } - } - - private void scrollToCurrentObjective() { - for (int i = 0; i < ObjectivesPlugin.getPlugin().getObjectives().size(); i++) { - Objective objective = ObjectivesPlugin.getPlugin().getObjectives().get(i); - if (!objective.isStarted() || !objective.isAccomplished()) { - RecyclerView.SmoothScroller smoothScroller = new LinearSmoothScroller(getContext()) { - @Override - protected int getVerticalSnapPreference() { - return LinearSmoothScroller.SNAP_TO_START; - } - - @Override - protected int calculateTimeForScrolling(int dx) { - return super.calculateTimeForScrolling(dx) * 4; - } - }; - smoothScroller.setTargetPosition(i); - recyclerView.getLayoutManager().startSmoothScroll(smoothScroller); - break; - } - } - } - - private class ObjectivesAdapter extends RecyclerView.Adapter { - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.objectives_item, parent, false)); - } - - @Override - public void onBindViewHolder(@NonNull ViewHolder holder, int position) { - Objective objective = ObjectivesPlugin.getPlugin().getObjectives().get(position); - holder.title.setText(MainApp.gs(R.string.nth_objective, position + 1)); - holder.revert.setVisibility(View.INVISIBLE); - if (objective.getObjective() != 0) { - holder.objective.setVisibility(View.VISIBLE); - holder.objective.setText(MainApp.gs(objective.getObjective())); - } else holder.objective.setVisibility(View.GONE); - if (objective.getGate() != 0) { - holder.gate.setVisibility(View.VISIBLE); - holder.gate.setText(MainApp.gs(objective.getGate())); - } else holder.gate.setVisibility(View.GONE); - if (!objective.isStarted()) { - holder.gate.setTextColor(0xFFFFFFFF); - holder.verify.setVisibility(View.GONE); - holder.progress.setVisibility(View.GONE); - if (position == 0 || ObjectivesPlugin.getPlugin().getObjectives().get(position - 1).isAccomplished()) - holder.start.setVisibility(View.VISIBLE); - else holder.start.setVisibility(View.GONE); - } else if (objective.isAccomplished()) { - holder.gate.setTextColor(0xFF4CAF50); - holder.verify.setVisibility(View.GONE); - holder.progress.setVisibility(View.GONE); - holder.start.setVisibility(View.GONE); - } else if (objective.isStarted()) { - holder.gate.setTextColor(0xFFFFFFFF); - holder.verify.setVisibility(View.VISIBLE); - holder.verify.setEnabled(objective.isCompleted() || enableFake.isChecked()); - holder.start.setVisibility(View.GONE); - if(objective.isRevertable()) { - holder.revert.setVisibility(View.VISIBLE); - } - holder.progress.setVisibility(View.VISIBLE); - holder.progress.removeAllViews(); - for (Objective.Task task : objective.getTasks()) { - if (task.shouldBeIgnored()) continue; - TextView textView = new TextView(holder.progress.getContext()); - textView.setTextColor(0xFFFFFFFF); - String basicHTML = "%2$s: %3$s"; - String formattedHTML = String.format(basicHTML, task.isCompleted() ? "#4CAF50" : "#FF9800", MainApp.gs(task.getTask()), task.getProgress()); - textView.setText(Html.fromHtml(formattedHTML)); - holder.progress.addView(textView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); - } - } - holder.verify.setOnClickListener((view) -> { - objective.setAccomplishedOn(new Date()); - notifyDataSetChanged(); - scrollToCurrentObjective(); - startUpdateTimer(); - }); - holder.start.setOnClickListener((view) -> { - objective.setStartedOn(new Date()); - notifyDataSetChanged(); - scrollToCurrentObjective(); - startUpdateTimer(); - }); - holder.revert.setOnClickListener((view) -> { - objective.setAccomplishedOn(null); - objective.setStartedOn(null); - if (position > 0) { - Objective prevObj = ObjectivesPlugin.getPlugin().getObjectives().get(position - 1); - prevObj.setAccomplishedOn(null); - } - notifyDataSetChanged(); - scrollToCurrentObjective(); - }); - } - - - - @Override - public int getItemCount() { - return ObjectivesPlugin.getPlugin().getObjectives().size(); - } - - public class ViewHolder extends RecyclerView.ViewHolder { - - public CardView cardView; - public TextView title; - public TextView objective; - public TextView gate; - public LinearLayout progress; - public Button verify; - public Button start; - public Button revert; - - public ViewHolder(View itemView) { - super(itemView); - cardView = (CardView) itemView; - title = itemView.findViewById(R.id.objective_title); - objective = itemView.findViewById(R.id.objective_objective); - gate = itemView.findViewById(R.id.objective_gate); - progress = itemView.findViewById(R.id.objective_progress); - verify = itemView.findViewById(R.id.objective_verify); - start = itemView.findViewById(R.id.objective_start); - revert = itemView.findViewById(R.id.objective_back); - } - } - } - - @Override - public void updateGUI() { - Activity activity = getActivity(); - if (activity != null) - activity.runOnUiThread(() -> { - objectivesAdapter.notifyDataSetChanged(); - }); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt new file mode 100644 index 0000000000..63f522da8d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesFragment.kt @@ -0,0 +1,268 @@ +package info.nightscout.androidaps.plugins.constraints.objectives + +import android.graphics.Color +import android.os.Bundle +import android.os.Handler +import android.os.Looper +import android.view.Gravity +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Button +import android.widget.EditText +import android.widget.LinearLayout +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.LinearSmoothScroller +import androidx.recyclerview.widget.RecyclerView +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.constraints.objectives.activities.ObjectivesExamDialog +import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.ExamTask +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.HtmlHelper +import info.nightscout.androidaps.utils.SP +import io.reactivex.android.schedulers.AndroidSchedulers +import io.reactivex.disposables.CompositeDisposable +import kotlinx.android.synthetic.main.objectives_fragment.* + +class ObjectivesFragment : Fragment() { + private val objectivesAdapter = ObjectivesAdapter() + private val handler = Handler(Looper.getMainLooper()) + + private var disposable: CompositeDisposable = CompositeDisposable() + + private val objectiveUpdater = object : Runnable { + override fun run() { + handler.postDelayed(this, (60 * 1000).toLong()) + updateGUI() + } + } + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + return inflater.inflate(R.layout.objectives_fragment, container, false) + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + objectives_recyclerview.layoutManager = LinearLayoutManager(view.context) + objectives_recyclerview.adapter = objectivesAdapter + objectives_fake.setOnClickListener { updateGUI() } + objectives_reset.setOnClickListener { + ObjectivesPlugin.reset() + objectives_recyclerview.adapter?.notifyDataSetChanged() + scrollToCurrentObjective() + } + scrollToCurrentObjective() + startUpdateTimer() + } + + @Synchronized + override fun onResume() { + super.onResume() + disposable.add(RxBus + .toObservable(EventObjectivesUpdateGui::class.java) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ + objectives_recyclerview.adapter?.notifyDataSetChanged() + }, { + FabricPrivacy.logException(it) + }) + ) + } + + @Synchronized + override fun onPause() { + super.onPause() + disposable.clear() + } + + @Synchronized + override fun onDestroyView() { + super.onDestroyView() + handler.removeCallbacks(objectiveUpdater) + } + + private fun startUpdateTimer() { + handler.removeCallbacks(objectiveUpdater) + for (objective in ObjectivesPlugin.objectives) { + if (objective.isStarted && !objective.isAccomplished) { + val timeTillNextMinute = (System.currentTimeMillis() - objective.startedOn) % (60 * 1000) + handler.postDelayed(objectiveUpdater, timeTillNextMinute) + break + } + } + } + + private fun scrollToCurrentObjective() { + for (i in 0 until ObjectivesPlugin.objectives.size) { + val objective = ObjectivesPlugin.objectives[i] + if (!objective.isStarted || !objective.isAccomplished) { + val smoothScroller = object : LinearSmoothScroller(context!!) { + override fun getVerticalSnapPreference(): Int { + return SNAP_TO_START + } + + override fun calculateTimeForScrolling(dx: Int): Int { + return super.calculateTimeForScrolling(dx) * 4 + } + } + smoothScroller.targetPosition = i + objectives_recyclerview.layoutManager?.startSmoothScroll(smoothScroller) + break + } + } + } + + private inner class ObjectivesAdapter : RecyclerView.Adapter() { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { + return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.objectives_item, parent, false)) + } + + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val objective = ObjectivesPlugin.objectives[position] + holder.title.text = MainApp.gs(R.string.nth_objective, position + 1) + holder.revert.visibility = View.GONE + if (objective.objective != 0) { + holder.objective.visibility = View.VISIBLE + holder.objective.text = MainApp.gs(objective.objective) + } else + holder.objective.visibility = View.GONE + if (objective.gate != 0) { + holder.gate.visibility = View.VISIBLE + holder.gate.text = MainApp.gs(objective.gate) + } else + holder.gate.visibility = View.GONE + if (!objective.isStarted) { + holder.gate.setTextColor(-0x1) + holder.verify.visibility = View.GONE + holder.progress.visibility = View.GONE + holder.accomplished.visibility = View.GONE + if (position == 0 || ObjectivesPlugin.objectives[position - 1].isAccomplished) + holder.start.visibility = View.VISIBLE + else + holder.start.visibility = View.GONE + } else if (objective.isAccomplished) { + holder.gate.setTextColor(-0xb350b0) + holder.verify.visibility = View.GONE + holder.progress.visibility = View.GONE + holder.start.visibility = View.GONE + holder.accomplished.visibility = View.VISIBLE + } else if (objective.isStarted) { + holder.gate.setTextColor(-0x1) + holder.verify.visibility = View.VISIBLE + holder.verify.isEnabled = objective.isCompleted || objectives_fake.isChecked + holder.start.visibility = View.GONE + holder.accomplished.visibility = View.GONE + if (objective.isRevertable) { + holder.revert.visibility = View.VISIBLE + } + holder.progress.visibility = View.VISIBLE + holder.progress.removeAllViews() + for (task in objective.tasks) { + if (task.shouldBeIgnored()) continue + val name = TextView(holder.progress.context) + name.text = MainApp.gs(task.task) + ":" + name.setTextColor(-0x1) + holder.progress.addView(name, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + val state = TextView(holder.progress.context) + state.setTextColor(-0x1) + val basicHTML = "%2\$s" + val formattedHTML = String.format(basicHTML, if (task.isCompleted) "#4CAF50" else "#FF9800", task.progress) + state.text = HtmlHelper.fromHtml(formattedHTML) + state.gravity = Gravity.END + holder.progress.addView(state, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT) + if (task is ExamTask) { + state.setOnClickListener { + val dialog = ObjectivesExamDialog() + val bundle = Bundle() + val position = objective.tasks.indexOf(task) + bundle.putInt("currentTask", position) + dialog.arguments = bundle + ObjectivesExamDialog.objective = objective + fragmentManager?.let { dialog.show(it, "ObjectivesFragment") } + } + } + val separator = View(holder.progress.context) + separator.setBackgroundColor(Color.DKGRAY) + holder.progress.addView(separator, LinearLayout.LayoutParams.MATCH_PARENT, 2) + } + } + holder.accomplished.text = MainApp.gs(R.string.accomplished, DateUtil.dateAndTimeString(objective.accomplishedOn)) + holder.accomplished.setTextColor(-0x3e3e3f) + holder.verify.setOnClickListener { + objective.accomplishedOn = DateUtil.now() + notifyDataSetChanged() + scrollToCurrentObjective() + startUpdateTimer() + } + holder.start.setOnClickListener { + objective.startedOn = DateUtil.now() + notifyDataSetChanged() + scrollToCurrentObjective() + startUpdateTimer() + } + holder.revert.setOnClickListener { + objective.accomplishedOn = 0 + objective.startedOn = 0 + if (position > 0) { + val prevObj = ObjectivesPlugin.objectives[position - 1] + prevObj.accomplishedOn = 0 + } + notifyDataSetChanged() + scrollToCurrentObjective() + } + if (objective.hasSpecialInput && !objective.isAccomplished && objective.isStarted) { + // generate random request code if none exists + val request = SP.getString(R.string.key_objectives_request_code, String.format("%1$05d", (Math.random() * 99999).toInt())) + SP.putString(R.string.key_objectives_request_code, request) + holder.requestCode.text = MainApp.gs(R.string.requestcode, request) + holder.requestCode.visibility = View.VISIBLE + holder.enterButton.visibility = View.VISIBLE + holder.input.visibility = View.VISIBLE + holder.inputHint.visibility = View.VISIBLE + holder.enterButton.setOnClickListener { + val input = holder.input.text.toString() + objective.specialAction(activity, input) + notifyDataSetChanged() + } + } else { + holder.enterButton.visibility = View.GONE + holder.input.visibility = View.GONE + holder.inputHint.visibility = View.GONE + holder.requestCode.visibility = View.GONE + } + } + + + override fun getItemCount(): Int { + return ObjectivesPlugin.objectives.size + } + + inner class ViewHolder internal constructor(itemView: View) : RecyclerView.ViewHolder(itemView) { + val title: TextView = itemView.findViewById(R.id.objective_title) + val objective: TextView = itemView.findViewById(R.id.objective_objective) + val gate: TextView = itemView.findViewById(R.id.objective_gate) + val accomplished: TextView = itemView.findViewById(R.id.objective_accomplished) + val progress: LinearLayout = itemView.findViewById(R.id.objective_progress) + val verify: Button = itemView.findViewById(R.id.objective_verify) + val start: Button = itemView.findViewById(R.id.objective_start) + val revert: Button = itemView.findViewById(R.id.objective_back) + val inputHint: TextView = itemView.findViewById(R.id.objective_inputhint) + val input: EditText = itemView.findViewById(R.id.objective_input) + val enterButton: Button = itemView.findViewById(R.id.objective_enterbutton) + val requestCode: TextView = itemView.findViewById(R.id.objective_requestcode) + } + } + + fun updateGUI() { + activity?.runOnUiThread { objectivesAdapter.notifyDataSetChanged() } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java deleted file mode 100644 index 1d18cd14b4..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.java +++ /dev/null @@ -1,164 +0,0 @@ -package info.nightscout.androidaps.plugins.constraints.objectives; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.ArrayList; -import java.util.List; - -import info.nightscout.androidaps.Config; -import info.nightscout.androidaps.MainApp; -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.interfaces.ConstraintsInterface; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.interfaces.PumpInterface; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; -import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesSaved; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective1; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective2; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective3; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective4; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective5; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective6; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective7; -import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective8; -import info.nightscout.androidaps.utils.SP; - -/** - * Created by mike on 05.08.2016. - */ -public class ObjectivesPlugin extends PluginBase implements ConstraintsInterface { - private static Logger log = LoggerFactory.getLogger(L.CONSTRAINTS); - - private static ObjectivesPlugin objectivesPlugin; - - public List objectives = new ArrayList<>(); - public boolean bgIsAvailableInNS = false; - public boolean pumpStatusIsAvailableInNS = false; - public Integer manualEnacts = 0; - - public static ObjectivesPlugin getPlugin() { - if (objectivesPlugin == null) { - objectivesPlugin = new ObjectivesPlugin(); - } - return objectivesPlugin; - } - - private ObjectivesPlugin() { - super(new PluginDescription() - .mainType(PluginType.CONSTRAINTS) - .fragmentClass(ObjectivesFragment.class.getName()) - .alwaysEnabled(!Config.NSCLIENT) - .showInList(!Config.NSCLIENT) - .pluginName(R.string.objectives) - .shortName(R.string.objectives_shortname) - .description(R.string.description_objectives) - ); - setupObjectives(); - loadProgress(); - } - - @Override - public boolean specialEnableCondition() { - PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); - return pump == null || pump.getPumpDescription().isTempBasalCapable; - } - - private void setupObjectives() { - objectives.add(new Objective1()); - objectives.add(new Objective2()); - objectives.add(new Objective3()); - objectives.add(new Objective4()); - objectives.add(new Objective5()); - objectives.add(new Objective6()); - objectives.add(new Objective7()); - objectives.add(new Objective8()); - } - - public void reset() { - for (Objective objective : objectives) { - objective.setStartedOn(null); - objective.setAccomplishedOn(null); - } - bgIsAvailableInNS = false; - pumpStatusIsAvailableInNS = false; - manualEnacts = 0; - saveProgress(); - } - - public void saveProgress() { - SP.putBoolean("Objectives" + "bgIsAvailableInNS", bgIsAvailableInNS); - SP.putBoolean("Objectives" + "pumpStatusIsAvailableInNS", pumpStatusIsAvailableInNS); - SP.putString("Objectives" + "manualEnacts", Integer.toString(manualEnacts)); - if (L.isEnabled(L.CONSTRAINTS)) - log.debug("Objectives stored"); - MainApp.bus().post(new EventObjectivesSaved()); - } - - private void loadProgress() { - bgIsAvailableInNS = SP.getBoolean("Objectives" + "bgIsAvailableInNS", false); - pumpStatusIsAvailableInNS = SP.getBoolean("Objectives" + "pumpStatusIsAvailableInNS", false); - try { - manualEnacts = SP.getInt("Objectives" + "manualEnacts", 0); - } catch (Exception e) { - log.error("Unhandled exception", e); - } - if (L.isEnabled(L.CONSTRAINTS)) - log.debug("Objectives loaded"); - } - - public List getObjectives() { - return objectives; - } - - /** - * Constraints interface - **/ - @Override - public Constraint isLoopInvocationAllowed(Constraint value) { - if (!objectives.get(0).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 1), this); - return value; - } - - @Override - public Constraint isClosedLoopAllowed(Constraint value) { - if (!objectives.get(3).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 4), this); - return value; - } - - @Override - public Constraint isAutosensModeEnabled(Constraint value) { - if (!objectives.get(5).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 6), this); - return value; - } - - @Override - public Constraint isAMAModeEnabled(Constraint value) { - if (!objectives.get(6).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 7), this); - return value; - } - - @Override - public Constraint isSMBModeEnabled(Constraint value) { - if (!objectives.get(7).isStarted()) - value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), 8), this); - return value; - } - - @Override - public Constraint applyMaxIOBConstraints(Constraint maxIob) { - if (objectives.get(3).isStarted() && !objectives.get(3).isAccomplished()) - maxIob.set(0d, String.format(MainApp.gs(R.string.objectivenotfinished), 4), this); - return maxIob; - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt new file mode 100644 index 0000000000..dcd9dd31d1 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/ObjectivesPlugin.kt @@ -0,0 +1,170 @@ +package info.nightscout.androidaps.plugins.constraints.objectives + +import android.app.Activity +import com.google.common.base.Charsets +import com.google.common.hash.Hashing +import info.nightscout.androidaps.BuildConfig +import info.nightscout.androidaps.Config +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.* +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.SP +import java.util.* + +/** + * Created by mike on 05.08.2016. + */ +object ObjectivesPlugin : PluginBase(PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .fragmentClass(ObjectivesFragment::class.qualifiedName) + .alwaysEnabled(!Config.NSCLIENT) + .showInList(!Config.NSCLIENT) + .pluginName(R.string.objectives) + .shortName(R.string.objectives_shortname) + .description(R.string.description_objectives)), ConstraintsInterface { + + var objectives: MutableList = ArrayList() + + val FIRST_OBJECTIVE = 0 + val USAGE_OBJECTIVE = 1 + val EXAM_OBJECTIVE = 2 + val OPENLOOP_OBJECTIVE = 3 + val MAXBASAL_OBJECTIVE = 4 + val MAXIOB_ZERO_CL_OBJECTIVE = 5 + val MAXIOB_OBJECTIVE = 6 + val AUTOSENS_OBJECTIVE = 7 + val AMA_OBJECTIVE = 8 + val SMB_OBJECTIVE = 9 + + init { + convertSP() + setupObjectives() + } + + override fun specialEnableCondition(): Boolean { + val pump = ConfigBuilderPlugin.getPlugin().activePump + return pump == null || pump.pumpDescription.isTempBasalCapable + } + + // convert 2.3 SP version + private fun convertSP() { + doConvertSP(0, "config") + doConvertSP(1, "openloop") + doConvertSP(2, "maxbasal") + doConvertSP(3, "maxiobzero") + doConvertSP(4, "maxiob") + doConvertSP(5, "autosens") + doConvertSP(6, "ama") + doConvertSP(7, "smb") + } + + private fun doConvertSP(number: Int, name: String) { + if (!SP.contains("Objectives_" + name + "_started")) { + SP.putLong("Objectives_" + name + "_started", SP.getLong("Objectives" + number + "accomplished", 0L)) + SP.putLong("Objectives_" + name + "_accomplished", SP.getLong("Objectives" + number + "accomplished", 0L)) + } + // TODO: we can remove Objectives1accomplished sometimes later + } + + private fun setupObjectives() { + objectives.clear() + objectives.add(Objective0()) + objectives.add(Objective1()) + objectives.add(Objective2()) + objectives.add(Objective3()) + objectives.add(Objective4()) + objectives.add(Objective5()) + objectives.add(Objective6()) + objectives.add(Objective7()) + objectives.add(Objective8()) + objectives.add(Objective9()) + } + + fun reset() { + for (objective in objectives) { + objective.startedOn = 0 + objective.accomplishedOn = 0 + } + SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false) + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false) + SP.putInt(R.string.key_ObjectivesmanualEnacts, 0) + SP.putBoolean(R.string.key_objectiveuseprofileswitch, false) + SP.putBoolean(R.string.key_objectiveusedisconnect, false) + SP.putBoolean(R.string.key_objectiveusereconnect, false) + SP.putBoolean(R.string.key_objectiveusetemptarget, false) + SP.putBoolean(R.string.key_objectiveuseactions, false) + SP.putBoolean(R.string.key_objectiveuseloop, false) + SP.putBoolean(R.string.key_objectiveusescale, false) + } + + fun completeObjectives(activity: Activity, request: String) { + val requestCode = SP.getString(R.string.key_objectives_request_code, "") + var url = SP.getString(R.string.key_nsclientinternal_url, "").toLowerCase() + if (!url.endsWith("\"")) url = "$url/" + val hashNS = Hashing.sha1().hashString(url + BuildConfig.APPLICATION_ID + "/" + requestCode, Charsets.UTF_8).toString() + if (request.equals(hashNS.substring(0, 10), ignoreCase = true)) { + SP.putLong("Objectives_" + "openloop" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "openloop" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxbasal" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxbasal" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxiobzero" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxiobzero" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "maxiob" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "maxiob" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "autosens" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "autosens" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "ama" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "ama" + "_accomplished", DateUtil.now()) + SP.putLong("Objectives_" + "smb" + "_started", DateUtil.now()) + SP.putLong("Objectives_" + "smb" + "_accomplished", DateUtil.now()) + setupObjectives() + OKDialog.show(activity, "", MainApp.gs(R.string.codeaccepted), null) + } else { + OKDialog.show(activity, "", MainApp.gs(R.string.codeinvalid), null) + } + } + + /** + * Constraints interface + */ + override fun isLoopInvocationAllowed(value: Constraint): Constraint { + if (!objectives[FIRST_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), FIRST_OBJECTIVE + 1), this) + return value + } + + override fun isClosedLoopAllowed(value: Constraint): Constraint { + if (!objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) + return value + } + + override fun isAutosensModeEnabled(value: Constraint): Constraint { + if (!objectives[AUTOSENS_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AUTOSENS_OBJECTIVE + 1), this) + return value + } + + override fun isAMAModeEnabled(value: Constraint): Constraint { + if (!objectives[AMA_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), AMA_OBJECTIVE + 1), this) + return value + } + + override fun isSMBModeEnabled(value: Constraint): Constraint { + if (!objectives[SMB_OBJECTIVE].isStarted) + value.set(false, String.format(MainApp.gs(R.string.objectivenotstarted), SMB_OBJECTIVE + 1), this) + return value + } + + override fun applyMaxIOBConstraints(maxIob: Constraint): Constraint { + if (objectives[MAXIOB_ZERO_CL_OBJECTIVE].isStarted && !objectives[MAXIOB_ZERO_CL_OBJECTIVE].isAccomplished) + maxIob.set(0.0, String.format(MainApp.gs(R.string.objectivenotfinished), MAXIOB_ZERO_CL_OBJECTIVE + 1), this) + return maxIob + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt new file mode 100644 index 0000000000..a0d6f6cedf --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/activities/ObjectivesExamDialog.kt @@ -0,0 +1,132 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.activities + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.DialogFragment +import info.nightscout.androidaps.MainApp +import info.nightscout.androidaps.R +import info.nightscout.androidaps.plugins.bus.RxBus +import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesUpdateGui +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective +import info.nightscout.androidaps.plugins.constraints.objectives.objectives.Objective.* +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.OKDialog +import info.nightscout.androidaps.utils.T +import info.nightscout.androidaps.utils.ToastUtils +import kotlinx.android.synthetic.main.objectives_exam_fragment.* + +class ObjectivesExamDialog : DialogFragment() { + companion object { + var objective: Objective? = null + } + + var currentTask = 0 + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle?): View? { + // load data from bundle + (savedInstanceState ?: arguments)?.let { bundle -> + currentTask = bundle.getInt("currentTask", 0) + } + + return inflater.inflate(R.layout.objectives_exam_fragment, container, false) + } + + override fun onStart() { + super.onStart() + dialog.setCanceledOnTouchOutside(false) + dialog.window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + } + + override fun onResume() { + super.onResume() + updateGui() + } + + override fun onSaveInstanceState(bundle: Bundle) { + super.onSaveInstanceState(bundle) + bundle.putInt("currentTask", currentTask) + } + + fun updateGui() { + objective?.let { objective -> + val task: ExamTask = objective.tasks[currentTask] as ExamTask + objectives_exam_name.setText(task.task) + objectives_exam_question.setText(task.question) + // Options + objectives_exam_options.removeAllViews() + for (o in task.options) { + val option: Option = o as Option; + val cb = option.generate(context) + if (task.answered) { + cb.isEnabled = false + if (option.isCorrect) + cb.isChecked = true + } + objectives_exam_options.addView(cb) + } + // Hints + objectives_exam_hints.removeAllViews() + for (h in task.hints) { + val hint: Hint = h as Hint; + objectives_exam_hints.addView(hint.generate(context)) + } + // Disabled to + objectives_exam_disabledto.text = MainApp.gs(R.string.answerdisabledto, DateUtil.timeString(task.disabledTo)) + objectives_exam_disabledto.visibility = if (task.isEnabledAnswer) View.GONE else View.VISIBLE + // Buttons + objectives_exam_verify.isEnabled = !task.answered && task.isEnabledAnswer + objectives_exam_verify.setOnClickListener { + var result = true + for (o in task.options) { + val option: Option = o as Option; + result = result && option.evaluate() + } + task.setAnswered(result); + if (!result) { + task.disabledTo = DateUtil.now() + T.hours(1).msecs() + ToastUtils.showToastInUiThread(context, R.string.wronganswer) + } else task.disabledTo = 0 + updateGui() + RxBus.send(EventObjectivesUpdateGui()) + } + close.setOnClickListener { dismiss() } + objectives_exam_reset.setOnClickListener { + task.answered = false + //task.disabledTo = 0 + updateGui() + RxBus.send(EventObjectivesUpdateGui()) + } + objectives_back_button.isEnabled = currentTask != 0 + objectives_back_button.setOnClickListener { + currentTask-- + updateGui() + } + objectives_next_button.isEnabled = currentTask != objective.tasks.size - 1 + objectives_next_button.setOnClickListener { + currentTask++ + updateGui() + } + + objectives_next_unanswered_button.isEnabled = !objective.isCompleted + objectives_next_unanswered_button.setOnClickListener { + for (i in (currentTask + 1)..(objective.tasks.size - 1)) { + if (!objective.tasks[i].isCompleted) { + currentTask = i + updateGui() + return@setOnClickListener + } + } + for (i in 0..currentTask) { + if (!objective.tasks[i].isCompleted) { + currentTask = i + updateGui() + return@setOnClickListener + } + } + } + } + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java deleted file mode 100644 index d4dbb0251d..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesSaved.java +++ /dev/null @@ -1,6 +0,0 @@ -package info.nightscout.androidaps.plugins.constraints.objectives.events; - -import info.nightscout.androidaps.events.Event; - -public class EventObjectivesSaved extends Event { -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt new file mode 100644 index 0000000000..fd59db7d9f --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/events/EventObjectivesUpdateGui.kt @@ -0,0 +1,5 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.events + +import info.nightscout.androidaps.events.EventUpdateGui + +class EventObjectivesUpdateGui : EventUpdateGui() \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java index 55aba1b49f..f58d469fa2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective.java @@ -1,35 +1,41 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; +import android.app.Activity; +import android.content.Context; +import android.graphics.Color; +import android.text.util.Linkify; +import android.widget.CheckBox; +import android.widget.TextView; + import androidx.annotation.StringRes; import java.util.ArrayList; -import java.util.Date; import java.util.List; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.T; public abstract class Objective { - private int number; + private String spName; @StringRes private int objective; @StringRes private int gate; - private Date startedOn; - private Date accomplishedOn; - private List tasks = new ArrayList<>(); + private long startedOn; + private long accomplishedOn; + List tasks = new ArrayList<>(); + public boolean hasSpecialInput = false; - public Objective(int number, @StringRes int objective, @StringRes int gate) { - this.number = number; + public Objective(String spName, @StringRes int objective, @StringRes int gate) { + this.spName = spName; this.objective = objective; this.gate = gate; - startedOn = new Date(SP.getLong("Objectives" + number + "started", 0L)); - if (startedOn.getTime() == 0L) startedOn = null; - accomplishedOn = new Date(SP.getLong("Objectives" + number + "accomplished", 0L)); - if (accomplishedOn.getTime() == 0L) accomplishedOn = null; + startedOn = SP.getLong("Objectives_" + spName + "_started", 0L); + accomplishedOn = SP.getLong("Objectives_" + spName + "_accomplished", 0L); setupTasks(tasks); for (Task task : tasks) task.objective = this; } @@ -47,14 +53,14 @@ public abstract class Objective { } public boolean isAccomplished() { - return accomplishedOn != null; + return accomplishedOn != 0; } public boolean isStarted() { - return startedOn != null; + return startedOn != 0; } - public Date getStartedOn() { + public long getStartedOn() { return startedOn; } @@ -66,14 +72,18 @@ public abstract class Objective { return gate; } - public void setStartedOn(Date startedOn) { + public void setStartedOn(long startedOn) { this.startedOn = startedOn; - SP.putLong("Objectives" + number + "started", startedOn == null ? 0 : startedOn.getTime()); + SP.putLong("Objectives_" + spName + "_started", startedOn); } - public void setAccomplishedOn(Date accomplishedOn) { + public void setAccomplishedOn(long accomplishedOn) { this.accomplishedOn = accomplishedOn; - SP.putLong("Objectives" + number + "accomplished", accomplishedOn == null ? 0 : accomplishedOn.getTime()); + SP.putLong("Objectives_" + spName + "_accomplished", accomplishedOn); + } + + public long getAccomplishedOn() { + return accomplishedOn; } protected void setupTasks(List tasks) { @@ -84,6 +94,8 @@ public abstract class Objective { return tasks; } + public void specialAction(Activity activity, String input) {} + public abstract class Task { @StringRes private int task; @@ -93,7 +105,7 @@ public abstract class Objective { this.task = task; } - public int getTask() { + public @StringRes int getTask() { return task; } @@ -116,19 +128,19 @@ public abstract class Objective { private long minimumDuration; - public MinimumDurationTask(long minimumDuration) { + MinimumDurationTask(long minimumDuration) { super(R.string.time_elapsed); this.minimumDuration = minimumDuration; } @Override public boolean isCompleted() { - return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn().getTime() >= minimumDuration; + return getObjective().isStarted() && System.currentTimeMillis() - getObjective().getStartedOn() >= minimumDuration; } @Override public String getProgress() { - return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn().getTime()) + return getDurationText(System.currentTimeMillis() - getObjective().getStartedOn()) + " / " + getDurationText(minimumDuration); } @@ -142,4 +154,117 @@ public abstract class Objective { } } + public class ExamTask extends Task { + @StringRes + int question; + List hints = new ArrayList<>(); + List options = new ArrayList<>(); + private String spIdentifier; + private boolean answered; + private long disabledTo; + + ExamTask(@StringRes int task, @StringRes int question, String spIdentifier) { + super(task); + this.question = question; + this.spIdentifier = spIdentifier; + answered = SP.getBoolean("ExamTask_" + spIdentifier, false); + disabledTo = SP.getLong("DisabledTo_" + spIdentifier, 0L); + } + + public void setDisabledTo(long newState) { + disabledTo = newState; + SP.putLong("DisabledTo_" + spIdentifier, disabledTo); + } + + public long getDisabledTo() { + return disabledTo; + } + + public boolean isEnabledAnswer() { + return disabledTo < DateUtil.now(); + } + + public void setAnswered(boolean newState) { + answered = newState; + SP.putBoolean("ExamTask_" + spIdentifier, answered); + } + + public boolean getAnswered() { + return answered; + } + + ExamTask option(Option option) { + options.add(option); + return this; + } + + ExamTask hint(Hint hint) { + hints.add(hint); + return this; + } + + public @StringRes int getQuestion() { + return question; + } + + public List getOptions() { + return options; + } + + public List getHints() { + return hints; + } + + @Override + public boolean isCompleted() { + return answered; + } + } + + public class Option { + @StringRes int option; + boolean isCorrect; + + CheckBox cb; // TODO: change it, this will block releasing memeory + + Option(@StringRes int option, boolean isCorrect) { + this.option = option; + this.isCorrect = isCorrect; + } + + public boolean isCorrect() { + return isCorrect; + } + + public CheckBox generate(Context context) { + cb = new CheckBox(context); + cb.setText(option); + return cb; + } + + public boolean evaluate() { + boolean selection = cb.isChecked(); + if (selection && isCorrect) return true; + if (!selection && !isCorrect) return true; + return false; + } + } + + public class Hint { + @StringRes int hint; + + Hint(@StringRes int hint) { + this.hint = hint; + } + + public TextView generate(Context context) { + TextView textView = new TextView(context); + textView.setText(hint); + textView.setAutoLinkMask(Linkify.WEB_URLS); + textView.setLinksClickable(true); + textView.setLinkTextColor(Color.YELLOW); + Linkify.addLinks(textView, Linkify.WEB_URLS); + return textView; + } + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java new file mode 100644 index 0000000000..f6f0267a23 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective0.java @@ -0,0 +1,84 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.objectives; + +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.DatabaseHelper; +import info.nightscout.androidaps.interfaces.APSInterface; +import info.nightscout.androidaps.interfaces.PluginBase; +import info.nightscout.androidaps.interfaces.PluginType; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; +import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; +import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; +import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; +import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.utils.SP; + +public class Objective0 extends Objective { + + public Objective0() { + super("config", R.string.objectives_0_objective, R.string.objectives_0_gate); + } + + @Override + protected void setupTasks(List tasks) { + tasks.add(new Task(R.string.objectives_bgavailableinns) { + @Override + public boolean isCompleted() { + return SP.getBoolean(R.string.key_ObjectivesbgIsAvailableInNS, false); + } + }); + tasks.add(new Task(R.string.nsclienthaswritepermission) { + @Override + public boolean isCompleted() { + return NSClientPlugin.getPlugin().hasWritePermission(); + } + }); + tasks.add(new Task(R.string.virtualpump_uploadstatus_title) { + @Override + public boolean isCompleted() { + return SP.getBoolean("virtualpump_uploadstatus", false); + } + + @Override + public boolean shouldBeIgnored() { + return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); + } + }); + tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) { + @Override + public boolean isCompleted() { + return SP.getBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, false); + } + }); + tasks.add(new Task(R.string.hasbgdata) { + @Override + public boolean isCompleted() { + return DatabaseHelper.lastBg() != null; + } + }); + tasks.add(new Task(R.string.loopenabled) { + @Override + public boolean isCompleted() { + return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP); + } + }); + tasks.add(new Task(R.string.apsselected) { + @Override + public boolean isCompleted() { + APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS(); + if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) + return true; + return false; + } + }); + tasks.add(new Task(R.string.activate_profile) { + @Override + public boolean isCompleted() { + return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null; + } + }); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java index 65a716abab..22ff17331e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective1.java @@ -3,81 +3,60 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.db.DatabaseHelper; -import info.nightscout.androidaps.interfaces.APSInterface; -import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginType; -import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.aps.loop.LoopPlugin; -import info.nightscout.androidaps.plugins.general.nsclient.NSClientPlugin; -import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin; -import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.utils.DateUtil; +import info.nightscout.androidaps.plugins.general.actions.ActionsPlugin; import info.nightscout.androidaps.utils.SP; public class Objective1 extends Objective { + public Objective1() { - super(0, R.string.objectives_0_objective, R.string.objectives_0_gate); + super("usage", R.string.objectives_usage_objective, R.string.objectives_usage_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new Task(R.string.objectives_bgavailableinns) { + tasks.add(new Task(R.string.objectives_useprofileswitch) { @Override public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().bgIsAvailableInNS; + return SP.getBoolean(R.string.key_objectiveuseprofileswitch, false); } }); - tasks.add(new Task(R.string.nsclienthaswritepermission) { + tasks.add(new Task(R.string.objectives_usedisconnectpump) { @Override public boolean isCompleted() { - return NSClientPlugin.getPlugin().hasWritePermission(); + return SP.getBoolean(R.string.key_objectiveusedisconnect, false); } }); - tasks.add(new Task(R.string.virtualpump_uploadstatus_title) { + tasks.add(new Task(R.string.objectives_usereconnectpump) { @Override public boolean isCompleted() { - return SP.getBoolean("virtualpump_uploadstatus", false); - } - - @Override - public boolean shouldBeIgnored() { - return !VirtualPumpPlugin.getPlugin().isEnabled(PluginType.PUMP); + return SP.getBoolean(R.string.key_objectiveusereconnect, false); } }); - tasks.add(new Task(R.string.objectives_pumpstatusavailableinns) { + tasks.add(new Task(R.string.objectives_usetemptarget) { @Override public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS; + return SP.getBoolean(R.string.key_objectiveusetemptarget, false); } }); - tasks.add(new Task(R.string.hasbgdata) { + tasks.add(new Task(R.string.objectives_useactions) { @Override public boolean isCompleted() { - return DatabaseHelper.lastBg() != null; + return SP.getBoolean(R.string.key_objectiveuseactions, false) && ActionsPlugin.INSTANCE.isEnabled(PluginType.GENERAL) && ActionsPlugin.INSTANCE.isFragmentVisible(); } }); - tasks.add(new Task(R.string.loopenabled) { + tasks.add(new Task(R.string.objectives_useloop) { @Override public boolean isCompleted() { - return LoopPlugin.getPlugin().isEnabled(PluginType.LOOP); + return SP.getBoolean(R.string.key_objectiveuseloop, false); } }); - tasks.add(new Task(R.string.apsselected) { + tasks.add(new Task(R.string.objectives_usescale) { @Override public boolean isCompleted() { - APSInterface usedAPS = ConfigBuilderPlugin.getPlugin().getActiveAPS(); - if (usedAPS != null && ((PluginBase) usedAPS).isEnabled(PluginType.APS)) - return true; - return false; - } - }); - tasks.add(new Task(R.string.activate_profile) { - @Override - public boolean isCompleted() { - return TreatmentsPlugin.getPlugin().getProfileSwitchFromHistory(DateUtil.now()) != null; + return SP.getBoolean(R.string.key_objectiveusescale, false); } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java index 6f97bfdd95..380412f7ff 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective2.java @@ -1,36 +1,195 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; +import java.util.Collections; import java.util.List; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; -import info.nightscout.androidaps.utils.T; public class Objective2 extends Objective { - public final int MANUAL_ENACTS_NEEDED = 20; public Objective2() { - super(1, R.string.objectives_1_objective, R.string.objectives_1_gate); + super("exam", R.string.objectives_exam_objective, R.string.objectives_exam_gate); + for (Task task : tasks) { + if (!task.isCompleted()) setAccomplishedOn(0); + } } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(7).msecs())); - tasks.add(new Task(R.string.objectives_manualenacts) { - @Override - public boolean isCompleted() { - return ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED; - } + tasks.add(new ExamTask(R.string.dia_meaningofdia, R.string.dia_whatmeansdia,"dia") + .option(new Option(R.string.dia_minimumis3h, false)) + .option(new Option(R.string.dia_minimumis5h, true)) + .option(new Option(R.string.dia_meaningisequaltodiapump, false)) + .option(new Option(R.string.dia_valuemustbedetermined, true)) + .hint(new Hint(R.string.dia_hint1)) + ); + tasks.add(new ExamTask(R.string.hypott, R.string.hypott_whenhypott,"hypott") + .option(new Option(R.string.hypott_goinglow, false)) + .option(new Option(R.string.hypott_havinglow, false)) + .option(new Option(R.string.hypott_preventoversmb, true)) + .hint(new Hint(R.string.hypott_hint1)) + ); + tasks.add(new ExamTask(R.string.offlineprofile, R.string.offlineprofile_whatprofile,"offlineprofile") + .option(new Option(R.string.localprofile, true)) + .option(new Option(R.string.nsprofile, false)) + .option(new Option(R.string.offlineprofile_nsprofile, true)) + .hint(new Hint(R.string.offlineprofile_hint1)) + ); + tasks.add(new ExamTask(R.string.pumpdisconnect, R.string.pumpdisconnect_whattodo,"pumpdisconnect") + .option(new Option(R.string.pumpdisconnect_letknow, true)) + .option(new Option(R.string.pumpdisconnect_dontchnage, false)) + .hint(new Hint(R.string.pumpdisconnect_hint1)) + ); + tasks.add(new ExamTask(R.string.objectives, R.string.objectives_howtosave,"objectives") + .option(new Option(R.string.objectives_exportsettings, true)) + .option(new Option(R.string.objectives_storeelsewhere, true)) + .option(new Option(R.string.objectives_doexportonstart, false)) + .option(new Option(R.string.objectives_doexportafterchange, true)) + .option(new Option(R.string.objectives_doexportafterfirtssettings, true)) + .hint(new Hint(R.string.objectives_hint1)) + .hint(new Hint(R.string.objectives_hint2)) + ); + tasks.add(new ExamTask(R.string.noisycgm, R.string.noisycgm_whattodo,"noisycgm") + .option(new Option(R.string.nothing, false)) + .option(new Option(R.string.disconnectpumpfor1h, false)) + .option(new Option(R.string.noisycgm_pause, true)) + .option(new Option(R.string.noisycgm_replacesensor, true)) + .option(new Option(R.string.noisycgm_turnoffphone, false)) + .option(new Option(R.string.noisycgm_checksmoothing, true)) + .hint(new Hint(R.string.noisycgm_hint1)) + ); + tasks.add(new ExamTask(R.string.exercise, R.string.exercise_whattodo,"exercise") + .option(new Option(R.string.nothing, false)) + .option(new Option(R.string.exercise_setactivitytt, true)) + .option(new Option(R.string.exercise_switchprofilebelow100, true)) + .option(new Option(R.string.exercise_switchprofileabove100, false)) + .option(new Option(R.string.exercise_stoploop, false)) + .option(new Option(R.string.exercise_doitbeforestart, true)) + .option(new Option(R.string.exercise_doitafterstart, false)) + .hint(new Hint(R.string.exercise_hint1)) + ); + tasks.add(new ExamTask(R.string.suspendloop, R.string.suspendloop_doigetinsulin,"suspendloop") + .option(new Option(R.string.suspendloop_yes, true)) + .option(new Option(R.string.suspendloop_no, false)) + ); + tasks.add(new ExamTask(R.string.basaltest, R.string.basaltest_when,"basaltest") + .option(new Option(R.string.basaltest_beforeloop, true)) + .option(new Option(R.string.basaltest_havingregularhypo, true)) + .option(new Option(R.string.basaltest_havingregularhyper, true)) + .hint(new Hint(R.string.basaltest_hint1)) + ); + tasks.add(new ExamTask(R.string.prerequisites, R.string.prerequisites_what, "prerequisites") + .option(new Option(R.string.prerequisites_determinedcorrectprofile, true)) + .option(new Option(R.string.prerequisites_computer, true)) + .option(new Option(R.string.prerequisites_phone, true)) + .option(new Option(R.string.prerequisites_car, false)) + .option(new Option(R.string.prerequisites_nightscout, true)) + .option(new Option(R.string.prerequisites_tidepoolaccount, false)) + .option(new Option(R.string.prerequisites_googleaccount, false)) + .option(new Option(R.string.prerequisites_githubaccount, false)) + .option(new Option(R.string.prerequisites_beanandroiddeveloper, false)) + .option(new Option(R.string.prerequisites_own670g, false)) + .option(new Option(R.string.prerequisites_smartwatch, false)) + .option(new Option(R.string.prerequisites_supportedcgm, true)) + .hint(new Hint(R.string.prerequisites_hint1)) + ); + tasks.add(new ExamTask(R.string.update_update, R.string.whatistrue,"update") + .option(new Option(R.string.update_git, true)) + .option(new Option(R.string.update_asap, true)) + .option(new Option(R.string.update_keys, true)) + .option(new Option(R.string.update_neverupdate, false)) + .option(new Option(R.string.update_askfriend, false)) + .hint(new Hint(R.string.update_hint1)) + ); + tasks.add(new ExamTask(R.string.troubleshooting, R.string.troubleshooting_wheretoask,"troubleshooting") + .option(new Option(R.string.troubleshooting_fb, true)) + .option(new Option(R.string.troubleshooting_wiki, true)) + .option(new Option(R.string.troubleshooting_gitter, true)) + .option(new Option(R.string.troubleshooting_googlesupport, false)) + .option(new Option(R.string.troubleshooting_yourendo, false)) + .hint(new Hint(R.string.troubleshooting_hint1)) + .hint(new Hint(R.string.troubleshooting_hint2)) + .hint(new Hint(R.string.troubleshooting_hint3)) + ); + tasks.add(new ExamTask(R.string.insulin, R.string.insulin_ultrarapid,"insulin") + .option(new Option(R.string.insulin_fiasp, true)) + .option(new Option(R.string.insulin_novorapid, false)) + .option(new Option(R.string.insulin_humalog, false)) + .option(new Option(R.string.insulin_actrapid, false)) + .hint(new Hint(R.string.insulin_hint1)) + ); + tasks.add(new ExamTask(R.string.sensitivity, R.string.sensitivity_which,"sensitivity") + .option(new Option(R.string.sensitivityweightedaverage, true)) + .option(new Option(R.string.sensitivityoref0, false)) + .option(new Option(R.string.sensitivityoref1, false)) + .option(new Option(R.string.sensitivityaaps, true)) + .hint(new Hint(R.string.sensitivity_hint1)) + ); + tasks.add(new ExamTask(R.string.sensitivity, R.string.sensitivityuam_which,"sensitivityuam") + .option(new Option(R.string.sensitivityweightedaverage, false)) + .option(new Option(R.string.sensitivityoref0, false)) + .option(new Option(R.string.sensitivityoref1, true)) + .option(new Option(R.string.sensitivityaaps, false)) + .hint(new Hint(R.string.sensitivity_hint1)) + ); + tasks.add(new ExamTask(R.string.wrongcarbs, R.string.wrongcarbs_whattodo,"wrongcarbs") + .option(new Option(R.string.wrongcarbs_addfakeinsulin, false)) + .option(new Option(R.string.wrongcarbs_treatmentstab, true)) + ); + tasks.add(new ExamTask(R.string.extendedcarbs, R.string.extendedcarbs_handling,"extendedcarbs") + .option(new Option(R.string.extendedcarbs_useextendedcarbs, true)) + .option(new Option(R.string.extendedcarbs_add, false)) + .option(new Option(R.string.extendedcarbs_useextendedbolus, false)) + .hint(new Hint(R.string.extendedcarbs_hint1)) + ); + tasks.add(new ExamTask(R.string.nsclient_monitoring, R.string.nsclient_howcanyou,"nsclient") + .option(new Option(R.string.nightscout, true)) + .option(new Option(R.string.nsclientinternal, true)) + .option(new Option(R.string.dexcomfollow, true)) + .option(new Option(R.string.dexcomfollowxdrip, false)) + .option(new Option(R.string.xdripfollower, true)) + .option(new Option(R.string.looponiphone, false)) + .option(new Option(R.string.spikeiphone, true)) + ); + tasks.add(new ExamTask(R.string.nsprofileview_isf_label, R.string.whatistrue,"isf") + .option(new Option(R.string.isf_increasingvalue, true)) + .option(new Option(R.string.isf_decreasingvalue, false)) + .option(new Option(R.string.isf_noeffect, false)) + .option(new Option(R.string.isf_preferences, false)) + .option(new Option(R.string.isf_profile, false)) + .hint(new Hint(R.string.isf_hint1)) + .hint(new Hint(R.string.isf_hint2)) + ); + tasks.add(new ExamTask(R.string.nsprofileview_ic_label, R.string.whatistrue,"ic") + .option(new Option(R.string.ic_increasingvalue, true)) + .option(new Option(R.string.ic_decreasingvalue, false)) + .option(new Option(R.string.ic_noeffect, false)) + .option(new Option(R.string.ic_different, false)) + .option(new Option(R.string.ic_meaning, false)) + .hint(new Hint(R.string.ic_hint1)) + ); + tasks.add(new ExamTask(R.string.profileswitch, R.string.profileswitch_pctwillchange,"profileswitch") + .option(new Option(R.string.profileswitch_basalhigher, false)) + .option(new Option(R.string.profileswitch_basallower, true)) + .option(new Option(R.string.profileswitch_ichigher, true)) + .option(new Option(R.string.profileswitch_iclower, false)) + .option(new Option(R.string.profileswitch_isfhigher, true)) + .option(new Option(R.string.profileswitch_isflower, false)) + .option(new Option(R.string.profileswitch_overall, true)) + .option(new Option(R.string.profileswitch_targethigher, false)) + .option(new Option(R.string.profileswitch_targetlower, false)) + .option(new Option(R.string.profileswitch_targetbottom, false)) + .hint(new Hint(R.string.profileswitch_hint1)) + ); - @Override - public String getProgress() { - if (ObjectivesPlugin.getPlugin().manualEnacts >= MANUAL_ENACTS_NEEDED) - return MainApp.gs(R.string.completed_well_done); - else - return ObjectivesPlugin.getPlugin().manualEnacts + " / " + MANUAL_ENACTS_NEEDED; - } - }); + for (Task task : tasks) + Collections.shuffle(((ExamTask)task).options); } + + @Override + public boolean isRevertable() { + return true; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java index 4924d9434c..c9ac7d8935 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective3.java @@ -1,10 +1,45 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; +import android.app.Activity; + +import java.util.List; + +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.T; public class Objective3 extends Objective { + public final int MANUAL_ENACTS_NEEDED = 20; + public Objective3() { - super(2, R.string.objectives_2_objective, R.string.objectives_2_gate); + super("openloop", R.string.objectives_openloop_objective, R.string.objectives_openloop_gate); + hasSpecialInput = true; + } + + @Override + protected void setupTasks(List tasks) { + tasks.add(new MinimumDurationTask(T.days(7).msecs())); + tasks.add(new Task(R.string.objectives_manualenacts) { + @Override + public boolean isCompleted() { + return SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED; + } + + @Override + public String getProgress() { + if (SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) >= MANUAL_ENACTS_NEEDED) + return MainApp.gs(R.string.completed_well_done); + else + return SP.getInt(R.string.key_ObjectivesmanualEnacts, 0) + " / " + MANUAL_ENACTS_NEEDED; + } + }); + } + + @Override + public void specialAction(Activity activity, String input) { + ObjectivesPlugin.INSTANCE.completeObjectives(activity, input); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java index 1bbb4ef7c2..bb46d3c338 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective4.java @@ -1,33 +1,10 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; -import java.util.List; - import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.Constraint; -import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; -import info.nightscout.androidaps.utils.T; public class Objective4 extends Objective { public Objective4() { - super(3, R.string.objectives_3_objective, R.string.objectives_3_gate); - } - - @Override - protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(5).msecs())); - tasks.add(new Task(R.string.closedmodeenabled) { - @Override - public boolean isCompleted() { - Constraint closedLoopEnabled = new Constraint<>(true); - SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled); - return closedLoopEnabled.value(); - } - }); - } - - @Override - public boolean isRevertable() { - return true; + super("maxbasal", R.string.objectives_maxbasal_objective, R.string.objectives_maxbasal_gate); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java index b04062655a..2407594069 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective5.java @@ -2,25 +2,32 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; -import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.interfaces.Constraint; +import info.nightscout.androidaps.plugins.constraints.safety.SafetyPlugin; import info.nightscout.androidaps.utils.T; public class Objective5 extends Objective { public Objective5() { - super(4, R.string.objectives_4_objective, R.string.objectives_4_gate); + super("maxiobzero", R.string.objectives_maxiobzero_objective, R.string.objectives_maxiobzero_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(1).msecs())); - tasks.add(new Task(R.string.maxiobset) { + tasks.add(new MinimumDurationTask(T.days(5).msecs())); + tasks.add(new Task(R.string.closedmodeenabled) { @Override public boolean isCompleted() { - double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); - return maxIOB > 0; + Constraint closedLoopEnabled = new Constraint<>(true); + SafetyPlugin.getPlugin().isClosedLoopAllowed(closedLoopEnabled); + return closedLoopEnabled.value(); } }); } + + @Override + public boolean isRevertable() { + return true; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java index 284dfa3ab0..1b224bd40c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective6.java @@ -2,17 +2,25 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; +import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.utils.T; public class Objective6 extends Objective { public Objective6() { - super(5, R.string.objectives_5_objective, R.string.objectives_5_gate); + super("maxiob", R.string.objectives_maxiob_objective, R.string.objectives_maxiob_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(7).msecs())); + tasks.add(new MinimumDurationTask(T.days(1).msecs())); + tasks.add(new Task(R.string.maxiobset) { + @Override + public boolean isCompleted() { + double maxIOB = MainApp.getConstraintChecker().getMaxIOBAllowed().value(); + return maxIOB > 0; + } + }); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java index f90411ecfb..497eb0a180 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective7.java @@ -3,16 +3,17 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.utils.T; public class Objective7 extends Objective { public Objective7() { - super(6, R.string.objectives_6_objective, 0); + super("autosens", R.string.objectives_autosens_objective, R.string.objectives_autosens_gate); } @Override protected void setupTasks(List tasks) { - tasks.add(new MinimumDurationTask(T.days(28).msecs())); + tasks.add(new MinimumDurationTask(T.days(7).msecs())); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java index 7148f5e5ad..3f943041b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective8.java @@ -3,12 +3,13 @@ package info.nightscout.androidaps.plugins.constraints.objectives.objectives; import java.util.List; import info.nightscout.androidaps.R; +import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.utils.T; public class Objective8 extends Objective { public Objective8() { - super(7, R.string.objectives_7_objective, R.string.objectives_7_gate); + super("ama", R.string.objectives_ama_objective, 0); } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java new file mode 100644 index 0000000000..106c25cb79 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/objectives/objectives/Objective9.java @@ -0,0 +1,18 @@ +package info.nightscout.androidaps.plugins.constraints.objectives.objectives; + +import java.util.List; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.utils.T; + +public class Objective9 extends Objective { + + public Objective9() { + super("smb", R.string.objectives_smb_objective, R.string.objectives_smb_gate); + } + + @Override + protected void setupTasks(List tasks) { + tasks.add(new MinimumDurationTask(T.days(28).msecs())); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java index 7248a49f0f..579700be4c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsFragment.java @@ -5,13 +5,13 @@ import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; -import androidx.fragment.app.Fragment; -import androidx.fragment.app.FragmentManager; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; +import androidx.fragment.app.FragmentManager; + import com.squareup.otto.Subscribe; import java.util.ArrayList; @@ -43,31 +43,21 @@ import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment; import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow; import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin; -import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; import info.nightscout.androidaps.utils.SingleClickButton; - -/** - * A simple {@link Fragment} subclass. - */ public class ActionsFragment extends SubscriberFragment implements View.OnClickListener { - static ActionsPlugin actionsPlugin = new ActionsPlugin(); - - static public ActionsPlugin getPlugin() { - return actionsPlugin; - } - - View actionsFragmentView; - SingleClickButton profileSwitch; - SingleClickButton tempTarget; - SingleClickButton extendedBolus; - SingleClickButton extendedBolusCancel; - SingleClickButton tempBasal; - SingleClickButton tempBasalCancel; - SingleClickButton fill; - SingleClickButton tddStats; - SingleClickButton history; + private View actionsFragmentView; + private SingleClickButton profileSwitch; + private SingleClickButton tempTarget; + private SingleClickButton extendedBolus; + private SingleClickButton extendedBolusCancel; + private SingleClickButton tempBasal; + private SingleClickButton tempBasalCancel; + private SingleClickButton fill; + private SingleClickButton tddStats; + private SingleClickButton history; private Map pumpCustomActions = new HashMap<>(); private List pumpCustomButtons = new ArrayList<>(); @@ -80,38 +70,33 @@ public class ActionsFragment extends SubscriberFragment implements View.OnClickL @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - try { - View view = inflater.inflate(R.layout.actions_fragment, container, false); + View view = inflater.inflate(R.layout.actions_fragment, container, false); - profileSwitch = (SingleClickButton) view.findViewById(R.id.actions_profileswitch); - tempTarget = (SingleClickButton) view.findViewById(R.id.actions_temptarget); - extendedBolus = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus); - extendedBolusCancel = (SingleClickButton) view.findViewById(R.id.actions_extendedbolus_cancel); - tempBasal = (SingleClickButton) view.findViewById(R.id.actions_settempbasal); - tempBasalCancel = (SingleClickButton) view.findViewById(R.id.actions_canceltempbasal); - fill = (SingleClickButton) view.findViewById(R.id.actions_fill); - tddStats = view.findViewById(R.id.actions_tddstats); - history = view.findViewById(R.id.actions_historybrowser); + profileSwitch = view.findViewById(R.id.actions_profileswitch); + tempTarget = view.findViewById(R.id.actions_temptarget); + extendedBolus = view.findViewById(R.id.actions_extendedbolus); + extendedBolusCancel = view.findViewById(R.id.actions_extendedbolus_cancel); + tempBasal = view.findViewById(R.id.actions_settempbasal); + tempBasalCancel = view.findViewById(R.id.actions_canceltempbasal); + fill = view.findViewById(R.id.actions_fill); + tddStats = view.findViewById(R.id.actions_tddstats); + history = view.findViewById(R.id.actions_historybrowser); - profileSwitch.setOnClickListener(this); - tempTarget.setOnClickListener(this); - extendedBolus.setOnClickListener(this); - extendedBolusCancel.setOnClickListener(this); - tempBasal.setOnClickListener(this); - tempBasalCancel.setOnClickListener(this); - fill.setOnClickListener(this); - history.setOnClickListener(this); - tddStats.setOnClickListener(this); + profileSwitch.setOnClickListener(this); + tempTarget.setOnClickListener(this); + extendedBolus.setOnClickListener(this); + extendedBolusCancel.setOnClickListener(this); + tempBasal.setOnClickListener(this); + tempBasalCancel.setOnClickListener(this); + fill.setOnClickListener(this); + history.setOnClickListener(this); + tddStats.setOnClickListener(this); - actionsFragmentView = view; + actionsFragmentView = view; - updateGUI(); - return view; - } catch (Exception e) { - FabricPrivacy.logException(e); - } - - return null; + updateGUI(); + SP.putBoolean(R.string.key_objectiveuseactions, true); + return view; } @Subscribe diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java deleted file mode 100644 index 5d47206e5c..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.java +++ /dev/null @@ -1,23 +0,0 @@ -package info.nightscout.androidaps.plugins.general.actions; - -import info.nightscout.androidaps.R; -import info.nightscout.androidaps.interfaces.PluginBase; -import info.nightscout.androidaps.interfaces.PluginDescription; -import info.nightscout.androidaps.interfaces.PluginType; - -/** - * Created by mike on 05.11.2016. - */ - -public class ActionsPlugin extends PluginBase { - - public ActionsPlugin() { - super(new PluginDescription() - .mainType(PluginType.GENERAL) - .fragmentClass(ActionsFragment.class.getName()) - .pluginName(R.string.actions) - .shortName(R.string.actions_shortname) - .description(R.string.description_actions) - ); - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt new file mode 100644 index 0000000000..086c75a157 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/actions/ActionsPlugin.kt @@ -0,0 +1,13 @@ +package info.nightscout.androidaps.plugins.general.actions + +import info.nightscout.androidaps.R +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType + +object ActionsPlugin : PluginBase(PluginDescription() + .mainType(PluginType.GENERAL) + .fragmentClass(ActionsFragment::class.java.name) + .pluginName(R.string.actions) + .shortName(R.string.actions_shortname) + .description(R.string.description_actions)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java index b4c6fb1f11..ec1cac23d6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/EventListAdapter.java @@ -84,14 +84,13 @@ class EventListAdapter extends RecyclerView.Adapter // enabled event holder.enabled.setOnCheckedChangeListener((buttonView, isChecked) -> { event.setEnabled(isChecked); - notifyDataSetChanged(); RxBus.INSTANCE.send(new EventAutomationDataChanged()); }); // remove event holder.iconTrash.setOnClickListener(v -> { mEventList.remove(event); - notifyDataSetChanged(); + RxBus.INSTANCE.send(new EventAutomationDataChanged()); }); // edit event diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java index 05d06f0b3a..659bb508eb 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/actions/ActionStartTempTarget.java @@ -71,7 +71,7 @@ public class ActionStartTempTarget extends Action { int unitResId = value.getUnits().equals(Constants.MGDL) ? R.string.mgdl : R.string.mmol; new LayoutBuilder() - .add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget), MainApp.gs(unitResId), value)) + .add(new LabelWithElement(MainApp.gs(R.string.careportal_temporarytarget) + " [" + MainApp.gs(unitResId) + "]", "", value)) .add(new LabelWithElement(MainApp.gs(R.string.careportal_newnstreatment_duration_min_label), "", duration)) .build(root); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java index f8464e7ee0..518b00f5b4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDouble.java @@ -25,8 +25,8 @@ public class InputDouble extends Element { }; private double value; - double minValue; - double maxValue; + private double minValue; + private double maxValue; private double step; private DecimalFormat decimalFormat; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java index a35fe4a4ad..aa19896471 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.java @@ -20,6 +20,11 @@ public class InputDuration extends Element { this.value = value; } + public InputDuration(InputDuration another) { + unit = another.unit; + value = another.value; + } + @Override public void addToLayout(LinearLayout root) { NumberPicker numberPicker = new NumberPicker(root.getContext(), null); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java index 8175c496a5..7e9207c0e1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputTempTarget.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.general.automation.elements; +import android.text.Editable; +import android.text.TextWatcher; import android.widget.LinearLayout; import java.text.DecimalFormat; @@ -17,13 +19,29 @@ public class InputTempTarget extends Element { private double step; private DecimalFormat decimalFormat; + private final TextWatcher textWatcher = new TextWatcher() { + @Override + public void afterTextChanged(Editable s) { + value = Math.max(minValue, value); + value = Math.min(maxValue, value); + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + } + }; + public InputTempTarget() { super(); setUnits(ProfileFunctions.getInstance().getProfileUnits()); if (getUnits().equals(Constants.MMOL)) - value = Constants.MIN_TT_MMOL; + value = 6; else - value = Constants.MIN_TT_MGDL; + value = 110; } public InputTempTarget(InputTempTarget another) { @@ -36,7 +54,7 @@ public class InputTempTarget extends Element { @Override public void addToLayout(LinearLayout root) { NumberPicker numberPicker = new NumberPicker(root.getContext(), null); - numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, null); + numberPicker.setParams(value, minValue, maxValue, step, decimalFormat, true, null, textWatcher); numberPicker.setOnValueChangedListener(value -> this.value = value); root.addView(numberPicker); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java index 2531d56e6c..145d8c2d2c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/LabelWithElement.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.general.automation.elements; import android.graphics.Typeface; import android.view.ViewGroup; import android.widget.LinearLayout; +import android.widget.TableLayout; import android.widget.TextView; import info.nightscout.androidaps.MainApp; @@ -37,6 +38,10 @@ public class LabelWithElement extends Element { textViewPre.setTypeface(textViewPre.getTypeface(), Typeface.BOLD); layout.addView(textViewPre); + TextView spacer = new TextView(root.getContext()); + spacer.setLayoutParams(new TableLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1f)); + layout.addView(spacer); + // add element to layout element.addToLayout(layout); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java index e1792d8bd3..0ad9f75ab2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerBolusAgo.java @@ -11,8 +11,6 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.DecimalFormat; - import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.logging.L; @@ -28,9 +26,7 @@ import info.nightscout.androidaps.utils.T; public class TriggerBolusAgo extends Trigger { private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); - private final double step = 1; - private DecimalFormat decimalFormat = new DecimalFormat("1"); - public InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES); + private InputDuration minutesAgo = new InputDuration(0, InputDuration.TimeUnit.MINUTES); private Comparator comparator = new Comparator(); public TriggerBolusAgo() { @@ -39,7 +35,7 @@ public class TriggerBolusAgo extends Trigger { private TriggerBolusAgo(TriggerBolusAgo triggerBolusAgo) { super(); - minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo.getMinutes(), InputDuration.TimeUnit.MINUTES); + minutesAgo = new InputDuration(triggerBolusAgo.minutesAgo); lastRun = triggerBolusAgo.lastRun; comparator = new Comparator(triggerBolusAgo.comparator); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java index a794851236..4ddeb4299a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerCOB.java @@ -32,10 +32,8 @@ import info.nightscout.androidaps.utils.T; public class TriggerCOB extends Trigger { private static Logger log = LoggerFactory.getLogger(L.AUTOMATION); private final int minValue = 0; - private final int maxValue = (int) (SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48)); - private final double step = 1; - private DecimalFormat decimalFormat = new DecimalFormat("1"); - private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, step, decimalFormat); + private final int maxValue = SP.getInt(R.string.key_treatmentssafety_maxcarbs, 48); + private InputDouble value = new InputDouble(0, (double) minValue, (double) maxValue, 1, new DecimalFormat("1")); private Comparator comparator = new Comparator(); public TriggerCOB() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java index 0b9edf148a..a3939a60b7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerDelta.java @@ -51,10 +51,11 @@ public class TriggerDelta extends Trigger { private TriggerDelta(TriggerDelta triggerDelta) { super(); - this.units = ProfileFunctions.getInstance().getProfileUnits(); - initializer(); - value = triggerDelta.value; lastRun = triggerDelta.lastRun; + this.units = triggerDelta.units; + deltaType = triggerDelta.deltaType; + value = new InputDelta(triggerDelta.value); + comparator = new Comparator(triggerDelta.comparator); } public double getValue() { @@ -68,7 +69,7 @@ public class TriggerDelta extends Trigger { if (units.equals(Constants.MMOL)) value = new InputDelta(0, -MMOL_MAX, MMOL_MAX, 0.1d, new DecimalFormat("0.1"), DeltaType.DELTA); else - value = new InputDelta(0, -MGDL_MAX, MGDL_MAX, 0.1d, new DecimalFormat("1"), DeltaType.DELTA); + value = new InputDelta(0, -MGDL_MAX, MGDL_MAX, 1d, new DecimalFormat("1"), DeltaType.DELTA); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java index d2be0ffa1f..4772d29112 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerLocation.java @@ -51,10 +51,11 @@ public class TriggerLocation extends Trigger { private TriggerLocation(TriggerLocation triggerLocation) { super(); - latitude = new InputDouble(triggerLocation.latitude.getValue(), -90d, +90d, 0.00001d, new DecimalFormat("0.00000")); - longitude = new InputDouble(triggerLocation.longitude.getValue(), -180d, +180d, 0.00001d, new DecimalFormat("0.00000")); - distance = new InputDouble(200d, 0, 100000, 10d, new DecimalFormat("0")); + latitude = new InputDouble(triggerLocation.latitude); + longitude = new InputDouble(triggerLocation.longitude); + distance = new InputDouble(triggerLocation.distance); lastRun = triggerLocation.lastRun; + name = triggerLocation.name; } @Override diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java index e520ef38d6..84094095d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/automation/triggers/TriggerWifiSsid.java @@ -65,7 +65,7 @@ public class TriggerWifiSsid extends Trigger { return true; } - boolean doRun = eventNetworkChange.wifiConnected && comparator.getValue().check(eventNetworkChange.ssid, getValue()); + boolean doRun = eventNetworkChange.wifiConnected && comparator.getValue().check(eventNetworkChange.getSsid(), getValue()); if (doRun) { if (L.isEnabled(L.AUTOMATION)) log.debug("Ready for execution: " + friendlyDescription()); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java index ab98682fb4..c7f6e1bf64 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/CareportalFragment.java @@ -22,12 +22,16 @@ import info.nightscout.androidaps.R; import info.nightscout.androidaps.data.ProfileStore; import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.events.EventCareportalEventChange; +import info.nightscout.androidaps.interfaces.PumpInterface; import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatmentDialog; import info.nightscout.androidaps.plugins.common.SubscriberFragment; import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.general.overview.OverviewFragment; +import info.nightscout.androidaps.utils.DecimalFormatter; import info.nightscout.androidaps.utils.FabricPrivacy; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.SetWarnColor; public class CareportalFragment extends SubscriberFragment implements View.OnClickListener { private static Logger log = LoggerFactory.getLogger(CareportalFragment.class); @@ -91,15 +95,15 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli view.findViewById(R.id.careportal_openapsoffline).setOnClickListener(this); view.findViewById(R.id.careportal_temporarytarget).setOnClickListener(this); - iage = (TextView) view.findViewById(R.id.careportal_insulinage); - cage = (TextView) view.findViewById(R.id.careportal_canulaage); - sage = (TextView) view.findViewById(R.id.careportal_sensorage); - pbage = (TextView) view.findViewById(R.id.careportal_pbage); + iage = view.findViewById(R.id.careportal_insulinage); + cage = view.findViewById(R.id.careportal_canulaage); + sage = view.findViewById(R.id.careportal_sensorage); + pbage = view.findViewById(R.id.careportal_pbage); statsLayout = view.findViewById(R.id.careportal_stats); noProfileView = view.findViewById(R.id.profileview_noprofile); - butonsLayout = (LinearLayout) view.findViewById(R.id.careportal_buttons); + butonsLayout = view.findViewById(R.id.careportal_buttons); ProfileStore profileStore = ConfigBuilderPlugin.getPlugin().getActiveProfileInterface() != null ? ConfigBuilderPlugin.getPlugin().getActiveProfileInterface().getProfile() : null; if (profileStore == null) { @@ -249,13 +253,17 @@ public class CareportalFragment extends SubscriberFragment implements View.OnCli } private static TextView handleAge(final TextView age, String eventType, double warnThreshold, double urgentThreshold) { - String notavailable = OverviewFragment.shorttextmode ? "-" : MainApp.gs(R.string.notavailable); + return handleAge(age, "", eventType, warnThreshold, urgentThreshold, OverviewFragment.shorttextmode); + } + + public static TextView handleAge(final TextView age, String prefix, String eventType, double warnThreshold, double urgentThreshold, boolean useShortText) { + String notavailable = useShortText ? "-" : MainApp.gs(R.string.notavailable); if (age != null) { CareportalEvent careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(eventType); if (careportalEvent != null) { age.setTextColor(CareportalFragment.determineTextColor(careportalEvent, warnThreshold, urgentThreshold)); - age.setText(careportalEvent.age()); + age.setText(prefix + careportalEvent.age(useShortText)); } else { age.setText(notavailable); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java index 3489180d9d..7c50cdc7e5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/careportal/Dialogs/NewNSTreatmentDialog.java @@ -741,6 +741,8 @@ public class NewNSTreatmentDialog extends DialogFragment implements View.OnClick } TreatmentsPlugin.getPlugin().addToHistoryTempTarget(tempTarget); } + if (duration == 10) + SP.putBoolean(R.string.key_objectiveusetemptarget, true); } else { if (JsonHelper.safeGetString(data, "eventType").equals(CareportalEvent.PROFILESWITCH)) { ProfileSwitch profileSwitch = ProfileFunctions.prepareProfileSwitch( diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java index 78830aae0e..ea7a8c34bd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/data/NSDeviceStatus.java @@ -17,10 +17,9 @@ import java.util.Map; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; -import info.nightscout.androidaps.plugins.aps.loop.APSResult; import info.nightscout.androidaps.logging.BundleLogger; +import info.nightscout.androidaps.logging.L; +import info.nightscout.androidaps.plugins.aps.loop.APSResult; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.Round; import info.nightscout.androidaps.utils.SP; @@ -108,8 +107,7 @@ public class NSDeviceStatus { setData(devicestatusJson); if (devicestatusJson.has("pump")) { // Objectives 0 - ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true); } } if (bundle.containsKey("devicestatuses")) { @@ -120,8 +118,7 @@ public class NSDeviceStatus { setData(devicestatusJson); if (devicestatusJson.has("pump")) { // Objectives 0 - ObjectivesPlugin.getPlugin().pumpStatusIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivespumpStatusIsAvailableInNS, true); } } } 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 41c0611ce4..93f499c8ca 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 @@ -4,8 +4,6 @@ import android.annotation.SuppressLint; import android.app.Activity; import android.app.NotificationManager; -import androidx.arch.core.util.Function; - import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; @@ -60,7 +58,6 @@ import info.nightscout.androidaps.data.IobTotal; import info.nightscout.androidaps.data.Profile; import info.nightscout.androidaps.data.QuickWizardEntry; import info.nightscout.androidaps.db.BgReading; -import info.nightscout.androidaps.db.CareportalEvent; import info.nightscout.androidaps.db.DatabaseHelper; import info.nightscout.androidaps.db.ExtendedBolus; import info.nightscout.androidaps.db.Source; @@ -92,7 +89,6 @@ import info.nightscout.androidaps.plugins.general.careportal.Dialogs.NewNSTreatm import info.nightscout.androidaps.plugins.general.careportal.OptionsToShow; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.general.nsclient.data.NSDeviceStatus; -import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; import info.nightscout.androidaps.plugins.general.overview.activities.QuickWizardListActivity; import info.nightscout.androidaps.plugins.general.overview.dialogs.CalibrationDialog; import info.nightscout.androidaps.plugins.general.overview.dialogs.NewCarbsDialog; @@ -258,17 +254,17 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, apsModeView = (TextView) view.findViewById(R.id.overview_apsmode); tempTargetView = (TextView) view.findViewById(R.id.overview_temptarget); - iage = (TextView) view.findViewById(R.id.careportal_insulinage); - cage = (TextView) view.findViewById(R.id.careportal_canulaage); - sage = (TextView) view.findViewById(R.id.careportal_sensorage); - pbage = (TextView) view.findViewById(R.id.careportal_pbage); + iage = view.findViewById(R.id.careportal_insulinage); + cage = view.findViewById(R.id.careportal_canulaage); + sage = view.findViewById(R.id.careportal_sensorage); + pbage = view.findViewById(R.id.careportal_pbage); - iageView = (TextView) view.findViewById(R.id.overview_insulinage); - cageView = (TextView) view.findViewById(R.id.overview_canulaage); - reservoirView = (TextView) view.findViewById(R.id.overview_reservoirlevel); - sageView = (TextView) view.findViewById(R.id.overview_sensorage); - batteryView = (TextView) view.findViewById(R.id.overview_batterylevel); - statuslightsLayout = (LinearLayout) view.findViewById(R.id.overview_statuslights); + iageView = view.findViewById(R.id.overview_insulinage); + cageView = view.findViewById(R.id.overview_canulaage); + reservoirView = view.findViewById(R.id.overview_reservoirlevel); + sageView = view.findViewById(R.id.overview_sensorage); + batteryView = view.findViewById(R.id.overview_batterylevel); + statuslightsLayout = view.findViewById(R.id.overview_statuslights); bgGraph = (GraphView) view.findViewById(R.id.overview_bggraph); iobGraph = (GraphView) view.findViewById(R.id.overview_iobgraph); @@ -334,6 +330,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, rangeToDisplay = rangeToDisplay > 24 ? 6 : rangeToDisplay; SP.putInt(R.string.key_rangetodisplay, rangeToDisplay); updateGUI("rangeChange"); + SP.putBoolean(R.string.key_objectiveusescale, true); return false; }); @@ -592,6 +589,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, } } }); + SP.putBoolean(R.string.key_objectiveusereconnect, true); NSUpload.uploadOpenAPSOffline(0); return true; } else if (item.getTitle().equals(MainApp.gs(R.string.suspendloopfor1h))) { @@ -620,6 +618,7 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, return true; } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor1h))) { LoopPlugin.getPlugin().disconnectPump(60, profile); + SP.putBoolean(R.string.key_objectiveusedisconnect, true); updateGUI("suspendmenu"); return true; } else if (item.getTitle().equals(MainApp.gs(R.string.disconnectpumpfor2h))) { @@ -1324,55 +1323,19 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, cobView.setText(cobText); } - if (statuslightsLayout != null) { + if (statuslightsLayout != null) if (SP.getBoolean(R.string.key_show_statuslights, false)) { - CareportalEvent careportalEvent; - NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance(); - double iageUrgent = nsSettings.getExtendedWarnValue("iage", "urgent", 96); - double iageWarn = nsSettings.getExtendedWarnValue("iage", "warn", 72); - double cageUrgent = nsSettings.getExtendedWarnValue("cage", "urgent", 72); - double cageWarn = nsSettings.getExtendedWarnValue("cage", "warn", 48); - double sageUrgent = nsSettings.getExtendedWarnValue("sage", "urgent", 166); - double sageWarn = nsSettings.getExtendedWarnValue("sage", "warn", 164); - //double pbageUrgent = nsSettings.getExtendedWarnValue("pgage", "urgent", 360); - //double pbageWarn = nsSettings.getExtendedWarnValue("pgage", "warn", 240); - double batUrgent = SP.getDouble(R.string.key_statuslights_bat_critical, 5.0); - double batWarn = SP.getDouble(R.string.key_statuslights_bat_warning, 25.0); - double resUrgent = SP.getDouble(R.string.key_statuslights_res_critical, 10.0); - double resWarn = SP.getDouble(R.string.key_statuslights_res_warning, 80.0); - - if (cageView != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SITECHANGE); - double canAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE; - applyStatuslight(cageView, "CAN", canAge, cageWarn, cageUrgent, Double.MAX_VALUE, true); + StatuslightHandler handler = new StatuslightHandler(); + if (SP.getBoolean(R.string.key_show_statuslights_extended, false)) { + handler.extendedStatuslight(cageView, iageView, reservoirView, sageView, batteryView); + statuslightsLayout.setVisibility(View.VISIBLE); + } else { + handler.statuslight(cageView, iageView, reservoirView, sageView, batteryView); + statuslightsLayout.setVisibility(View.VISIBLE); } - - if (iageView != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.INSULINCHANGE); - double insulinAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE; - applyStatuslight(iageView, "INS", insulinAge, iageWarn, iageUrgent, Double.MAX_VALUE, true); - } - - if (reservoirView != null) { - double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1; - applyStatuslight(reservoirView, "RES", reservoirLevel, resWarn, resUrgent, -1, false); - } - - if (sageView != null) { - careportalEvent = MainApp.getDbHelper().getLastCareportalEvent(CareportalEvent.SENSORCHANGE); - double sensorAge = careportalEvent != null ? careportalEvent.getHoursFromStart() : Double.MAX_VALUE; - applyStatuslight(sageView, "SEN", sensorAge, sageWarn, sageUrgent, Double.MAX_VALUE, true); - } - - if (batteryView != null) { - double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1; - applyStatuslight(batteryView, "BAT", batteryLevel, batWarn, batUrgent, -1, false); - } - statuslightsLayout.setVisibility(View.VISIBLE); } else { statuslightsLayout.setVisibility(View.GONE); } - } boolean predictionsAvailable; if (Config.APS) @@ -1559,21 +1522,5 @@ public class OverviewFragment extends Fragment implements View.OnClickListener, Profiler.log(log, from, updateGUIStart); } - public static void applyStatuslight(TextView view, String text, double value, double warnThreshold, double urgentThreshold, double invalid, boolean checkAscending) { - Function check = checkAscending ? (Double threshold) -> value >= threshold : (Double threshold) -> value <= threshold; - if (value != invalid) { - view.setText(text); - if (check.apply(urgentThreshold)) { - view.setTextColor(MainApp.gc(R.color.ribbonCritical)); - } else if (check.apply(warnThreshold)) { - view.setTextColor(MainApp.gc(R.color.ribbonWarning)); - } else { - view.setTextColor(MainApp.gc(R.color.ribbonDefault)); - } - view.setVisibility(View.VISIBLE); - } else { - view.setVisibility(View.GONE); - } - } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatuslightHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatuslightHandler.java new file mode 100644 index 0000000000..23c3fd2cec --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/StatuslightHandler.java @@ -0,0 +1,135 @@ +package info.nightscout.androidaps.plugins.general.overview; + +import android.view.View; +import android.widget.TextView; + +import androidx.arch.core.util.Function; + +import info.nightscout.androidaps.MainApp; +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.db.CareportalEvent; +import info.nightscout.androidaps.interfaces.PumpInterface; +import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin; +import info.nightscout.androidaps.plugins.general.careportal.CareportalFragment; +import info.nightscout.androidaps.plugins.general.nsclient.data.NSSettingsStatus; +import info.nightscout.androidaps.utils.DecimalFormatter; +import info.nightscout.androidaps.utils.SP; +import info.nightscout.androidaps.utils.SetWarnColor; + +class StatuslightHandler { + + /** + * applies the statuslight subview on the overview fragement + */ + void statuslight(TextView cageView, TextView iageView, TextView reservoirView, + TextView sageView, TextView batteryView) { + PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); + + applyStatuslight("cage", CareportalEvent.SITECHANGE, cageView, "CAN", 48, 72); + applyStatuslight("iage", CareportalEvent.INSULINCHANGE, iageView, "INS", 72, 96); + + double reservoirLevel = pump.isInitialized() ? pump.getReservoirLevel() : -1; + applyStatuslightLevel(R.string.key_statuslights_res_critical, 10.0, + R.string.key_statuslights_res_warning, 80.0, reservoirView, "RES", reservoirLevel); + + applyStatuslight("sage", CareportalEvent.SENSORCHANGE, sageView, "SEN", 164, 166); + + double batteryLevel = pump.isInitialized() ? pump.getBatteryLevel() : -1; + applyStatuslightLevel(R.string.key_statuslights_bat_critical, 5.0, + R.string.key_statuslights_bat_warning, 22.0, + batteryView, "BAT", batteryLevel); + + } + + void applyStatuslight(String nsSettingPlugin, String eventName, TextView view, String text, + int defaultWarnThreshold, int defaultUrgentThreshold) { + NSSettingsStatus nsSettings = NSSettingsStatus.getInstance(); + + if (view != null) { + double urgent = nsSettings.getExtendedWarnValue(nsSettingPlugin, "urgent", defaultUrgentThreshold); + double warn = nsSettings.getExtendedWarnValue(nsSettingPlugin, "warn", defaultWarnThreshold); + CareportalEvent event = MainApp.getDbHelper().getLastCareportalEvent(eventName); + double age = event != null ? event.getHoursFromStart() : Double.MAX_VALUE; + applyStatuslight(view, text, age, warn, urgent, Double.MAX_VALUE, true); + } + } + + void applyStatuslightLevel(int criticalSetting, double criticalDefaultValue, + int warnSetting, double warnDefaultValue, + TextView view, String text, double level) { + if (view != null) { + double resUrgent = SP.getDouble(criticalSetting, criticalDefaultValue); + double resWarn = SP.getDouble(warnSetting, warnDefaultValue); + applyStatuslight(view, text, level, resWarn, resUrgent, -1, false); + } + } + + void applyStatuslight(TextView view, String text, double value, double warnThreshold, + double urgentThreshold, double invalid, boolean checkAscending) { + Function check = checkAscending ? (Double threshold) -> value >= threshold : + (Double threshold) -> value <= threshold; + if (value != invalid) { + view.setText(text); + if (check.apply(urgentThreshold)) { + view.setTextColor(MainApp.gc(R.color.ribbonCritical)); + } else if (check.apply(warnThreshold)) { + view.setTextColor(MainApp.gc(R.color.ribbonWarning)); + } else { + view.setTextColor(MainApp.gc(R.color.ribbonDefault)); + } + view.setVisibility(View.VISIBLE); + } else { + view.setVisibility(View.GONE); + } + + } + + /** + * applies the extended statuslight subview on the overview fragement + */ + void extendedStatuslight(TextView cageView, TextView iageView, + TextView reservoirView, TextView sageView, + TextView batteryView) { + PumpInterface pump = ConfigBuilderPlugin.getPlugin().getActivePump(); + + handleAge("cage", CareportalEvent.SITECHANGE, cageView, "CAN ", + 48, 72); + + handleAge("iage", CareportalEvent.INSULINCHANGE, iageView, "INS ", + 72, 96); + + handleLevel(R.string.key_statuslights_res_critical, 10.0, + R.string.key_statuslights_res_warning, 80.0, + reservoirView, "RES ", pump.getReservoirLevel()); + + handleAge("sage", CareportalEvent.SENSORCHANGE, sageView, "SEN ", + 164, 166); + + handleLevel(R.string.key_statuslights_bat_critical, 26.0, + R.string.key_statuslights_bat_warning, 51.0, + batteryView, "BAT ", pump.getBatteryLevel()); + } + + void handleAge(String nsSettingPlugin, String eventName, TextView view, String text, + int defaultUrgentThreshold, int defaultWarnThreshold) { + NSSettingsStatus nsSettings = new NSSettingsStatus().getInstance(); + + if (view != null) { + double urgent = nsSettings.getExtendedWarnValue(nsSettingPlugin, "urgent", defaultUrgentThreshold); + double warn = nsSettings.getExtendedWarnValue(nsSettingPlugin, "warn", defaultWarnThreshold); + CareportalFragment.handleAge(view, text, eventName, warn, urgent, true); + } + } + + void handleLevel(int criticalSetting, double criticalDefaultValue, + int warnSetting, double warnDefaultValue, + TextView view, String text, double level) { + if (view != null) { + double resUrgent = SP.getDouble(criticalSetting, criticalDefaultValue); + double resWarn = SP.getDouble(warnSetting, warnDefaultValue); + view.setText(text + DecimalFormatter.to0Decimal(level)); + SetWarnColor.setColorInverse(view, level, resWarn, resUrgent); + } + } + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt index 1b54b0c69c..3d64345650 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/overview/dialogs/WizardDialog.kt @@ -107,6 +107,7 @@ class WizardDialog : DialogFragment() { ?: 0.0, -60.0, 60.0, 5.0, DecimalFormat("0"), false, ok, textWatcher) initDialog() + treatments_wizard_percent_used.text = SP.getInt(R.string.key_boluswizard_percentage, 100).toString() + "%" // ok button ok.setOnClickListener { if (okClicked) { @@ -128,6 +129,7 @@ class WizardDialog : DialogFragment() { treatments_wizard_basaliobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } treatments_wizard_bolusiobcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } treatments_wizard_bgtrendcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } + treatments_wizard_sbcheckbox.setOnCheckedChangeListener { buttonView, _ -> onCheckedChanged(buttonView) } // profile spinner treatments_wizard_profile.onItemSelectedListener = object : OnItemSelectedListener { override fun onNothingSelected(parent: AdapterView<*>?) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/DoseStepSize.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/DoseStepSize.java index c22f73ab3d..86a67ffc3d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/DoseStepSize.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/DoseStepSize.java @@ -4,8 +4,7 @@ package info.nightscout.androidaps.plugins.pump.common.defs; * Created by andy on 02/05/2018. */ -public enum DoseStepSize -{ +public enum DoseStepSize { ComboBasal( // new DoseStepSizeEntry(0f, 1f, 0.01f), // @@ -26,28 +25,25 @@ public enum DoseStepSize new DoseStepSizeEntry(0f, 1f, 0.025f), // new DoseStepSizeEntry(1f, 10f, 0.05f), // new DoseStepSizeEntry(10f, Double.MAX_VALUE, 0.1f)), // - ; DoseStepSizeEntry[] entries; - DoseStepSize(DoseStepSizeEntry...entries) - { + DoseStepSize(DoseStepSizeEntry... entries) { this.entries = entries; } - public double getStepSizeForAmount(double amount) - { + public double getStepSizeForAmount(double amount) { for (DoseStepSizeEntry entry : entries) { if (entry.from <= amount && entry.to > amount) return entry.value; } // should never come to this - return entries[entries.length-1].value; + return entries[entries.length - 1].value; } @@ -61,12 +57,9 @@ public enum DoseStepSize sb.append(entry.from); sb.append("-"); - if (entry.to == Double.MAX_VALUE) - { + if (entry.to == Double.MAX_VALUE) { sb.append("~}"); - } - else - { + } else { sb.append(entry.to); sb.append("}, "); } @@ -76,15 +69,13 @@ public enum DoseStepSize } - static class DoseStepSizeEntry - { + static class DoseStepSizeEntry { double from; double to; double value; // to = this value is not included, but would actually mean <, so for rates between 0.025-0.975 u/h, we would have [from=0, to=10] - DoseStepSizeEntry(double from, double to, double value) - { + DoseStepSizeEntry(double from, double to, double value) { this.from = from; this.to = to; this.value = value; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java index 601826893d..61cc3d2bc7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/AbstractDanaRPlugin.java @@ -481,7 +481,6 @@ public abstract class AbstractDanaRPlugin extends PluginBase implements PumpInte if (!veryShort) { ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; } - ret += "IOB: " + pump.iob + "U\n"; ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java index c8141d1265..782ec42eed 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/SerialIOThread.java @@ -12,7 +12,7 @@ import java.io.OutputStream; import info.nightscout.androidaps.logging.L; import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTable; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTableBase; import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractSerialIOThread; import info.nightscout.androidaps.utils.CRC; @@ -30,9 +30,11 @@ public class SerialIOThread extends AbstractSerialIOThread { private byte[] mReadBuff = new byte[0]; private MessageBase processedMessage; + private MessageHashTableBase hashTable; - public SerialIOThread(BluetoothSocket rfcommSocket) { + public SerialIOThread(BluetoothSocket rfcommSocket, MessageHashTableBase hashTable) { super(); + this.hashTable = hashTable; mRfCommSocket = rfcommSocket; try { @@ -68,11 +70,11 @@ public class SerialIOThread extends AbstractSerialIOThread { message = processedMessage; } else { // get it from hash table - message = MessageHashTable.findMessage(command); + message = hashTable.findMessage(command); } if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); + log.debug("<<<<< " + message.getMessageName() + " " + MessageBase.toHexString(extractedBuff)); // process the message content message.received = true; @@ -83,14 +85,14 @@ public class SerialIOThread extends AbstractSerialIOThread { } } } catch (Exception e) { - if (e.getMessage().indexOf("bt socket closed") < 0) + if (!e.getMessage().contains("bt socket closed")) log.error("Thread exception: ", e); mKeepRunning = false; } disconnect("EndOfLoop"); } - void appendToBuffer(byte[] newData, int gotBytes) { + private void appendToBuffer(byte[] newData, int gotBytes) { // add newData to mReadBuff byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); @@ -98,7 +100,7 @@ public class SerialIOThread extends AbstractSerialIOThread { mReadBuff = newReadBuff; } - byte[] cutMessageFromBuffer() { + private byte[] cutMessageFromBuffer() { if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { int length = (mReadBuff[2] & 0xFF) + 7; // Check if we have enough data @@ -148,7 +150,7 @@ public class SerialIOThread extends AbstractSerialIOThread { byte[] messageBytes = message.getRawMessageBytes(); if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); + log.debug(">>>>> " + message.getMessageName() + " " + MessageBase.toHexString(messageBytes)); try { mOutputStream.write(messageBytes); @@ -165,8 +167,10 @@ public class SerialIOThread extends AbstractSerialIOThread { } SystemClock.sleep(200); - if (!message.received) { - log.warn("Reply not received " + message.getMessageName()); + if (!message.isReceived()) { + message.handleMessageNotReceived(); + if (L.isEnabled(L.PUMPBTCOMM)) + log.error("Reply not received " + message.getMessageName()); if (message.getCommand() == 0xF0F1) { DanaRPump.getInstance().isNewPump = false; if (L.isEnabled(L.PUMPCOMM)) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java index 57244ecc20..bf2ca4b83b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageBase.java @@ -105,6 +105,9 @@ public class MessageBase { } } + public void handleMessageNotReceived() { + } + public int getCommand() { int command = byteFromRawBuff(buffer, 5) | (byteFromRawBuff(buffer, 4) << 8); return command; @@ -189,4 +192,8 @@ public class MessageBase { return sb.toString(); } + + public boolean isReceived() { + return received; + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTable.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTable.java deleted file mode 100644 index d7ec39f6b7..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTable.java +++ /dev/null @@ -1,82 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaR.comm; - -import java.util.HashMap; - -/** - * Created by mike on 28.05.2016. - */ -public class MessageHashTable { - public static HashMap messages = null; - - static { - if (messages == null) { - messages = new HashMap(); - put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP - put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA - put(new MsgBolusStartWithSpeed()); // 0x0104 CMD_MEALINS_START_DATA_SPEED - put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS - put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I - put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I - put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS - put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO - put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO - put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO - put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION - put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S - put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S - put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP - put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP - put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S - put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS - put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT - put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT - put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS - put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS - put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE - put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM - put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR - put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY - put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL - put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND - put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR - put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED - put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I - put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I - put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I - put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I - put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL - put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I - put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY - put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I - put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS - put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER - put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE - put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S - put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S - put(new MsgSetUserOptions()); // 0x330B CMD_SETTING_USER_OPTIONS_S - put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S - put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE - put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL - put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE - put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue()); // 0xF0F1 CMD_PUMP_CHECK_VALUE - } - } - - public static void put(MessageBase message) { - int command = message.getCommand(); - //String name = MessageOriginalNames.getName(command); - messages.put(command, message); - //log.debug(String.format("%04x ", command) + " " + name); - } - - public static MessageBase findMessage(Integer command) { - if (messages.containsKey(command)) { - return messages.get(command); - } else { - return new MessageBase(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableBase.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableBase.kt new file mode 100644 index 0000000000..9c524e02a6 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableBase.kt @@ -0,0 +1,6 @@ +package info.nightscout.androidaps.plugins.pump.danaR.comm + +interface MessageHashTableBase { + fun put(message: MessageBase) + fun findMessage(command: Int): MessageBase +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableR.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableR.kt new file mode 100644 index 0000000000..6d3129f5ba --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MessageHashTableR.kt @@ -0,0 +1,69 @@ +package info.nightscout.androidaps.plugins.pump.danaR.comm + +import java.util.* + +object MessageHashTableR : MessageHashTableBase { + var messages: HashMap = HashMap() + + init { + put(MsgBolusStop()) // 0x0101 CMD_MEALINS_STOP + put(MsgBolusStart()) // 0x0102 CMD_MEALINS_START_DATA + put(MsgBolusStartWithSpeed()) // 0x0104 CMD_MEALINS_START_DATA_SPEED + put(MsgBolusProgress()) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(MsgStatusProfile()) // 0x0204 CMD_PUMP_CALCULATION_SETTING + put(MsgStatusTempBasal()) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended()) // 0x0207 CMD_PUMP_EXPANS_INS_I + put(MsgStatusBasic()) // 0x020A CMD_PUMP_INITVIEW_I + put(MsgStatus()) // 0x020B CMD_PUMP_STATUS + put(MsgInitConnStatusTime()) // 0x0301 CMD_PUMPINIT_TIME_INFO + put(MsgInitConnStatusBolus()) // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(MsgInitConnStatusBasic()) // 0x0303 CMD_PUMPINIT_INIT_INFO + put(MsgInitConnStatusOption()) // 0x0304 CMD_PUMPINIT_OPTION + put(MsgSetTempBasalStart()) // 0x0401 CMD_PUMPSET_EXERCISE_S + put(MsgSetCarbsEntry()) // 0x0402 CMD_PUMPSET_HIS_S + put(MsgSetTempBasalStop()) // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(MsgSetExtendedBolusStop()) // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(MsgSetExtendedBolusStart()) // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(MsgError()) // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(MsgPCCommStart()) // 0x3001 CMD_CONNECT + put(MsgPCCommStop()) // 0x3002 CMD_DISCONNECT + put(MsgHistoryBolus()) // 0x3101 CMD_HISTORY_MEAL_INS + put(MsgHistoryDailyInsulin()) // 0x3102 CMD_HISTORY_DAY_INS + put(MsgHistoryGlucose()) // 0x3104 CMD_HISTORY_GLUCOSE + put(MsgHistoryAlarm()) // 0x3105 CMD_HISTORY_ALARM + put(MsgHistoryError()) // 0x3106 CMD_HISTORY_ERROR + put(MsgHistoryCarbo()) // 0x3107 CMD_HISTORY_CARBOHY + put(MsgHistoryRefill()) // 0x3108 CMD_HISTORY_REFILL + put(MsgHistorySuspend()) // 0x3109 CMD_HISTORY_SUSPEND + put(MsgHistoryBasalHour()) // 0x310A CMD_HISTORY_BASAL_HOUR + put(MsgHistoryDone()) // 0x31F1 CMD_HISTORY_DONT_USED + put(MsgSettingBasal()) // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(MsgSettingMeal()) // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(MsgSettingProfileRatios()) // 0x3204 CMD_SETTING_V_CCC_I + put(MsgSettingMaxValues()) // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(MsgSettingBasalProfileAll()) // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(MsgSettingShippingInfo()) // 0x3207 CMD_SETTING_V_SHIPPING_I + put(MsgSettingGlucose()) // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(MsgSettingPumpTime()) // 0x320A CMD_SETTING_V_TIME_I + put(MsgSettingUserOptions()) // 0x320B CMD_SETTING_V_USER_OPTIONS + put(MsgSettingActiveProfile()) // 0x320C CMD_SETTING_V_PROFILE_NUMBER + put(MsgSettingProfileRatiosAll()) // 0x320D CMD_SETTING_V_CIR_CF_VALUE + put(MsgSetSingleBasalProfile()) // 0x3302 CMD_SETTING_BASAL_INS_S + put(MsgSetBasalProfile()) // 0x3306 CMD_SETTING_BASAL_PROFILE_S + put(MsgSetUserOptions()) // 0x330B CMD_SETTING_USER_OPTIONS_S + put(MsgSetActivateBasalProfile()) // 0x330C CMD_SETTING_PROFILE_NUMBER_S + put(MsgHistoryAllDone()) // 0x41F1 CMD_HISTORY_ALL_DONE + put(MsgHistoryAll()) // 0x41F2 CMD_HISTORY_ALL + put(MsgHistoryNewDone()) // 0x42F1 CMD_HISTORY_NEW_DONE + put(MsgHistoryNew()) // 0x42F2 CMD_HISTORY_NEW + put(MsgCheckValue()) // 0xF0F1 CMD_PUMP_CHECK_VALUE + } + + override fun put(message: MessageBase) { + messages[message.command] = message + } + + override fun findMessage(command: Int): MessageBase { + return messages[command] ?: MessageBase() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java index d22352e69f..23a6ba6f75 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/comm/MsgSettingPumpTime.java @@ -34,4 +34,10 @@ public class MsgSettingPumpTime extends MessageBase { DanaRPump.getInstance().pumpTime = time; } + + @Override + public void handleMessageNotReceived() { + DanaRPump.getInstance().pumpTime = 0; + } + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java index 0f46448aee..38957fe34c 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaR/services/DanaRExecutionService.java @@ -33,6 +33,7 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; import info.nightscout.androidaps.plugins.pump.danaR.SerialIOThread; import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; +import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageHashTableR; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusProgress; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStartWithSpeed; @@ -124,7 +125,7 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { if (mSerialIOThread != null) { mSerialIOThread.disconnect("Recreate SerialIOThread"); } - mSerialIOThread = new SerialIOThread(mRfcommSocket); + mSerialIOThread = new SerialIOThread(mRfcommSocket, MessageHashTableR.INSTANCE); mHandshakeInProgress = true; MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, 0)); } @@ -186,6 +187,15 @@ public class DanaRExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(new MsgSettingUserOptions()); MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + danaRPump.lastSettingsRead = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + MainApp.bus().post(new EventInitializationChanged()); + return; + } long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; if (L.isEnabled(L.PUMP)) log.debug("Pump time difference: " + timeDiff + " seconds"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/SerialIOThread.java deleted file mode 100644 index 5c47d7c7d1..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/SerialIOThread.java +++ /dev/null @@ -1,210 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaRKorean; - -import android.bluetooth.BluetoothSocket; -import android.os.SystemClock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; -import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractSerialIOThread; -import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MessageHashTable_k; -import info.nightscout.androidaps.utils.CRC; - -/** - * Created by mike on 17.07.2016. - */ -public class SerialIOThread extends AbstractSerialIOThread { - private static Logger log = LoggerFactory.getLogger(L.PUMPBTCOMM); - - private InputStream mInputStream = null; - private OutputStream mOutputStream = null; - private BluetoothSocket mRfCommSocket; - - private boolean mKeepRunning = true; - private byte[] mReadBuff = new byte[0]; - - private MessageBase processedMessage; - - public SerialIOThread(BluetoothSocket rfcommSocket) { - super(); - - mRfCommSocket = rfcommSocket; - try { - mOutputStream = mRfCommSocket.getOutputStream(); - mInputStream = mRfCommSocket.getInputStream(); - } catch (IOException e) { - log.error("Unhandled exception", e); - } - this.start(); - } - - @Override - public final void run() { - try { - while (mKeepRunning) { - int availableBytes = mInputStream.available(); - // Ask for 1024 byte (or more if available) - byte[] newData = new byte[Math.max(1024, availableBytes)]; - int gotBytes = mInputStream.read(newData); - // When we are here there is some new data available - appendToBuffer(newData, gotBytes); - - // process all messages we already got - while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size - byte[] extractedBuff = cutMessageFromBuffer(); - if (extractedBuff == null) - break; // message is not complete in buffer (wrong packet calls disconnection) - - int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); - - MessageBase message; - if (processedMessage != null && processedMessage.getCommand() == command) { - message = processedMessage; - } else { - // get it from hash table - message = MessageHashTable_k.findMessage(command); - } - - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); - - // process the message content - message.received = true; - message.handleMessage(extractedBuff); - synchronized (message) { - message.notify(); - } - } - } - } catch (Exception e) { - if (e.getMessage().indexOf("bt socket closed") < 0) - log.error("Thread exception: ", e); - mKeepRunning = false; - } - disconnect("EndOfLoop"); - } - - void appendToBuffer(byte[] newData, int gotBytes) { - // add newData to mReadBuff - byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; - System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); - System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes); - mReadBuff = newReadBuff; - } - - byte[] cutMessageFromBuffer() { - if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { - int length = (mReadBuff[2] & 0xFF) + 7; - // Check if we have enough data - if (mReadBuff.length < length) { - return null; - } - if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) { - log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff)); - disconnect("wrong packet"); - return null; - } - - short crc = CRC.getCrc16(mReadBuff, 3, length - 7); - byte crcByte0 = (byte) (crc >> 8 & 0xFF); - byte crcByte1 = (byte) (crc & 0xFF); - - byte crcByte0received = mReadBuff[length - 4]; - byte crcByte1received = mReadBuff[length - 3]; - - if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) { - log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received)); - disconnect("crc error"); - return null; - } - // Packet is verified here. extract data - byte[] extractedBuff = new byte[length]; - System.arraycopy(mReadBuff, 0, extractedBuff, 0, length); - // remove extracted data from read buffer - byte[] unprocessedData = new byte[mReadBuff.length - length]; - System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length); - mReadBuff = unprocessedData; - return extractedBuff; - } else { - log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff)); - disconnect("Wrong beginning of packet"); - return null; - } - } - - @Override - public synchronized void sendMessage(MessageBase message) { - if (!mRfCommSocket.isConnected()) { - log.error("Socket not connected on sendMessage"); - return; - } - processedMessage = message; - - byte[] messageBytes = message.getRawMessageBytes(); - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); - - try { - mOutputStream.write(messageBytes); - } catch (Exception e) { - log.error("sendMessage write exception: ", e); - } - - synchronized (message) { - try { - message.wait(5000); - } catch (InterruptedException e) { - log.error("sendMessage InterruptedException", e); - } - } - - SystemClock.sleep(200); - if (!message.received) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.warn("Reply not received " + message.getMessageName()); - if (message.getCommand() == 0xF0F1) { - DanaRPump.getInstance().isNewPump = false; - log.error("Old firmware detected"); - } - } - } - - @Override - public void disconnect(String reason) { - mKeepRunning = false; - try { - mInputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mOutputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mRfCommSocket.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - System.runFinalization(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("Disconnected: " + reason); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTableRkorean.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTableRkorean.kt new file mode 100644 index 0000000000..ffdf9d14c5 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTableRkorean.kt @@ -0,0 +1,56 @@ +package info.nightscout.androidaps.plugins.pump.danaRKorean.comm + +import info.nightscout.androidaps.plugins.pump.danaR.comm.* +import java.util.* + +object MessageHashTableRkorean : MessageHashTableBase { + var messages: HashMap = HashMap() + + init { + put(MsgBolusStop()) // 0x0101 CMD_MEALINS_STOP + put(MsgBolusStart()) // 0x0102 CMD_MEALINS_START_DATA + put(MsgBolusProgress()) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(MsgStatusProfile()) // 0x0204 CMD_PUMP_CALCULATION_SETTING + put(MsgStatusTempBasal()) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended()) // 0x0207 CMD_PUMP_EXPANS_INS_I + put(MsgStatusBasic_k()) // 0x020A CMD_PUMP_INITVIEW_I + put(MsgStatus_k()) // 0x020B CMD_PUMP_STATUS + put(MsgInitConnStatusTime_k()) // 0x0301 CMD_PUMPINIT_TIME_INFO + put(MsgInitConnStatusBolus_k()) // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(MsgInitConnStatusBasic_k()) // 0x0303 CMD_PUMPINIT_INIT_INFO + put(MsgSetTempBasalStart()) // 0x0401 CMD_PUMPSET_EXERCISE_S + put(MsgSetCarbsEntry()) // 0x0402 CMD_PUMPSET_HIS_S + put(MsgSetTempBasalStop()) // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(MsgSetExtendedBolusStop()) // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(MsgSetExtendedBolusStart()) // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(MsgError()) // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(MsgPCCommStart()) // 0x3001 CMD_CONNECT + put(MsgPCCommStop()) // 0x3002 CMD_DISCONNECT + put(MsgHistoryBolus()) // 0x3101 CMD_HISTORY_MEAL_INS + put(MsgHistoryDailyInsulin()) // 0x3102 CMD_HISTORY_DAY_INS + put(MsgHistoryGlucose()) // 0x3104 CMD_HISTORY_GLUCOSE + put(MsgHistoryAlarm()) // 0x3105 CMD_HISTORY_ALARM + put(MsgHistoryCarbo()) // 0x3107 CMD_HISTORY_CARBOHY + put(MsgSettingBasal_k()) // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(MsgSettingMeal()) // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(MsgSettingProfileRatios()) // 0x3204 CMD_SETTING_V_CCC_I + put(MsgSettingMaxValues()) // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(MsgSettingBasalProfileAll_k()) // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(MsgSettingShippingInfo()) // 0x3207 CMD_SETTING_V_SHIPPING_I + put(MsgSettingGlucose()) // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(MsgSettingPumpTime()) // 0x320A CMD_SETTING_V_TIME_I + put(MsgSetSingleBasalProfile()) // 0x3302 CMD_SETTING_BASAL_INS_S + put(MsgHistoryAll()) // 0x41F2 CMD_HISTORY_ALL + put(MsgHistoryNewDone()) // 0x42F1 CMD_HISTORY_NEW_DONE + put(MsgHistoryNew()) // 0x42F2 CMD_HISTORY_NEW + put(MsgCheckValue_k()) // 0xF0F1 CMD_PUMP_CHECK_VALUE + } + + override fun put(message: MessageBase) { + messages[message.command] = message + } + + override fun findMessage(command: Int): MessageBase { + return messages[command] ?: MessageBase() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTable_k.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTable_k.java deleted file mode 100644 index 30ac710724..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/comm/MessageHashTable_k.java +++ /dev/null @@ -1,76 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaRKorean.comm; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.HashMap; - -import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.pump.danaR.comm.*; - -/** - * Created by mike on 28.05.2016. - */ -public class MessageHashTable_k { - private static Logger log = LoggerFactory.getLogger(MessageHashTable_k.class); - - public static HashMap messages = null; - - static { - if (messages == null) { - messages = new HashMap(); - put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP - put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA - put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS - put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - put(new MsgStatusTempBasal()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended()); // 0x0207 CMD_PUMP_EXPANS_INS_I - put(new MsgStatusBasic_k()); // 0x020A CMD_PUMP_INITVIEW_I - put(new MsgStatus_k()); // 0x020B CMD_PUMP_STATUS - put(new MsgInitConnStatusTime_k()); // 0x0301 CMD_PUMPINIT_TIME_INFO - put(new MsgInitConnStatusBolus_k()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO - put(new MsgInitConnStatusBasic_k()); // 0x0303 CMD_PUMPINIT_INIT_INFO - put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S - put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S - put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP - put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP - put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S - put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS - put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT - put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT - put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS - put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS - put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE - put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM - put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY - put(new MsgSettingBasal_k()); // 0x3202 CMD_SETTING_V_BASAL_INS_I - put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I - put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I - put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I - put(new MsgSettingBasalProfileAll_k()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL - put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I - put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY - put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I - put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S - put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL - put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE - put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue_k()); // 0xF0F1 CMD_PUMP_CHECK_VALUE - } - } - - public static void put(MessageBase message) { - int command = message.getCommand(); - //String name = MessageOriginalNames.getName(command); - messages.put(command, message); - //log.debug(String.format("%04x ", command) + " " + name); - } - - public static MessageBase findMessage(Integer command) { - if (messages.containsKey(command)) { - return messages.get(command); - } else { - return new MessageBase(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java index c61a2ab6a3..2fba40c198 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRKorean/services/DanaRKoreanExecutionService.java @@ -30,6 +30,7 @@ import info.nightscout.androidaps.plugins.general.overview.dialogs.BolusProgress import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.SerialIOThread; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusProgress; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStop; @@ -51,7 +52,7 @@ import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusBolusExtended import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusTempBasal; import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus; import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractDanaRExecutionService; -import info.nightscout.androidaps.plugins.pump.danaRKorean.SerialIOThread; +import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MessageHashTableRkorean; import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MsgCheckValue_k; import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MsgSettingBasal_k; import info.nightscout.androidaps.plugins.pump.danaRKorean.comm.MsgStatusBasic_k; @@ -129,7 +130,7 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { if (mSerialIOThread != null) { mSerialIOThread.disconnect("Recreate SerialIOThread"); } - mSerialIOThread = new SerialIOThread(mRfcommSocket); + mSerialIOThread = new SerialIOThread(mRfcommSocket, MessageHashTableRkorean.INSTANCE); mHandshakeInProgress = true; MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, 0)); } @@ -187,6 +188,15 @@ public class DanaRKoreanExecutionService extends AbstractDanaRExecutionService { mSerialIOThread.sendMessage(new MsgSettingProfileRatios()); MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + danaRPump.lastSettingsRead = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + MainApp.bus().post(new EventInitializationChanged()); + return; + } long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; if (L.isEnabled(L.PUMP)) log.debug("Pump time difference: " + timeDiff + " seconds"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java index 19005509cb..463f646cfd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/DanaRSPlugin.java @@ -794,7 +794,6 @@ public class DanaRSPlugin extends PluginBase implements PumpInterface, DanaRInte if (!veryShort) { ret += "TDD: " + DecimalFormatter.to0Decimal(pump.dailyTotalUnits) + " / " + pump.maxDailyTotalUnits + " U\n"; } - ret += "IOB: " + pump.iob + "U\n"; ret += "Reserv: " + DecimalFormatter.to0Decimal(pump.reservoirRemainingUnits) + "U\n"; ret += "Batt: " + pump.batteryRemaining + "\n"; return ret; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java index b97509b7b9..3d59b34e16 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet.java @@ -58,6 +58,9 @@ public class DanaRS_Packet { public void handleMessage(byte[] data) { } + public void handleMessageNotReceived() { + } + public String getFriendlyName() { return "UNKNOWN_PACKET"; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java index d12ed52c79..500c1707b6 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/comm/DanaRS_Packet_Option_Get_Pump_Time.java @@ -58,6 +58,11 @@ public class DanaRS_Packet_Option_Get_Pump_Time extends DanaRS_Packet { } } + @Override + public void handleMessageNotReceived() { + DanaRPump.getInstance().pumpTime = 0; + } + @Override public String getFriendlyName() { return "OPTION__GET_PUMP_TIME"; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java index 69ca9f1901..3eb3a89c79 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/BLEComm.java @@ -643,6 +643,7 @@ public class BLEComm { //SystemClock.sleep(200); if (!message.isReceived()) { log.warn("Reply not received " + message.getFriendlyName()); + message.handleMessageNotReceived(); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java index 1fbcf70dfd..9987c031b2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRS/services/DanaRSService.java @@ -158,6 +158,14 @@ public class DanaRSService extends Service { bleComm.sendMessage(new DanaRS_Packet_Option_Get_Pump_Time()); long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + MainApp.bus().post(new EventInitializationChanged()); + return; + } if (L.isEnabled(L.PUMPCOMM)) log.debug("Pump time difference: " + timeDiff + " seconds"); if (Math.abs(timeDiff) > 3) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/SerialIOThread.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/SerialIOThread.java deleted file mode 100644 index ba1fdc5cb2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/SerialIOThread.java +++ /dev/null @@ -1,209 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaRv2; - -import android.bluetooth.BluetoothSocket; -import android.os.SystemClock; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; -import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractSerialIOThread; -import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MessageHashTable_v2; -import info.nightscout.androidaps.utils.CRC; - -/** - * Created by mike on 17.07.2016. - */ -public class SerialIOThread extends AbstractSerialIOThread { - private static Logger log = LoggerFactory.getLogger(L.PUMPBTCOMM); - - private InputStream mInputStream = null; - private OutputStream mOutputStream = null; - private BluetoothSocket mRfCommSocket; - - private boolean mKeepRunning = true; - private byte[] mReadBuff = new byte[0]; - - private MessageBase processedMessage; - - public SerialIOThread(BluetoothSocket rfcommSocket) { - super(); - - mRfCommSocket = rfcommSocket; - try { - mOutputStream = mRfCommSocket.getOutputStream(); - mInputStream = mRfCommSocket.getInputStream(); - } catch (IOException e) { - log.error("Unhandled exception", e); - } - this.start(); - } - - @Override - public final void run() { - try { - while (mKeepRunning) { - int availableBytes = mInputStream.available(); - // Ask for 1024 byte (or more if available) - byte[] newData = new byte[Math.max(1024, availableBytes)]; - int gotBytes = mInputStream.read(newData); - // When we are here there is some new data available - appendToBuffer(newData, gotBytes); - - // process all messages we already got - while (mReadBuff.length > 3) { // 3rd byte is packet size. continue only if we an determine packet size - byte[] extractedBuff = cutMessageFromBuffer(); - if (extractedBuff == null) - break; // message is not complete in buffer (wrong packet calls disconnection) - - int command = (extractedBuff[5] & 0xFF) | ((extractedBuff[4] << 8) & 0xFF00); - - MessageBase message; - if (processedMessage != null && processedMessage.getCommand() == command) { - message = processedMessage; - } else { - // get it from hash table - message = MessageHashTable_v2.findMessage(command); - } - - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("<<<<< " + message.getMessageName() + " " + message.toHexString(extractedBuff)); - - // process the message content - message.received = true; - message.handleMessage(extractedBuff); - synchronized (message) { - message.notify(); - } - } - } - } catch (Exception e) { - if (e.getMessage().indexOf("bt socket closed") < 0) - log.error("Thread exception: ", e); - mKeepRunning = false; - } - disconnect("EndOfLoop"); - } - - void appendToBuffer(byte[] newData, int gotBytes) { - // add newData to mReadBuff - byte[] newReadBuff = new byte[mReadBuff.length + gotBytes]; - System.arraycopy(mReadBuff, 0, newReadBuff, 0, mReadBuff.length); - System.arraycopy(newData, 0, newReadBuff, mReadBuff.length, gotBytes); - mReadBuff = newReadBuff; - } - - byte[] cutMessageFromBuffer() { - if (mReadBuff[0] == (byte) 0x7E && mReadBuff[1] == (byte) 0x7E) { - int length = (mReadBuff[2] & 0xFF) + 7; - // Check if we have enough data - if (mReadBuff.length < length) { - return null; - } - if (mReadBuff[length - 2] != (byte) 0x2E || mReadBuff[length - 1] != (byte) 0x2E) { - log.error("wrong packet lenght=" + length + " data " + MessageBase.toHexString(mReadBuff)); - disconnect("wrong packet"); - return null; - } - - short crc = CRC.getCrc16(mReadBuff, 3, length - 7); - byte crcByte0 = (byte) (crc >> 8 & 0xFF); - byte crcByte1 = (byte) (crc & 0xFF); - - byte crcByte0received = mReadBuff[length - 4]; - byte crcByte1received = mReadBuff[length - 3]; - - if (crcByte0 != crcByte0received || crcByte1 != crcByte1received) { - log.error("CRC Error" + String.format("%02x ", crcByte0) + String.format("%02x ", crcByte1) + String.format("%02x ", crcByte0received) + String.format("%02x ", crcByte1received)); - disconnect("crc error"); - return null; - } - // Packet is verified here. extract data - byte[] extractedBuff = new byte[length]; - System.arraycopy(mReadBuff, 0, extractedBuff, 0, length); - // remove extracted data from read buffer - byte[] unprocessedData = new byte[mReadBuff.length - length]; - System.arraycopy(mReadBuff, length, unprocessedData, 0, unprocessedData.length); - mReadBuff = unprocessedData; - return extractedBuff; - } else { - log.error("Wrong beginning of packet len=" + mReadBuff.length + " " + MessageBase.toHexString(mReadBuff)); - disconnect("Wrong beginning of packet"); - return null; - } - } - - @Override - public synchronized void sendMessage(MessageBase message) { - if (!mRfCommSocket.isConnected()) { - log.error("Socket not connected on sendMessage"); - return; - } - processedMessage = message; - - byte[] messageBytes = message.getRawMessageBytes(); - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(">>>>> " + message.getMessageName() + " " + message.toHexString(messageBytes)); - - try { - mOutputStream.write(messageBytes); - } catch (Exception e) { - log.error("sendMessage write exception: ", e); - } - - synchronized (message) { - try { - message.wait(5000); - } catch (InterruptedException e) { - log.error("sendMessage InterruptedException", e); - } - } - - SystemClock.sleep(200); - if (!message.received) { - log.error("Reply not received " + message.getMessageName()); - if (message.getCommand() == 0xF0F1) { - DanaRPump.getInstance().isNewPump = false; - log.error("Old firmware detected"); - } - } - } - - @Override - public void disconnect(String reason) { - mKeepRunning = false; - try { - mInputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mOutputStream.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - mRfCommSocket.close(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - try { - System.runFinalization(); - } catch (Exception e) { - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug(e.getMessage()); - } - if (L.isEnabled(L.PUMPBTCOMM)) - log.debug("Disconnected: " + reason); - } - -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTableRv2.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTableRv2.kt new file mode 100644 index 0000000000..f22a3cf3fa --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTableRv2.kt @@ -0,0 +1,77 @@ +package info.nightscout.androidaps.plugins.pump.danaRv2.comm + +import info.nightscout.androidaps.plugins.pump.danaR.comm.* +import java.util.* + + +object MessageHashTableRv2 : MessageHashTableBase { + var messages: HashMap = HashMap() + + init { + put(MsgBolusStop()) // 0x0101 CMD_MEALINS_STOP + put(MsgBolusStart()) // 0x0102 CMD_MEALINS_START_DATA + put(MsgBolusStartWithSpeed()) // 0x0104 CMD_MEALINS_START_DATA_SPEED + put(MsgBolusProgress()) // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS + put(MsgStatusProfile()) // 0x0204 CMD_PUMP_CALCULATION_SETTING + + put(MsgStatusTempBasal_v2()) // 0x0205 CMD_PUMP_EXERCISE_MODE + put(MsgStatusBolusExtended_v2()) // 0x0207 CMD_PUMP_EXPANS_INS_I + + put(MsgStatusBasic()) // 0x020A CMD_PUMP_INITVIEW_I + put(MsgStatus()) // 0x020B CMD_PUMP_STATUS + put(MsgInitConnStatusTime()) // 0x0301 CMD_PUMPINIT_TIME_INFO + put(MsgInitConnStatusBolus()) // 0x0302 CMD_PUMPINIT_BOLUS_INFO + put(MsgInitConnStatusBasic()) // 0x0303 CMD_PUMPINIT_INIT_INFO + put(MsgInitConnStatusOption()) // 0x0304 CMD_PUMPINIT_OPTION + put(MsgSetTempBasalStart()) // 0x0401 CMD_PUMPSET_EXERCISE_S + put(MsgSetCarbsEntry()) // 0x0402 CMD_PUMPSET_HIS_S + put(MsgSetTempBasalStop()) // 0x0403 CMD_PUMPSET_EXERCISE_STOP + put(MsgSetExtendedBolusStop()) // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP + put(MsgSetExtendedBolusStart()) // 0x0407 CMD_PUMPSET_EXPANS_INS_S + put(MsgError()) // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS + put(MsgPCCommStart()) // 0x3001 CMD_CONNECT + put(MsgPCCommStop()) // 0x3002 CMD_DISCONNECT + put(MsgHistoryBolus()) // 0x3101 CMD_HISTORY_MEAL_INS + put(MsgHistoryDailyInsulin()) // 0x3102 CMD_HISTORY_DAY_INS + put(MsgHistoryGlucose()) // 0x3104 CMD_HISTORY_GLUCOSE + put(MsgHistoryAlarm()) // 0x3105 CMD_HISTORY_ALARM + put(MsgHistoryError()) // 0x3106 CMD_HISTORY_ERROR + put(MsgHistoryCarbo()) // 0x3107 CMD_HISTORY_CARBOHY + put(MsgHistoryRefill()) // 0x3108 CMD_HISTORY_REFILL + put(MsgHistorySuspend()) // 0x3109 CMD_HISTORY_SUSPEND + put(MsgHistoryBasalHour()) // 0x310A CMD_HISTORY_BASAL_HOUR + put(MsgHistoryDone()) // 0x31F1 CMD_HISTORY_DONT_USED + put(MsgSettingBasal()) // 0x3202 CMD_SETTING_V_BASAL_INS_I + put(MsgSettingMeal()) // 0x3203 CMD_SETTING_V_MEAL_SETTING_I + put(MsgSettingProfileRatios()) // 0x3204 CMD_SETTING_V_CCC_I + put(MsgSettingMaxValues()) // 0x3205 CMD_SETTING_V_MAX_VALUE_I + put(MsgSettingBasalProfileAll()) // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL + put(MsgSettingShippingInfo()) // 0x3207 CMD_SETTING_V_SHIPPING_I + put(MsgSettingGlucose()) // 0x3209 CMD_SETTING_V_GLUCOSEandEASY + put(MsgSettingPumpTime()) // 0x320A CMD_SETTING_V_TIME_I + put(MsgSettingUserOptions()) // 0x320B CMD_SETTING_V_USER_OPTIONS + put(MsgSettingActiveProfile()) // 0x320C CMD_SETTING_V_PROFILE_NUMBER + put(MsgSettingProfileRatiosAll()) // 0x320D CMD_SETTING_V_CIR_CF_VALUE + put(MsgSetSingleBasalProfile()) // 0x3302 CMD_SETTING_BASAL_INS_S + put(MsgSetBasalProfile()) // 0x3306 CMD_SETTING_BASAL_PROFILE_S + put(MsgSetUserOptions()) // 0x330B CMD_SETTING_USER_OPTIONS_S + put(MsgSetActivateBasalProfile()) // 0x330C CMD_SETTING_PROFILE_NUMBER_S + put(MsgHistoryAllDone()) // 0x41F1 CMD_HISTORY_ALL_DONE + put(MsgHistoryAll()) // 0x41F2 CMD_HISTORY_ALL + put(MsgHistoryNewDone()) // 0x42F1 CMD_HISTORY_NEW_DONE + put(MsgHistoryNew()) // 0x42F2 CMD_HISTORY_NEW + put(MsgCheckValue_v2()) // 0xF0F1 CMD_PUMP_CHECK_VALUE + put(MsgStatusAPS_v2()) // 0xE001 CMD_PUMPSTATUS_APS + put(MsgSetAPSTempBasalStart_v2()) // 0xE002 CMD_PUMPSET_APSTEMP + put(MsgHistoryEvents_v2()) // 0xE003 CMD_GET_HISTORY + put(MsgSetHistoryEntry_v2()) // 0xE004 CMD_SET_HISTORY_ENTRY + } + + override fun put(message: MessageBase) { + messages[message.command] = message + } + + override fun findMessage(command: Int): MessageBase { + return messages[command] ?: MessageBase() + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTable_v2.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTable_v2.java deleted file mode 100644 index 66376290af..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/comm/MessageHashTable_v2.java +++ /dev/null @@ -1,92 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.danaRv2.comm; - -import java.util.HashMap; - -import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; -import info.nightscout.androidaps.plugins.pump.danaR.comm.*; - - -/** - * Created by mike on 28.05.2016. - */ -public class MessageHashTable_v2 { - public static HashMap messages = null; - - static { - if (messages == null) { - messages = new HashMap(); - put(new MsgBolusStop()); // 0x0101 CMD_MEALINS_STOP - put(new MsgBolusStart()); // 0x0102 CMD_MEALINS_START_DATA - put(new MsgBolusStartWithSpeed()); // 0x0104 CMD_MEALINS_START_DATA_SPEED - put(new MsgBolusProgress()); // 0x0202 CMD_PUMP_THIS_REMAINDER_MEAL_INS - put(new MsgStatusProfile()); // 0x0204 CMD_PUMP_CALCULATION_SETTING - - put(new MsgStatusTempBasal_v2()); // 0x0205 CMD_PUMP_EXERCISE_MODE - put(new MsgStatusBolusExtended_v2()); // 0x0207 CMD_PUMP_EXPANS_INS_I - - put(new MsgStatusBasic()); // 0x020A CMD_PUMP_INITVIEW_I - put(new MsgStatus()); // 0x020B CMD_PUMP_STATUS - put(new MsgInitConnStatusTime()); // 0x0301 CMD_PUMPINIT_TIME_INFO - put(new MsgInitConnStatusBolus()); // 0x0302 CMD_PUMPINIT_BOLUS_INFO - put(new MsgInitConnStatusBasic()); // 0x0303 CMD_PUMPINIT_INIT_INFO - put(new MsgInitConnStatusOption()); // 0x0304 CMD_PUMPINIT_OPTION - put(new MsgSetTempBasalStart()); // 0x0401 CMD_PUMPSET_EXERCISE_S - put(new MsgSetCarbsEntry()); // 0x0402 CMD_PUMPSET_HIS_S - put(new MsgSetTempBasalStop()); // 0x0403 CMD_PUMPSET_EXERCISE_STOP - put(new MsgSetExtendedBolusStop()); // 0x0406 CMD_PUMPSET_EXPANS_INS_STOP - put(new MsgSetExtendedBolusStart()); // 0x0407 CMD_PUMPSET_EXPANS_INS_S - put(new MsgError()); // 0x0601 CMD_PUMPOWAY_SYSTEM_STATUS - put(new MsgPCCommStart()); // 0x3001 CMD_CONNECT - put(new MsgPCCommStop()); // 0x3002 CMD_DISCONNECT - put(new MsgHistoryBolus()); // 0x3101 CMD_HISTORY_MEAL_INS - put(new MsgHistoryDailyInsulin()); // 0x3102 CMD_HISTORY_DAY_INS - put(new MsgHistoryGlucose()); // 0x3104 CMD_HISTORY_GLUCOSE - put(new MsgHistoryAlarm()); // 0x3105 CMD_HISTORY_ALARM - put(new MsgHistoryError()); // 0x3106 CMD_HISTORY_ERROR - put(new MsgHistoryCarbo()); // 0x3107 CMD_HISTORY_CARBOHY - put(new MsgHistoryRefill()); // 0x3108 CMD_HISTORY_REFILL - put(new MsgHistorySuspend()); // 0x3109 CMD_HISTORY_SUSPEND - put(new MsgHistoryBasalHour()); // 0x310A CMD_HISTORY_BASAL_HOUR - put(new MsgHistoryDone()); // 0x31F1 CMD_HISTORY_DONT_USED - put(new MsgSettingBasal()); // 0x3202 CMD_SETTING_V_BASAL_INS_I - put(new MsgSettingMeal()); // 0x3203 CMD_SETTING_V_MEAL_SETTING_I - put(new MsgSettingProfileRatios()); // 0x3204 CMD_SETTING_V_CCC_I - put(new MsgSettingMaxValues()); // 0x3205 CMD_SETTING_V_MAX_VALUE_I - put(new MsgSettingBasalProfileAll()); // 0x3206 CMD_SETTING_V_BASAL_PROFILE_ALL - put(new MsgSettingShippingInfo()); // 0x3207 CMD_SETTING_V_SHIPPING_I - put(new MsgSettingGlucose()); // 0x3209 CMD_SETTING_V_GLUCOSEandEASY - put(new MsgSettingPumpTime()); // 0x320A CMD_SETTING_V_TIME_I - put(new MsgSettingUserOptions()); // 0x320B CMD_SETTING_V_USER_OPTIONS - put(new MsgSettingActiveProfile()); // 0x320C CMD_SETTING_V_PROFILE_NUMBER - put(new MsgSettingProfileRatiosAll()); // 0x320D CMD_SETTING_V_CIR_CF_VALUE - put(new MsgSetSingleBasalProfile()); // 0x3302 CMD_SETTING_BASAL_INS_S - put(new MsgSetBasalProfile()); // 0x3306 CMD_SETTING_BASAL_PROFILE_S - put(new MsgSetUserOptions()); // 0x330B CMD_SETTING_USER_OPTIONS_S - put(new MsgSetActivateBasalProfile()); // 0x330C CMD_SETTING_PROFILE_NUMBER_S - put(new MsgHistoryAllDone()); // 0x41F1 CMD_HISTORY_ALL_DONE - put(new MsgHistoryAll()); // 0x41F2 CMD_HISTORY_ALL - put(new MsgHistoryNewDone()); // 0x42F1 CMD_HISTORY_NEW_DONE - put(new MsgHistoryNew()); // 0x42F2 CMD_HISTORY_NEW - put(new MsgCheckValue_v2()); // 0xF0F1 CMD_PUMP_CHECK_VALUE - put(new MsgStatusAPS_v2()); // 0xE001 CMD_PUMPSTATUS_APS - put(new MsgSetAPSTempBasalStart_v2()); // 0xE002 CMD_PUMPSET_APSTEMP - put(new MsgHistoryEvents_v2()); // 0xE003 CMD_GET_HISTORY - put(new MsgSetHistoryEntry_v2()); // 0xE004 CMD_SET_HISTORY_ENTRY - } - } - - public static void put(MessageBase message) { - int command = message.getCommand(); - //String name = MessageOriginalNames.getName(command); - messages.put(command, message); - //log.debug(String.format("%04x ", command) + " " + name); - } - - public static MessageBase findMessage(Integer command) { - if (messages.containsKey(command)) { - return messages.get(command); - } else { - return new MessageBase(); - } - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java index 235e7d3bd3..c6a62ae908 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/danaRv2/services/DanaRv2ExecutionService.java @@ -33,6 +33,7 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotifi import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.pump.danaR.DanaRPump; +import info.nightscout.androidaps.plugins.pump.danaR.SerialIOThread; import info.nightscout.androidaps.plugins.pump.danaR.comm.MessageBase; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusProgress; import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgBolusStart; @@ -62,7 +63,7 @@ import info.nightscout.androidaps.plugins.pump.danaR.comm.MsgStatusBasic; import info.nightscout.androidaps.plugins.pump.danaR.events.EventDanaRNewStatus; import info.nightscout.androidaps.plugins.pump.danaR.services.AbstractDanaRExecutionService; import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin; -import info.nightscout.androidaps.plugins.pump.danaRv2.SerialIOThread; +import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MessageHashTableRv2; import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgCheckValue_v2; import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgHistoryEvents_v2; import info.nightscout.androidaps.plugins.pump.danaRv2.comm.MsgSetAPSTempBasalStart_v2; @@ -147,7 +148,7 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { if (mSerialIOThread != null) { mSerialIOThread.disconnect("Recreate SerialIOThread"); } - mSerialIOThread = new SerialIOThread(mRfcommSocket); + mSerialIOThread = new SerialIOThread(mRfcommSocket, MessageHashTableRv2.INSTANCE); mHandshakeInProgress = true; MainApp.bus().post(new EventPumpStatusChanged(EventPumpStatusChanged.HANDSHAKING, 0)); } @@ -195,6 +196,15 @@ public class DanaRv2ExecutionService extends AbstractDanaRExecutionService { MainApp.bus().post(new EventPumpStatusChanged(MainApp.gs(R.string.gettingpumptime))); mSerialIOThread.sendMessage(new MsgSettingPumpTime()); + if (danaRPump.pumpTime == 0) { + // initial handshake was not successfull + // deinitialize pump + danaRPump.lastConnection = 0; + danaRPump.lastSettingsRead = 0; + RxBus.INSTANCE.send(new EventDanaRNewStatus()); + MainApp.bus().post(new EventInitializationChanged()); + return; + } long timeDiff = (danaRPump.pumpTime - System.currentTimeMillis()) / 1000L; if (L.isEnabled(L.PUMP)) log.debug("Pump time difference: " + timeDiff + " seconds"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java index ff7ff9f608..29387b0724 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.java @@ -182,6 +182,7 @@ public class MedtronicPumpStatus extends PumpStatus { } else { this.pumpType = medtronicPumpMap.get(pumpTypePart); this.medtronicDeviceType = medtronicDeviceTypeMap.get(pumpTypePart); + this.pumpDescription.setPumpDescription(this.pumpType); if (pumpTypePart.startsWith("7")) this.reservoirFullUnits = 300; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java index 328f054aad..dd0a2c5e88 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/SourceNSClientPlugin.java @@ -16,7 +16,6 @@ import info.nightscout.androidaps.interfaces.PluginBase; import info.nightscout.androidaps.interfaces.PluginDescription; import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.logging.L; -import info.nightscout.androidaps.plugins.constraints.objectives.ObjectivesPlugin; import info.nightscout.androidaps.plugins.general.nsclient.data.NSSgv; import info.nightscout.androidaps.utils.JsonHelper; import info.nightscout.androidaps.utils.SP; @@ -85,8 +84,7 @@ public class SourceNSClientPlugin extends PluginBase implements BgSourceInterfac } // Objectives 0 - ObjectivesPlugin.getPlugin().bgIsAvailableInNS = true; - ObjectivesPlugin.getPlugin().saveProgress(); + SP.putBoolean(R.string.key_ObjectivesbgIsAvailableInNS, true); } private void storeSgv(JSONObject sgvJson) { diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java index cbc0af6491..2c6902cb01 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.java @@ -425,8 +425,8 @@ public class SWDefinition { .add(new SWBreak()) .add(new SWFragment(this) .add(new ObjectivesFragment())) - .validator(() -> ObjectivesPlugin.getPlugin().objectives.get(0).isStarted()) - .visibility(() -> !ObjectivesPlugin.getPlugin().objectives.get(0).isStarted() && Config.APS); + .validator(() -> ObjectivesPlugin.INSTANCE.getObjectives().get(ObjectivesPlugin.INSTANCE.getFIRST_OBJECTIVE()).isStarted()) + .visibility(() -> !ObjectivesPlugin.INSTANCE.getObjectives().get(ObjectivesPlugin.INSTANCE.getFIRST_OBJECTIVE()).isStarted() && Config.APS); private void SWDefinitionFull() { // List all the screens here diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java index 3064228fd3..1d3b867a6d 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SetupWizardActivity.java @@ -26,7 +26,6 @@ import info.nightscout.androidaps.activities.NoSplashAppCompatActivity; import info.nightscout.androidaps.events.EventProfileNeedsUpdate; import info.nightscout.androidaps.events.EventProfileStoreChanged; import info.nightscout.androidaps.events.EventPumpStatusChanged; -import info.nightscout.androidaps.plugins.constraints.objectives.events.EventObjectivesSaved; import info.nightscout.androidaps.plugins.general.nsclient.events.EventNSClientStatus; import info.nightscout.androidaps.setupwizard.elements.SWItem; import info.nightscout.androidaps.setupwizard.events.EventSWUpdate; @@ -121,11 +120,6 @@ public class SetupWizardActivity extends NoSplashAppCompatActivity { updateButtons(); } - @Subscribe - public void onEventObjectivesSaved(EventObjectivesSaved ignored) { - updateButtons(); - } - private void generateLayout() { SWScreen currentScreen = screens.get(currentWizardPage); LinearLayout layout = SWItem.generateLayout(this.findViewById(R.id.sw_content_fields)); diff --git a/app/src/main/java/info/nightscout/androidaps/utils/SP.java b/app/src/main/java/info/nightscout/androidaps/utils/SP.java index 84b6b4b70d..1b46642751 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/SP.java +++ b/app/src/main/java/info/nightscout/androidaps/utils/SP.java @@ -126,6 +126,13 @@ public class SP { editor.apply(); } + static public void incInt(int resourceID) { + SharedPreferences.Editor editor = sharedPreferences.edit(); + int value = SP.getInt(resourceID, 0) + 1; + editor.putInt(MainApp.gs(resourceID), value); + editor.apply(); + } + static public void putString(int resourceID, String value) { SharedPreferences.Editor editor = sharedPreferences.edit(); editor.putString(MainApp.gs(resourceID), value); diff --git a/app/src/main/res/layout/objectives_exam_fragment.xml b/app/src/main/res/layout/objectives_exam_fragment.xml new file mode 100644 index 0000000000..ff906d036d --- /dev/null +++ b/app/src/main/res/layout/objectives_exam_fragment.xml @@ -0,0 +1,157 @@ + + + + + + + + + + + + + +