diff --git a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java index 701b226031..10b0b3f453 100644 --- a/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java +++ b/app/src/main/java/info/nightscout/androidaps/interfaces/PumpDescription.java @@ -37,4 +37,40 @@ public class PumpDescription { public boolean isRefillingCapable = false; public boolean storesCarbInfo = true; + + + public void resetSettings() + { + isBolusCapable = true; + bolusStep = 0.1d; + + isExtendedBolusCapable = true; + extendedBolusStep = 0.1d; + extendedBolusDurationStep = 30; + extendedBolusMaxDuration = 12 * 60; + + isTempBasalCapable = true; + tempBasalStyle = PERCENT; + + maxTempPercent = 200; + tempPercentStep = 10; + + maxTempAbsolute = 10; + tempAbsoluteStep = 0.05d; + + tempDurationStep = 60; + tempMaxDuration = 12 * 60; + + + isSetBasalProfileCapable = true; + basalStep = 0.01d; + basalMinimumRate = 0.04d; + + isRefillingCapable = false; + + storesCarbInfo = true; + + } + + } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/DoseSettings.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/DoseSettings.java new file mode 100644 index 0000000000..36ee4e5845 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/data/DoseSettings.java @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.PumpCommon.data; + +/** + * Created by andy on 02/05/2018. + */ + +public class DoseSettings { + + private float step; + private int durationStep; + private int maxDuration; + private float minDose; + private Float maxDose; + + public DoseSettings(float step, int durationStep, int maxDuration, float minDose, Float maxDose) + { + this.step = step; + this.durationStep = durationStep; + this.maxDuration = maxDuration; + this.minDose = minDose; + this.maxDose = maxDose; + } + + public DoseSettings(float step, int durationStep, int maxDuration, float minDose) + { + this(step, durationStep, maxDuration, minDose, null); + } + + + public float getStep() { + return step; + } + + public int getDurationStep() { + return durationStep; + } + + public int getMaxDuration() { + return maxDuration; + } + + public float getMinDose() { + return minDose; + } + + public Float getMaxDose() { + return maxDose; + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/DoseStepSize.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/DoseStepSize.java new file mode 100644 index 0000000000..84293a0192 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/DoseStepSize.java @@ -0,0 +1,84 @@ +package info.nightscout.androidaps.plugins.PumpCommon.defs; + +/** + * Created by andy on 02/05/2018. + */ + +public enum DoseStepSize +{ + + ComboBasal( // + new DoseStepSizeEntry(0f, 1f, 0.01f), // + new DoseStepSizeEntry(1f, 10f, 0.05f), // + new DoseStepSizeEntry(10f, Float.MAX_VALUE, 0.1f)), // + + MedtronicVeoBasal( // + new DoseStepSizeEntry(0f, 1f, 0.025f), // + new DoseStepSizeEntry(1f, 10f, 0.05f), // + new DoseStepSizeEntry(10f, Float.MAX_VALUE, 0.1f)), // + + ; + + + DoseStepSizeEntry[] entries; + + + DoseStepSize(DoseStepSizeEntry...entries) + { + this.entries = entries; + } + + + public float getStepSizeForAmount(float 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; + } + + + public String getDescription() { + StringBuilder sb = new StringBuilder(); + + for (DoseStepSizeEntry entry : entries) { + + sb.append(entry.value); + sb.append(" {"); + sb.append(entry.from); + sb.append("-"); + + if (entry.to == Float.MAX_VALUE) + { + sb.append("~}"); + } + else + { + sb.append(entry.to); + sb.append("}, "); + } + } + + return sb.toString(); + } + + + static class DoseStepSizeEntry + { + float from; + float to; + float 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(float from, float to, float value) + { + this.from = from; + this.to = to; + this.value = value; + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpTempBasalType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpTempBasalType.java new file mode 100644 index 0000000000..167e886ea7 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpTempBasalType.java @@ -0,0 +1,10 @@ +package info.nightscout.androidaps.plugins.PumpCommon.defs; + +/** + * Created by andy on 02/05/2018. + */ + +public enum PumpTempBasalType { + Percent, // + Absolute, +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java new file mode 100644 index 0000000000..eac100cf0b --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/defs/PumpType.java @@ -0,0 +1,271 @@ +package info.nightscout.androidaps.plugins.PumpCommon.defs; + + +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.plugins.PumpCommon.data.DoseSettings; + +/** + * Created by andy on 02/05/2018. + * + * Most of this defintions is intended for VirtualPump only, but they can be used by other plugins. + */ + +public enum PumpType { + + GenericAAPS("Generic AAPS", 0.1f, null, // + new DoseSettings(0.05f, 30, 8*60, 0.05f), // + PumpTempBasalType.Percent, // + new DoseSettings(10,30, 24*60, 0f, 500f), // + 0.01f, 0.01f, null), // + + // Cellnovo + + Cellnovo1("Cellnovo", 0.05f, null, // + new DoseSettings(0.05f, 30, 24*60, 1f, null), + PumpTempBasalType.Percent, + new DoseSettings(5,30, 24*60, 0f, 200f), // + 0.05f, 0.05f, null), // + + // Accu-Chek + + AccuChekCombo("Accu-Chek Combo", 0.1f, null, // + new DoseSettings(0.1f, 15, 12*60, 0.1f), // + PumpTempBasalType.Percent, + new DoseSettings(10, 15, 12*60,0f, 500f), // + 0.01f, 0.1f, DoseStepSize.ComboBasal), // + + AccuChekSpirit("Accu-Chek Spirit", AccuChekCombo), // + + + // Animas + AnimasVibe("Animas Vibe", 0.05f, null, // AnimasBolus? + new DoseSettings(0.05f, 30, 12*60, 0.05f), // + PumpTempBasalType.Percent, // + new DoseSettings(10, 30, 24*60, 0f, 200f), // + 0.025f, 5f, 0f, null), // + + AnimasPing("Animas Ping", AnimasVibe), + + // Insulet + Insulet_Omnipod("Insulet Omnipod", 0.05f, null, // + new DoseSettings(0.05f, 30, 8*60, 0.05f), // + PumpTempBasalType.Absolute, // + new DoseSettings(0.05f, 30, 12*60, 0f, 5.0f), // cannot exceed max basal rate 30u/hr + 0.05f, 0.05f, null), + + // Medtronic + Minimed_512_712("Medtronic 512/712", 0.05f, null, // + new DoseSettings(0.05f, 30, 8*60, 0.05f), // + PumpTempBasalType.Absolute, // + new DoseSettings(0.05f, 30, 24*60, 0f, 35f), // + 0.05f, 0.05f, null), // TODO + + Minimed_515_715("Medtronic 515/715", Minimed_512_712), // TODO + Minimed_522_722("Medtronic 522/722", Minimed_512_712), // TODO + Minimed_523_723("Medtronic 523/723", Minimed_512_712), // TODO + + Minimed_553_753_Revel("Medtronic 553/753 (Revel)", 0.05f, null, // + new DoseSettings(0.05f, 30, 8*60, 0.05f), // + PumpTempBasalType.Absolute, // + new DoseSettings(0.05f, 30, 24*60, 0f, 35f), // + 0.025f, 0.025f, DoseStepSize.MedtronicVeoBasal), // + + Minimed_554_754_Veo("Medtronic 554/754 (Veo)", Minimed_553_753_Revel), // TODO + + Minimed_640G("Medtronic 640G", 0.025f, null, // + new DoseSettings(0.05f, 30, 8*60, 0.05f), // + PumpTempBasalType.Absolute, // + new DoseSettings(0.05f, 30, 24*60, 0f, 35f), // + 0.025f, 0.025f, DoseStepSize.MedtronicVeoBasal), // + + // Tandem + TandemTSlim("Tandem t:slim", 0.01f, null, // + new DoseSettings(0.01f,15, 8*60, 0.4f) , + PumpTempBasalType.Percent, + new DoseSettings(1,15, 8*60, 0f, 250f), // + 0.1f, 0.001f, null), + + TandemTFlex("Tandem t:flex", TandemTSlim), // + TandemTSlimG4("Tandem t:slim G4", TandemTSlim), // + TandemTSlimX2("Tandem t:slim X2", TandemTSlim), // + ; + + private String description; + private float bolusSize; + private DoseStepSize specialBolusSize; + private DoseSettings extendedBolusSettings; + private PumpTempBasalType pumpTempBasalType; + private DoseSettings tbrSettings; + private float baseBasalMinValue; // + private float baseBasalMaxValue; + private float baseBasalStep; // + private DoseStepSize baseBasalSpecialSteps; // + + private PumpType parent; + private static Map mapByDescription; + + static + { + mapByDescription = new HashMap<>(); + + for (PumpType pumpType : values()) { + mapByDescription.put(pumpType.getDescription(), pumpType); + } + } + + + PumpType(String description, PumpType parent) + { + this.description = description; + this.parent = parent; + } + + + PumpType(String description, float bolusSize, DoseStepSize specialBolusSize, // + DoseSettings extendedBolusSettings, // + PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, // + float baseBasalMinValue, float baseBasalStep, DoseStepSize baseBasalSpecialSteps) + { + this.description = description; + this.bolusSize = bolusSize; + this.specialBolusSize = specialBolusSize; + this.extendedBolusSettings = extendedBolusSettings; + this.pumpTempBasalType = pumpTempBasalType; + this.tbrSettings = tbrSettings; + this.baseBasalMinValue = baseBasalMinValue; + this.baseBasalStep = baseBasalStep; + this.baseBasalSpecialSteps = baseBasalSpecialSteps; + } + + PumpType(String description, float bolusSize, DoseStepSize specialBolusSize, // + DoseSettings extendedBolusSettings, // + PumpTempBasalType pumpTempBasalType, DoseSettings tbrSettings, // + float baseBasalMinValue, float baseBasalMaxValue, float baseBasalStep, DoseStepSize baseBasalSpecialSteps) + { + this.description = description; + this.bolusSize = bolusSize; + this.specialBolusSize = specialBolusSize; + this.extendedBolusSettings = extendedBolusSettings; + this.pumpTempBasalType = pumpTempBasalType; + this.tbrSettings = tbrSettings; + this.baseBasalMinValue = baseBasalMinValue; + this.baseBasalMaxValue = baseBasalMaxValue; + this.baseBasalStep = baseBasalStep; + this.baseBasalSpecialSteps = baseBasalSpecialSteps; + } + + + public String getDescription() { + return description; + } + + + public float getBolusSize() { + return isParentSet() ? parent.bolusSize : bolusSize; + } + + + public DoseStepSize getSpecialBolusSize() { + return isParentSet() ? parent.specialBolusSize : specialBolusSize; + } + + + public DoseSettings getExtendedBolusSettings() { + return isParentSet() ? parent.extendedBolusSettings : extendedBolusSettings; + } + + + public PumpTempBasalType getPumpTempBasalType() { + return isParentSet() ? parent.pumpTempBasalType : pumpTempBasalType; + } + + + public DoseSettings getTbrSettings() { + return isParentSet() ? parent.tbrSettings : tbrSettings; + } + + + public float getBaseBasalMinValue() { + return isParentSet() ? parent.baseBasalMinValue : baseBasalMinValue; + } + + + public Float getBaseBasalMaxValue() { + return isParentSet() ? parent.baseBasalMaxValue : baseBasalMaxValue; + } + + + public float getBaseBasalStep() { + return isParentSet() ? parent.baseBasalStep : baseBasalStep; + } + + + public DoseStepSize getBaseBasalSpecialSteps() { + return isParentSet() ? parent.baseBasalSpecialSteps : baseBasalSpecialSteps; + } + + + public PumpType getParent() { + return parent; + } + + + private boolean isParentSet() + { + return this.parent!=null; + } + + + public static PumpType getByDescription(String desc) + { + if (mapByDescription.containsKey(desc)) + { + return mapByDescription.get(desc); + } + else + { + return PumpType.GenericAAPS; + } + } + + + public String getFullDescription(String i18nTemplate) { + + String unit = getPumpTempBasalType()==PumpTempBasalType.Percent ? "%" : ""; + + DoseSettings eb = getExtendedBolusSettings(); + DoseSettings tbr = getTbrSettings(); + + return String.format(i18nTemplate, // + getStep("" + getBolusSize(), getSpecialBolusSize()), // + eb.getStep(), eb.getDurationStep(), eb.getMaxDuration()/60, // + getStep(getBaseBasalRange(), getBaseBasalSpecialSteps()), // + tbr.getMinDose() + unit + "-" + tbr.getMaxDose() + unit, tbr.getStep() + unit, tbr.getDurationStep(), tbr.getMaxDuration()/60); + } + + + private String getBaseBasalRange() + { + Float maxValue = getBaseBasalMaxValue(); + + return maxValue==null ? "" + getBaseBasalMinValue() : getBaseBasalMinValue() + "-" + maxValue; + } + + + private String getStep(String step, DoseStepSize stepSize) + { + if (stepSize!=null) + return step + " [" + stepSize.getDescription() + "] *"; + else + return "" + step; + } + + + public boolean hasExtendedBasals() { + return ((getBaseBasalSpecialSteps() !=null) || (getSpecialBolusSize() != null)); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/PumpUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/PumpUtil.java new file mode 100644 index 0000000000..87c7f07ba4 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpCommon/utils/PumpUtil.java @@ -0,0 +1,49 @@ +package info.nightscout.androidaps.plugins.PumpCommon.utils; + +import info.nightscout.androidaps.interfaces.PumpDescription; +import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpTempBasalType; +import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; + +/** + * Created by andy on 02/05/2018. + */ + +public class PumpUtil { + + // for now used only by VirtualPump, but with small changes could be used by any constructor + public static void setPumpDescription(PumpDescription pumpDescription, PumpType pumpType) + { + pumpDescription.isBolusCapable = true; + pumpDescription.bolusStep = pumpType.getBolusSize(); + + pumpDescription.isExtendedBolusCapable = true; + pumpDescription.extendedBolusStep = pumpType.getExtendedBolusSettings().getStep(); + pumpDescription.extendedBolusDurationStep = pumpType.getExtendedBolusSettings().getDurationStep(); + pumpDescription.extendedBolusMaxDuration = pumpType.getExtendedBolusSettings().getMaxDuration(); + + pumpDescription.isTempBasalCapable = true; + + if (pumpType.getPumpTempBasalType()==PumpTempBasalType.Percent) + { + pumpDescription.tempBasalStyle = PumpDescription.PERCENT; + pumpDescription.maxTempPercent = pumpType.getTbrSettings().getMaxDose().intValue(); + pumpDescription.tempPercentStep = (int)pumpType.getTbrSettings().getStep(); + } + else + { + pumpDescription.tempBasalStyle = PumpDescription.ABSOLUTE; + pumpDescription.maxTempAbsolute = pumpType.getTbrSettings().getMaxDose(); + pumpDescription.tempAbsoluteStep = pumpType.getTbrSettings().getStep(); + } + + pumpDescription.tempDurationStep = pumpType.getTbrSettings().getDurationStep(); + pumpDescription.tempMaxDuration = pumpType.getTbrSettings().getMaxDuration(); + + + pumpDescription.isSetBasalProfileCapable = true; + pumpDescription.basalStep = pumpType.getBaseBasalStep(); + pumpDescription.basalMinimumRate = pumpType.getBaseBasalMinValue(); + } + + +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java index ebaf2b19dd..a5c2b4dd93 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpFragment.java @@ -19,6 +19,7 @@ import org.slf4j.LoggerFactory; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.plugins.Common.SubscriberFragment; +import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; public class VirtualPumpFragment extends SubscriberFragment { @@ -29,6 +30,9 @@ public class VirtualPumpFragment extends SubscriberFragment { TextView extendedBolusView; TextView batteryView; TextView reservoirView; + TextView pumpTypeView; + TextView pumpSettingsView; + private static Handler sLoopHandler = new Handler(); private static Runnable sRefreshLoop = null; @@ -58,6 +62,8 @@ public class VirtualPumpFragment extends SubscriberFragment { extendedBolusView = (TextView) view.findViewById(R.id.virtualpump_extendedbolus); batteryView = (TextView) view.findViewById(R.id.virtualpump_battery); reservoirView = (TextView) view.findViewById(R.id.virtualpump_reservoir); + pumpTypeView = (TextView) view.findViewById(R.id.virtualpump_type); + pumpSettingsView = (TextView) view.findViewById(R.id.virtualpump_type_def); return view; } catch (Exception e) { @@ -93,6 +99,20 @@ public class VirtualPumpFragment extends SubscriberFragment { } batteryView.setText(virtualPump.batteryPercent + "%"); reservoirView.setText(virtualPump.reservoirInUnits + "U"); + + virtualPump.refreshConfiguration(); + + PumpType pumpType = virtualPump.getPumpType(); + + pumpTypeView.setText(pumpType.getDescription()); + + String template = MainApp.gs(R.string.virtualpump_pump_def); + + template = template.replace("EXTENDED_NOTE", pumpType.hasExtendedBasals() ? // + MainApp.gs(R.string.virtualpump_pump_def_extended_note) : ""); + + pumpSettingsView.setText(pumpType.getFullDescription(template)); + } }); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java index 1c9fdaaaf7..cf89e81093 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/PumpVirtual/VirtualPumpPlugin.java @@ -26,6 +26,8 @@ import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.plugins.Overview.events.EventNewNotification; import info.nightscout.androidaps.plugins.Overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.Overview.notifications.Notification; +import info.nightscout.androidaps.plugins.PumpCommon.defs.PumpType; +import info.nightscout.androidaps.plugins.PumpCommon.utils.PumpUtil; import info.nightscout.androidaps.plugins.PumpVirtual.events.EventVirtualPumpUpdateGui; import info.nightscout.utils.DateUtil; import info.nightscout.utils.NSUpload; @@ -51,6 +53,9 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { private PumpDescription pumpDescription = new PumpDescription(); + PumpType pumpType = null; + + private static void loadFakingStatus() { fromNSAreCommingFakedExtendedBoluses = SP.getBoolean("fromNSAreCommingFakedExtendedBoluses", false); } @@ -460,4 +465,31 @@ public class VirtualPumpPlugin implements PluginBase, PumpInterface { return "Virtual Pump"; } + public PumpType getPumpType() + { + return pumpType; + } + + + public void refreshConfiguration() + { + String pumptype = SP.getString("virtualpump_type", "Generic AAPS"); + + PumpType pumpTypeNew = PumpType.getByDescription(pumptype); + + if (pumpType == pumpTypeNew) + return; + + // reset + pumpDescription.resetSettings(); + + // virtual pump specific (not configurable) + pumpDescription.isRefillingCapable = false; + + PumpUtil.setPumpDescription(pumpDescription, pumpTypeNew); + + this.pumpType = pumpTypeNew; + + } + } diff --git a/app/src/main/res/layout/virtualpump_fragment.xml b/app/src/main/res/layout/virtualpump_fragment.xml index 3643c95bf5..0cc6e739ff 100644 --- a/app/src/main/res/layout/virtualpump_fragment.xml +++ b/app/src/main/res/layout/virtualpump_fragment.xml @@ -189,6 +189,7 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index 660f6ee00e..aee358981e 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -100,4 +100,25 @@ @string/yes + + Generic AAPS + Cellnovo + Accu-Chek Spirit + Accu-Chek Combo + Animas Ping + Animas Vibe + Insulet Omnipod + Medtronic 512/712 + Medtronic 515/715 + Medtronic 522/722 + Medtronic 523/723 + Medtronic 553/753 (Revel) + Medtronic 554/754 (Veo) + Medtronic 640G + Tandem t:slim + Tandem t:flex + Tandem t:slim G4 + Tandem t:slim X2 + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 554b7f759f..27726bf7ab 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -861,5 +861,9 @@ Recovering from connection loss Not enough insulin for bolus left in reservoir Extended bolus delivery error + Virtual Pump Type + Pump Definition + Bolus: Step=%s\nExtended Bolus: [Step=%s, Duration=%smin-%sh]\nBasal: Step=%s\nTBR: %s (by %s), Duration=%smin-%sh\nEXTENDED_NOTE + * Ranged basal/bolus values are not supported by Virtual Pump. diff --git a/app/src/main/res/xml/pref_virtualpump.xml b/app/src/main/res/xml/pref_virtualpump.xml index 23d39114b4..ac65f5e228 100644 --- a/app/src/main/res/xml/pref_virtualpump.xml +++ b/app/src/main/res/xml/pref_virtualpump.xml @@ -8,6 +8,14 @@ android:defaultValue="false" android:key="virtualpump_uploadstatus" android:title="@string/virtualpump_uploadstatus_title" /> + + + \ No newline at end of file