@@ -301,7 +303,16 @@
android:theme="@style/Theme.AppCompat.NoTitle" />
-
+
+
+
+
+
diff --git a/app/src/main/java/info/nightscout/androidaps/MainApp.java b/app/src/main/java/info/nightscout/androidaps/MainApp.java
index 734c7dd0ed..d2759e04ae 100644
--- a/app/src/main/java/info/nightscout/androidaps/MainApp.java
+++ b/app/src/main/java/info/nightscout/androidaps/MainApp.java
@@ -1,14 +1,10 @@
package info.nightscout.androidaps;
import android.app.Application;
-import android.bluetooth.BluetoothAdapter;
import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.SystemClock;
-import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.PluralsRes;
@@ -68,8 +64,6 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin;
import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin;
import info.nightscout.androidaps.plugins.profile.simple.SimpleProfilePlugin;
import info.nightscout.androidaps.plugins.pump.combo.ComboPlugin;
-import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
-import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
import info.nightscout.androidaps.plugins.pump.danaR.DanaRPlugin;
import info.nightscout.androidaps.plugins.pump.danaRKorean.DanaRKoreanPlugin;
import info.nightscout.androidaps.plugins.pump.danaRS.DanaRSPlugin;
@@ -77,6 +71,7 @@ import info.nightscout.androidaps.plugins.pump.danaRv2.DanaRv2Plugin;
import info.nightscout.androidaps.plugins.pump.insight.LocalInsightPlugin;
import info.nightscout.androidaps.plugins.pump.mdi.MDIPlugin;
import info.nightscout.androidaps.plugins.pump.medtronic.MedtronicPumpPlugin;
+import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin;
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityAAPSPlugin;
import info.nightscout.androidaps.plugins.sensitivity.SensitivityOref0Plugin;
@@ -187,7 +182,10 @@ public class MainApp extends Application {
if (Config.PUMPDRIVERS) pluginsList.add(LocalInsightPlugin.getPlugin());
pluginsList.add(CareportalPlugin.getPlugin());
if (Config.PUMPDRIVERS) pluginsList.add(ComboPlugin.getPlugin());
- if (Config.PUMPDRIVERS && engineeringMode) pluginsList.add(MedtronicPumpPlugin.getPlugin());
+ if (Config.PUMPDRIVERS && engineeringMode)
+ pluginsList.add(MedtronicPumpPlugin.getPlugin());
+ if (Config.PUMPDRIVERS && engineeringMode)
+ pluginsList.add(OmnipodPumpPlugin.getPlugin());
if (Config.MDI) pluginsList.add(MDIPlugin.getPlugin());
pluginsList.add(VirtualPumpPlugin.getPlugin());
if (Config.APS) pluginsList.add(LoopPlugin.getPlugin());
@@ -461,7 +459,7 @@ public class MainApp extends Application {
unregisterReceiver(btReceiver);
}
- if (timeDateOrTZChangeReceiver!=null) {
+ if (timeDateOrTZChangeReceiver != null) {
unregisterReceiver(timeDateOrTZChangeReceiver);
}
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 8524246d02..e1d462c821 100644
--- a/app/src/main/java/info/nightscout/androidaps/data/Profile.java
+++ b/app/src/main/java/info/nightscout/androidaps/data/Profile.java
@@ -23,6 +23,7 @@ import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.DecimalFormatter;
import info.nightscout.androidaps.utils.FabricPrivacy;
import info.nightscout.androidaps.utils.MidnightTime;
+import info.nightscout.androidaps.utils.Round;
public class Profile {
private static Logger log = LoggerFactory.getLogger(Profile.class);
@@ -475,6 +476,17 @@ public class Profile {
public int timeAsSeconds;
public double value;
+
+ public boolean equals(Object otherObject) {
+ if (!(otherObject instanceof ProfileValue)) {
+ return false;
+ }
+
+ ProfileValue otherProfileValue = (ProfileValue) otherObject;
+
+ return (timeAsSeconds == otherProfileValue.timeAsSeconds) && Round.isSame(value, otherProfileValue.value);
+
+ }
}
public synchronized ProfileValue[] getBasalValues() {
@@ -665,4 +677,27 @@ public class Profile {
public int getTimeshift() {
return timeshift;
}
+
+
+ public boolean isProfileTheSame(Profile otherProfile) {
+
+ if (!Round.isSame(this.baseBasalSum(), otherProfile.baseBasalSum()))
+ return false;
+
+ ProfileValue[] basalValues = this.getBasalValues();
+ ProfileValue[] otherBasalValues = otherProfile.getBasalValues();
+
+ if (basalValues.length != otherBasalValues.length)
+ return false;
+
+ for (int i = 0; i < basalValues.length; i++) {
+ if (!basalValues[i].equals(otherBasalValues[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java
index ff6b59c45c..33de29a745 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.java
@@ -1,18 +1,18 @@
package info.nightscout.androidaps.plugins.pump.common;
-import java.util.Date;
-
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import com.squareup.otto.Subscribe;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
import info.nightscout.androidaps.BuildConfig;
import info.nightscout.androidaps.MainApp;
import info.nightscout.androidaps.R;
@@ -22,12 +22,14 @@ import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.ExtendedBolus;
import info.nightscout.androidaps.db.TemporaryBasal;
import info.nightscout.androidaps.events.EventAppExit;
+import info.nightscout.androidaps.events.EventCustomActionsChanged;
import info.nightscout.androidaps.interfaces.ConstraintsInterface;
import info.nightscout.androidaps.interfaces.PluginBase;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpInterface;
import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState;
@@ -48,9 +50,9 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
protected static final PumpEnactResult OPERATION_NOT_SUPPORTED = new PumpEnactResult().success(false)
- .enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump_driver));
+ .enacted(false).comment(MainApp.gs(R.string.pump_operation_not_supported_by_pump_driver));
protected static final PumpEnactResult OPERATION_NOT_YET_SUPPORTED = new PumpEnactResult().success(false)
- .enacted(false).comment(MainApp.gs(R.string.pump_operation_not_yet_supported_by_pump));
+ .enacted(false).comment(MainApp.gs(R.string.pump_operation_not_yet_supported_by_pump));
protected PumpDescription pumpDescription = new PumpDescription();
protected PumpStatus pumpStatus;
@@ -231,7 +233,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
@Override
public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
- boolean enforceNew) {
+ boolean enforceNew) {
if (isLoggingEnabled())
LOG.warn("setTempBasalAbsolute [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
@@ -240,7 +242,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
@Override
public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile,
- boolean enforceNew) {
+ boolean enforceNew) {
if (isLoggingEnabled())
LOG.warn("setTempBasalPercent [PumpPluginAbstract] - Not implemented.");
return getOperationNotSupportedWithCustomText(R.string.pump_operation_not_supported_by_pump_driver);
@@ -294,8 +296,8 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
// Short info for SMS, Wear etc
public boolean isFakingTempsByExtendedBoluses() {
- if (isLoggingEnabled())
- LOG.warn("isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.");
+ //if (isLoggingEnabled())
+ // LOG.warn("isFakingTempsByExtendedBoluses [PumpPluginAbstract] - Not implemented.");
return false;
}
@@ -332,7 +334,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
TemporaryBasal tb = TreatmentsPlugin.getPlugin().getTempBasalFromHistory(System.currentTimeMillis());
if (tb != null) {
extended.put("TempBasalAbsoluteRate",
- tb.tempBasalConvertedToAbsolute(System.currentTimeMillis(), profile));
+ tb.tempBasalConvertedToAbsolute(System.currentTimeMillis(), profile));
extended.put("TempBasalStart", DateUtil.dateAndTimeString(tb.date));
extended.put("TempBasalRemaining", tb.getPlannedRemainingMinutes());
}
@@ -364,20 +366,20 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
String ret = "";
if (pumpStatus.lastConnection != 0) {
Long agoMsec = System.currentTimeMillis() - pumpStatus.lastConnection;
- int agoMin = (int)(agoMsec / 60d / 1000d);
+ int agoMin = (int) (agoMsec / 60d / 1000d);
ret += "LastConn: " + agoMin + " min ago\n";
}
if (pumpStatus.lastBolusTime != null && pumpStatus.lastBolusTime.getTime() != 0) {
ret += "LastBolus: " + DecimalFormatter.to2Decimal(pumpStatus.lastBolusAmount) + "U @" + //
- android.text.format.DateFormat.format("HH:mm", pumpStatus.lastBolusTime) + "\n";
+ android.text.format.DateFormat.format("HH:mm", pumpStatus.lastBolusTime) + "\n";
}
TemporaryBasal activeTemp = TreatmentsPlugin.getPlugin()
- .getRealTempBasalFromHistory(System.currentTimeMillis());
+ .getRealTempBasalFromHistory(System.currentTimeMillis());
if (activeTemp != null) {
ret += "Temp: " + activeTemp.toStringFull() + "\n";
}
ExtendedBolus activeExtendedBolus = TreatmentsPlugin.getPlugin().getExtendedBolusFromHistory(
- System.currentTimeMillis());
+ System.currentTimeMillis());
if (activeExtendedBolus != null) {
ret += "Extended: " + activeExtendedBolus.toString() + "\n";
}
@@ -401,7 +403,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
if (isLoggingEnabled())
LOG.error("deliverTreatment: Invalid input");
return new PumpEnactResult().success(false).enacted(false).bolusDelivered(0d).carbsDelivered(0d)
- .comment(MainApp.gs(R.string.danar_invalidinput));
+ .comment(MainApp.gs(R.string.danar_invalidinput));
} else if (detailedBolusInfo.insulin > 0) {
// bolus needed, ask pump to deliver it
return deliverBolus(detailedBolusInfo);
@@ -419,7 +421,7 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
LOG.debug("deliverTreatment: Carb only treatment.");
return new PumpEnactResult().success(true).enacted(true).bolusDelivered(0d)
- .carbsDelivered(detailedBolusInfo.carbs).comment(MainApp.gs(R.string.virtualpump_resultok));
+ .carbsDelivered(detailedBolusInfo.carbs).comment(MainApp.gs(R.string.virtualpump_resultok));
}
} finally {
triggerUIChange();
@@ -443,4 +445,32 @@ public abstract class PumpPluginAbstract extends PluginBase implements PumpInter
return new PumpEnactResult().success(false).enacted(false).comment(MainApp.gs(resourceId));
}
-}
+
+ @Override
+ public boolean canHandleDST() {
+ return false;
+ }
+
+
+ @Override
+ public ManufacturerType manufacturer() {
+ return pumpStatus.pumpType.getManufacturer();
+ }
+
+ @Override
+ public PumpType model() {
+ return pumpStatus.pumpType;
+ }
+
+
+ @Override
+ public void timeDateOrTimeZoneChanged() {
+ }
+
+
+ public void refreshCustomActionsList() {
+ MainApp.bus().post(new EventCustomActionsChanged());
+ }
+
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/TempBasalPair.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/TempBasalPair.java
new file mode 100644
index 0000000000..1e53734b5f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/data/TempBasalPair.java
@@ -0,0 +1,79 @@
+package info.nightscout.androidaps.plugins.pump.common.data;
+
+import com.google.gson.annotations.Expose;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.logging.L;
+
+public class TempBasalPair {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
+
+ @Expose
+ protected double insulinRate = 0.0d;
+ @Expose
+ protected int durationMinutes = 0;
+ @Expose
+ protected boolean isPercent = false;
+
+ private Long start;
+ private Long end;
+
+ public TempBasalPair() {
+ }
+
+
+ public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) {
+ this.insulinRate = insulinRate;
+ this.isPercent = isPercent;
+ this.durationMinutes = durationMinutes;
+ }
+
+
+ public double getInsulinRate() {
+ return insulinRate;
+ }
+
+
+ public void setInsulinRate(double insulinRate) {
+ this.insulinRate = insulinRate;
+ }
+
+
+ public int getDurationMinutes() {
+ return durationMinutes;
+ }
+
+
+ public void setDurationMinutes(int durationMinutes) {
+ this.durationMinutes = durationMinutes;
+ }
+
+
+ public boolean isPercent() {
+ return isPercent;
+ }
+
+
+ public void setIsPercent(boolean yesIsPercent) {
+ this.isPercent = yesIsPercent;
+ }
+
+ public void setStartTime(Long startTime) {
+ this.start = startTime;
+ }
+
+
+ public void setEndTime(Long endTime) {
+ this.end = endTime;
+ }
+
+
+ @Override
+ public String toString() {
+ return "TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent="
+ + isPercent + "]";
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java
index 69837afd7c..a0df5790b9 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkCommunicationManager.java
@@ -3,8 +3,6 @@ package info.nightscout.androidaps.plugins.pump.common.hw.rileylink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import android.content.Context;
-
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy;
@@ -38,7 +36,6 @@ public abstract class RileyLinkCommunicationManager {
private static final int ALLOWED_PUMP_UNREACHABLE = 10 * 60 * 1000; // 10 minutes
protected final RFSpy rfspy;
- protected final Context context;
protected int receiverDeviceAwakeForMinutes = 1; // override this in constructor of specific implementation
protected String receiverDeviceID; // String representation of receiver device (ex. Pump (xxxxxx) or Pod (yyyyyy))
protected long lastGoodReceiverCommunicationTime = 0;
@@ -51,8 +48,7 @@ public abstract class RileyLinkCommunicationManager {
private int timeoutCount = 0;
- public RileyLinkCommunicationManager(Context context, RFSpy rfspy) {
- this.context = context;
+ public RileyLinkCommunicationManager(RFSpy rfspy) {
this.rfspy = rfspy;
this.rileyLinkServiceData = RileyLinkUtil.getRileyLinkServiceData();
RileyLinkUtil.setRileyLinkCommunicationManager(this);
@@ -125,7 +121,6 @@ public abstract class RileyLinkCommunicationManager {
}
-
// FIXME change wakeup
// TODO we might need to fix this. Maybe make pump awake for shorter time (battery factor for pump) - Andy
public void wakeUp(int duration_minutes, boolean force) {
@@ -143,8 +138,8 @@ public abstract class RileyLinkCommunicationManager {
LOG.info("Waking pump...");
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData); // simple
- RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)200,
- (byte)0, (byte)0, 25000, (byte)0);
+ RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 200,
+ (byte) 0, (byte) 0, 25000, (byte) 0);
if (isLogEnabled())
LOG.info("wakeup: raw response is " + ByteUtil.shortHexString(resp.getRaw()));
@@ -225,8 +220,8 @@ public abstract class RileyLinkCommunicationManager {
for (int j = 0; j < tries; j++) {
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData);
- RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte)0, (byte)0,
- (byte)0, (byte)0, 1250, (byte)0);
+ RFSpyResponse resp = rfspy.transmitThenReceive(new RadioPacket(pumpMsgContent), (byte) 0, (byte) 0,
+ (byte) 0, (byte) 0, 1250, (byte) 0);
if (resp.wasTimeout()) {
LOG.error("scanForPump: Failed to find pump at frequency {}", frequencies[i]);
} else if (resp.looksLikeRadioPacket()) {
@@ -258,7 +253,7 @@ public abstract class RileyLinkCommunicationManager {
trial.tries++;
}
sumRSSI += -99.0 * (trial.tries - trial.successes);
- trial.averageRSSI2 = (double)(sumRSSI) / (double)(trial.tries);
+ trial.averageRSSI2 = (double) (sumRSSI) / (double) (trial.tries);
trial.calculateAverage();
@@ -273,7 +268,7 @@ public abstract class RileyLinkCommunicationManager {
FrequencyTrial one = results.trials.get(k);
stringBuilder.append(String.format("Scan Result[%s]: Freq=%s, avg RSSI = %s\n", "" + k, ""
- + one.frequencyMHz, "" + one.averageRSSI + ", RSSIs =" + one.rssiList));
+ + one.frequencyMHz, "" + one.averageRSSI + ", RSSIs =" + one.rssiList));
}
LOG.info(stringBuilder.toString());
@@ -315,7 +310,7 @@ public abstract class RileyLinkCommunicationManager {
// RLMessage msg = makeRLMessage(RLMessageType.ReadSimpleData);
byte[] pumpMsgContent = createPumpMessageContent(RLMessageType.ReadSimpleData);
RadioPacket pkt = new RadioPacket(pumpMsgContent);
- RFSpyResponse resp = rfspy.transmitThenReceive(pkt, (byte)0, (byte)0, (byte)0, (byte)0, SCAN_TIMEOUT, (byte)0);
+ RFSpyResponse resp = rfspy.transmitThenReceive(pkt, (byte) 0, (byte) 0, (byte) 0, (byte) 0, SCAN_TIMEOUT, (byte) 0);
if (resp.wasTimeout()) {
LOG.warn("tune_tryFrequency: no pump response at frequency {}", freqMHz);
} else if (resp.looksLikeRadioPacket()) {
@@ -327,8 +322,8 @@ public abstract class RileyLinkCommunicationManager {
LOG.warn("tune_tryFrequency: saw response level {} at frequency {}", radioResponse.rssi, freqMHz);
return calculateRssi(radioResponse.rssi);
} else {
- LOG.warn("tune_tryFrequency: invalid radio response:"
- + ByteUtil.shortHexString(radioResponse.getPayload()));
+ LOG.warn("tune_tryFrequency: invalid radio response:"
+ + ByteUtil.shortHexString(radioResponse.getPayload()));
}
} catch (RileyLinkCommunicationException e) {
@@ -350,7 +345,7 @@ public abstract class RileyLinkCommunicationManager {
// Try again at larger step size
stepsize += 0.05;
} else {
- if ((int)(evenBetterFrequency * 100) == (int)(betterFrequency * 100)) {
+ if ((int) (evenBetterFrequency * 100) == (int) (betterFrequency * 100)) {
// value did not change, so we're done.
break;
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java
index a887fede5c..80cad6fa9a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/data/RLHistoryItem.java
@@ -8,6 +8,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLin
import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicCommandType;
import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
/**
* Created by andy on 5/19/18.
@@ -23,10 +24,11 @@ public class RLHistoryItem {
private RileyLinkTargetDevice targetDevice;
private PumpDeviceState pumpDeviceState;
+ private OmnipodCommandType omnipodCommandType;
public RLHistoryItem(RileyLinkServiceState serviceState, RileyLinkError errorCode,
- RileyLinkTargetDevice targetDevice) {
+ RileyLinkTargetDevice targetDevice) {
this.targetDevice = targetDevice;
this.dateTime = new LocalDateTime();
this.serviceState = serviceState;
@@ -50,6 +52,13 @@ public class RLHistoryItem {
}
+ public RLHistoryItem(OmnipodCommandType omnipodCommandType) {
+ this.dateTime = new LocalDateTime();
+ this.omnipodCommandType = omnipodCommandType;
+ source = RLHistoryItemSource.OmnipodCommand;
+ }
+
+
public LocalDateTime getDateTime() {
return dateTime;
}
@@ -71,7 +80,7 @@ public class RLHistoryItem {
switch (this.source) {
case RileyLink:
return "State: " + MainApp.gs(serviceState.getResourceId(targetDevice))
- + (this.errorCode == null ? "" : ", Error Code: " + errorCode);
+ + (this.errorCode == null ? "" : ", Error Code: " + errorCode);
case MedtronicPump:
return MainApp.gs(pumpDeviceState.getResourceId());
@@ -79,6 +88,9 @@ public class RLHistoryItem {
case MedtronicCommand:
return medtronicCommandType.name();
+ case OmnipodCommand:
+ return omnipodCommandType.name();
+
default:
return "Unknown Description";
}
@@ -97,7 +109,8 @@ public class RLHistoryItem {
public enum RLHistoryItemSource {
RileyLink("RileyLink"), //
MedtronicPump("Medtronic"), //
- MedtronicCommand("Medtronic");
+ MedtronicCommand("Medtronic"), //
+ OmnipodCommand("Omnipod");
private String desc;
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java
index f67082cd93..621ed52f81 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.java
@@ -33,7 +33,6 @@ import info.nightscout.androidaps.data.Profile;
import info.nightscout.androidaps.data.PumpEnactResult;
import info.nightscout.androidaps.db.Source;
import info.nightscout.androidaps.db.TemporaryBasal;
-import info.nightscout.androidaps.events.EventCustomActionsChanged;
import info.nightscout.androidaps.events.EventRefreshOverview;
import info.nightscout.androidaps.interfaces.PluginDescription;
import info.nightscout.androidaps.interfaces.PluginType;
@@ -1560,11 +1559,6 @@ public class MedtronicPumpPlugin extends PumpPluginAbstract implements PumpInter
this.hasTimeDateOrTimeZoneChanged = true;
}
- private void refreshCustomActionsList() {
- MainApp.bus().post(new EventCustomActionsChanged());
- }
-
-
public void setEnableCustomAction(MedtronicCustomActionType customAction, boolean isEnabled) {
if (customAction == MedtronicCustomActionType.ClearBolusBlock) {
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java
index d53d59197e..fc6672b9a5 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/MedtronicCommunicationManager.java
@@ -1,6 +1,5 @@
package info.nightscout.androidaps.plugins.pump.medtronic.comm;
-import android.content.Context;
import android.os.SystemClock;
import org.joda.time.LocalDateTime;
@@ -71,8 +70,8 @@ public class MedtronicCommunicationManager extends RileyLinkCommunicationManager
private boolean doWakeUpBeforeCommand = true;
- public MedtronicCommunicationManager(Context context, RFSpy rfspy) {
- super(context, rfspy);
+ public MedtronicCommunicationManager(RFSpy rfspy) {
+ super(rfspy);
medtronicCommunicationManager = this;
this.medtronicConverter = new MedtronicConverter();
this.pumpHistoryDecoder = new MedtronicPumpHistoryDecoder();
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java
index 1c45cdbcef..2ad5e6897a 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.java
@@ -1,7 +1,5 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data.dto;
-import com.google.gson.annotations.Expose;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -18,18 +16,10 @@ import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
*
* Just need a class to keep the pair together, for parcel transport.
*/
-public class TempBasalPair {
+public class TempBasalPair extends info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair {
private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
- @Expose
- private double insulinRate = 0.0d;
- @Expose
- private int durationMinutes = 0;
- @Expose
- private boolean isPercent = false;
-
-
public TempBasalPair() {
}
@@ -42,6 +32,8 @@ public class TempBasalPair {
* @param isPercent
*/
public TempBasalPair(byte rateByte, int startTimeByte, boolean isPercent) {
+ super();
+
int rateInt = ByteUtil.asUINT8(rateByte);
if (isPercent)
@@ -53,13 +45,6 @@ public class TempBasalPair {
}
- public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) {
- this.insulinRate = insulinRate;
- this.isPercent = isPercent;
- this.durationMinutes = durationMinutes;
- }
-
-
public TempBasalPair(byte[] response) {
if (L.isEnabled(L.PUMPCOMM))
@@ -80,33 +65,8 @@ public class TempBasalPair {
}
- public double getInsulinRate() {
- return insulinRate;
- }
-
-
- public void setInsulinRate(double insulinRate) {
- this.insulinRate = insulinRate;
- }
-
-
- public int getDurationMinutes() {
- return durationMinutes;
- }
-
-
- public void setDurationMinutes(int durationMinutes) {
- this.durationMinutes = durationMinutes;
- }
-
-
- public boolean isPercent() {
- return isPercent;
- }
-
-
- public void setIsPercent(boolean yesIsPercent) {
- this.isPercent = yesIsPercent;
+ public TempBasalPair(double insulinRate, boolean isPercent, int durationMinutes) {
+ super(insulinRate, isPercent, durationMinutes);
}
@@ -160,10 +120,4 @@ public class TempBasalPair {
}
}
-
- @Override
- public String toString() {
- return "TempBasalPair [" + "Rate=" + insulinRate + ", DurationMinutes=" + durationMinutes + ", IsPercent="
- + isPercent + "]";
- }
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java
index cba33353f1..49d49ee06c 100644
--- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/service/RileyLinkMedtronicService.java
@@ -109,7 +109,7 @@ public class RileyLinkMedtronicService extends RileyLinkService {
RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE);
// init rileyLinkCommunicationManager
- medtronicCommunicationManager = new MedtronicCommunicationManager(context, rfspy);
+ medtronicCommunicationManager = new MedtronicCommunicationManager(rfspy);
}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.java
new file mode 100644
index 0000000000..343849729b
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.java
@@ -0,0 +1,514 @@
+package info.nightscout.androidaps.plugins.pump.omnipod;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.graphics.Color;
+import android.os.Bundle;
+import android.os.Handler;
+import android.text.Spanned;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.crashlytics.android.Crashlytics;
+import com.joanzapata.iconify.widget.IconTextView;
+import com.squareup.otto.Subscribe;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnClick;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.events.EventExtendedBolusChange;
+import info.nightscout.androidaps.events.EventPumpStatusChanged;
+import info.nightscout.androidaps.events.EventTempBasalChange;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.common.SubscriberFragment;
+import info.nightscout.androidaps.plugins.configBuilder.ConfigBuilderPlugin;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity;
+import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange;
+import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged;
+import info.nightscout.androidaps.plugins.pump.omnipod.service.OmnipodPumpStatus;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.queue.events.EventQueueChanged;
+import info.nightscout.androidaps.utils.DateUtil;
+import info.nightscout.androidaps.utils.DecimalFormatter;
+import info.nightscout.androidaps.utils.SetWarnColor;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+public class OmnipodFragment extends SubscriberFragment {
+
+ private static Logger LOG = LoggerFactory.getLogger(L.PUMP);
+
+ @BindView(R.id.omnipod_lastconnection)
+ TextView lastConnectionView;
+ @BindView(R.id.omnipod_lastbolus)
+ TextView lastBolusView;
+ @BindView(R.id.omnipod_basabasalrate)
+ TextView basaBasalRateView;
+
+ @BindView(R.id.omnipod_tempbasal)
+ TextView tempBasalView;
+ @BindView(R.id.omnipod_pumpstate_battery)
+ TextView batteryView;
+ @BindView(R.id.omnipod_rl_status)
+ IconTextView rileyLinkStatus;
+ @BindView(R.id.omnipod_reservoir)
+ TextView reservoirView;
+ @BindView(R.id.omnipod_errors)
+ TextView errorsView;
+ @BindView(R.id.omnipod_queue)
+ TextView queueView;
+ @BindView(R.id.overview_pumpstatuslayout_omnipod)
+ LinearLayout pumpStatusLayout;
+ @BindView(R.id.overview_pump_omnipod)
+ TextView overviewPumpOmnipodView;
+ @BindView(R.id.omnipod_pod_status)
+ IconTextView pumpStatusIconView;
+ @BindView(R.id.omnipod_refresh)
+ Button refreshButton;
+ private Handler loopHandler = new Handler();
+ private static Activity localActivity;
+
+ static Button refreshButtonStatic;
+
+ private Runnable refreshLoop = new Runnable() {
+
+ @Override
+ public void run() {
+ updateGUI();
+ loopHandler.postDelayed(refreshLoop, 60 * 1000L);
+ }
+ };
+
+
+ public OmnipodFragment() {
+ }
+
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ loopHandler.postDelayed(refreshLoop, 60 * 1000L);
+ }
+
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ loopHandler.removeCallbacks(refreshLoop);
+ }
+
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ try {
+ View view = inflater.inflate(R.layout.omnipod_fragment, container, false);
+ unbinder = ButterKnife.bind(this, view);
+
+ overviewPumpOmnipodView.setBackgroundColor(MainApp.sResources.getColor(R.color.colorInitializingBorder));
+
+ rileyLinkStatus.setText(getTranslation(RileyLinkServiceState.NotStarted.getResourceId(getTargetDevice())));
+ rileyLinkStatus.setTextSize(14);
+
+ pumpStatusIconView.setTextColor(Color.WHITE);
+ pumpStatusIconView.setTextSize(14);
+ pumpStatusIconView.setText("{fa-bed}");
+
+ refreshButtonStatic = refreshButton;
+
+ return view;
+ } catch (Exception e) {
+ Crashlytics.logException(e);
+ }
+
+ return null;
+ }
+
+
+ @OnClick(R.id.omnipod_pod_mgmt)
+ void onHistoryClick() {
+ // TODO
+// if (MedtronicUtil.getPumpStatus().verifyConfiguration()) {
+// startActivity(new Intent(getContext(), MedtronicHistoryActivity.class));
+// } else {
+// MedtronicUtil.displayNotConfiguredDialog(getContext());
+// }
+ }
+
+
+ @OnClick(R.id.omnipod_refresh)
+ void onRefreshClick() {
+ // TODO
+// if (!MedtronicUtil.getPumpStatus().verifyConfiguration()) {
+// MedtronicUtil.displayNotConfiguredDialog(getContext());
+// return;
+// }
+//
+// if (refreshButtonStatic != null)
+// refreshButtonStatic.setEnabled(false);
+//
+// MedtronicPumpPlugin.getPlugin().resetStatusState();
+//
+// ConfigBuilderPlugin.getPlugin().getCommandQueue().readStatus("Clicked refresh", new Callback() {
+//
+// @Override
+// public void run() {
+// Activity activity = getActivity();
+//
+// if (activity != null) {
+// activity.runOnUiThread(() -> {
+// if (refreshButtonStatic != null)
+// refreshButtonStatic.setEnabled(true);
+// });
+// }
+// }
+// });
+ }
+
+
+ @OnClick(R.id.omnipod_stats)
+ void onStatsClick() {
+ if (OmnipodUtil.getPumpStatus().verifyConfiguration()) {
+ startActivity(new Intent(getContext(), RileyLinkStatusActivity.class));
+ } else {
+ OmnipodUtil.displayNotConfiguredDialog(getContext());
+ }
+ }
+
+
+ @Subscribe
+ public void onStatusEvent(final EventPumpStatusChanged c) {
+ updateGUI();
+ }
+
+
+ public static void refreshButtonEnabled(boolean enable) {
+ if (localActivity != null) {
+ localActivity.runOnUiThread(() -> {
+ if (refreshButtonStatic != null) {
+ refreshButtonStatic.setEnabled(enable);
+ }
+ });
+ }
+ }
+
+
+ public static Activity getCustomActivity() {
+ return localActivity;
+ }
+
+
+ @Subscribe
+ public void onStatusEvent(final EventOmnipodDeviceStatusChange eventStatusChange) {
+ if (isLogEnabled())
+ LOG.info("onStatusEvent(EventOmnipodDeviceStatusChange): {}", eventStatusChange);
+ Activity activity = getActivity();
+
+ if (activity != null) {
+ localActivity = activity;
+ activity.runOnUiThread(() -> {
+ OmnipodPumpStatus pumpStatus = OmnipodUtil.getPumpStatus();
+ setDeviceStatus(pumpStatus);
+ });
+ }
+ }
+
+
+ private synchronized void setDeviceStatus(OmnipodPumpStatus pumpStatus) {
+
+ pumpStatus.rileyLinkServiceState = (RileyLinkServiceState) checkStatusSet(pumpStatus.rileyLinkServiceState,
+ RileyLinkUtil.getServiceState());
+
+ if (pumpStatus.rileyLinkServiceState != null && rileyLinkStatus != null) {
+
+ int resourceId = pumpStatus.rileyLinkServiceState.getResourceId(getTargetDevice());
+ rileyLinkStatus.setTextColor(Color.WHITE);
+ rileyLinkStatus.setTextSize(14);
+
+ if (pumpStatus.rileyLinkServiceState == RileyLinkServiceState.NotStarted) {
+ rileyLinkStatus.setText(getTranslation(resourceId));
+ rileyLinkStatus.setTextSize(14);
+ } else if (pumpStatus.rileyLinkServiceState.isConnecting()) {
+ rileyLinkStatus.setText("{fa-bluetooth-b spin} " + getTranslation(resourceId));
+ } else if (pumpStatus.rileyLinkServiceState.isError()) {
+
+ RileyLinkError rileyLinkError = RileyLinkUtil.getError();
+
+ if (rileyLinkError == null)
+ rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
+ else
+ rileyLinkStatus.setText("{fa-bluetooth-b} "
+ + getTranslation(rileyLinkError.getResourceId(RileyLinkTargetDevice.MedtronicPump)));
+
+ rileyLinkStatus.setTextColor(Color.RED);
+ } else {
+ rileyLinkStatus.setText("{fa-bluetooth-b} " + getTranslation(resourceId));
+ }
+ }
+
+ pumpStatus.rileyLinkError = (RileyLinkError) checkStatusSet(pumpStatus.rileyLinkError, RileyLinkUtil.getError());
+
+ if (errorsView != null) {
+ if (pumpStatus.rileyLinkError != null) {
+ int resourceId = pumpStatus.rileyLinkError.getResourceId(getTargetDevice());
+ errorsView.setText(getTranslation(resourceId));
+ } else
+ errorsView.setText("-");
+ }
+
+// pumpStatus.pumpDeviceState = (PumpDeviceState) checkStatusSet(pumpStatus.pumpDeviceState,
+// MedtronicUtil.getPumpDeviceState());
+//
+ if (pumpStatusIconView != null) {
+//
+// if (pumpStatus.pumpDeviceState != null) {
+//
+// switch (pumpStatus.pumpDeviceState) {
+// case Sleeping:
+// pumpStatusIconView.setText("{fa-bed} "); // + pumpStatus.pumpDeviceState.name());
+// break;
+//
+// case NeverContacted:
+// case WakingUp:
+// case PumpUnreachable:
+// case ErrorWhenCommunicating:
+// case TimeoutWhenCommunicating:
+// case InvalidConfiguration:
+// pumpStatusIconView.setText(" " + getTranslation(pumpStatus.pumpDeviceState.getResourceId()));
+// break;
+//
+// case Active: {
+// MedtronicCommandType cmd = MedtronicUtil.getCurrentCommand();
+//
+// LOG.debug("Command: " + cmd);
+//
+// if (cmd == null)
+// pumpStatusIconView.setText(" " + MainApp.gs(pumpStatus.pumpDeviceState.getResourceId()));
+// else {
+// Integer resourceId = cmd.getResourceId();
+//
+// if (cmd == MedtronicCommandType.GetHistoryData) {
+//
+// if (MedtronicUtil.frameNumber == null) {
+// pumpStatusIconView.setText(MainApp.gs(
+// R.string.medtronic_cmd_desc_get_history_request, MedtronicUtil.pageNumber));
+// } else {
+// pumpStatusIconView.setText(MainApp.gs(resourceId, MedtronicUtil.pageNumber,
+// MedtronicUtil.frameNumber));
+// }
+//
+// } else {
+// if (resourceId == null) {
+// pumpStatusIconView.setText(" " + cmd.getCommandDescription());
+// } else {
+// pumpStatusIconView.setText(" " + getTranslation(resourceId));
+// }
+// }
+//
+// }
+//
+// }
+// break;
+//
+// default:
+// LOG.warn("Unknown pump state: " + pumpStatus.pumpDeviceState);
+// }
+// } else {
+// pumpStatusIconView.setText("{fa-bed} ");
+// }
+
+ // TODO
+ pumpStatusIconView.setText("{fa-bed} ");
+ }
+
+ if (queueView != null) {
+ Spanned status = ConfigBuilderPlugin.getPlugin().getCommandQueue().spannedStatus();
+ if (status.toString().equals("")) {
+ queueView.setVisibility(View.GONE);
+ } else {
+ queueView.setVisibility(View.VISIBLE);
+ queueView.setText(status);
+ }
+ }
+
+ }
+
+
+ public Object checkStatusSet(Object object1, Object object2) {
+ if (object1 == null) {
+ return object2;
+ } else {
+ if (!object1.equals(object2)) {
+ return object2;
+ } else
+ return object1;
+ }
+ }
+
+
+ public RileyLinkTargetDevice getTargetDevice() {
+ return RileyLinkTargetDevice.Omnipod;
+ }
+
+
+ public String getTranslation(int resourceId) {
+ return MainApp.gs(resourceId);
+ }
+
+
+ @Subscribe
+ public void onStatusEvent(final EventOmnipodPumpValuesChanged s) {
+ if (isLogEnabled())
+ LOG.debug("EventOmnipodPumpValuesChanged triggered");
+ updateGUI();
+ }
+
+
+ @Subscribe
+ public void onStatusEvent(final EventTempBasalChange s) {
+ updateGUI();
+ }
+
+
+ @Subscribe
+ public void onStatusEvent(final EventExtendedBolusChange s) {
+ updateGUI();
+ }
+
+
+ @Subscribe
+ public void onStatusEvent(final EventQueueChanged s) {
+ updateGUI();
+ }
+
+
+ // GUI functions
+ @Override
+ protected void updateGUI() {
+ Activity activity = getActivity();
+ if (activity != null && basaBasalRateView != null)
+ activity.runOnUiThread(() -> {
+
+ if (lastConnectionView == null) // ui not yet initialized
+ return;
+
+ localActivity = activity;
+ OmnipodPumpPlugin plugin = OmnipodPumpPlugin.getPlugin();
+ OmnipodPumpStatus pumpStatus = OmnipodUtil.getPumpStatus();
+
+ setDeviceStatus(pumpStatus);
+
+ // last connection
+ String minAgo = DateUtil.minAgo(pumpStatus.lastConnection);
+ long min = (System.currentTimeMillis() - pumpStatus.lastConnection) / 1000 / 60;
+ if (pumpStatus.lastConnection + 60 * 1000 > System.currentTimeMillis()) {
+ lastConnectionView.setText(R.string.combo_pump_connected_now);
+ lastConnectionView.setTextColor(Color.WHITE);
+ } else if (pumpStatus.lastConnection + 30 * 60 * 1000 < System.currentTimeMillis()) {
+
+ if (min < 60) {
+ lastConnectionView.setText(MainApp.gs(R.string.minago, min));
+ } else if (min < 1440) {
+ int h = (int) (min / 60);
+
+ lastConnectionView.setText(MainApp.gq(R.plurals.objective_hours, h, h) + " "
+ + MainApp.gs(R.string.ago));
+ } else {
+
+ int h = (int) (min / 60);
+ int d = h / 24;
+ // h = h - (d * 24);
+
+ lastConnectionView.setText(MainApp.gq(R.plurals.objective_days, d, d) + " "
+ + MainApp.gs(R.string.ago));
+ }
+ lastConnectionView.setTextColor(Color.RED);
+ } else {
+ lastConnectionView.setText(minAgo);
+ lastConnectionView.setTextColor(Color.WHITE);
+ }
+
+ // last bolus
+ Double bolus = pumpStatus.lastBolusAmount;
+ Date bolusTime = pumpStatus.lastBolusTime;
+ if (bolus != null && bolusTime != null) {
+ long agoMsc = System.currentTimeMillis() - pumpStatus.lastBolusTime.getTime();
+ double bolusMinAgo = agoMsc / 60d / 1000d;
+ String unit = MainApp.gs(R.string.insulin_unit_shortname);
+ String ago;
+ if ((agoMsc < 60 * 1000)) {
+ ago = MainApp.gs(R.string.combo_pump_connected_now);
+ } else if (bolusMinAgo < 60) {
+ ago = DateUtil.minAgo(pumpStatus.lastBolusTime.getTime());
+ } else {
+ ago = DateUtil.hourAgo(pumpStatus.lastBolusTime.getTime());
+ }
+ lastBolusView.setText(MainApp.gs(R.string.combo_last_bolus, bolus, unit, ago));
+ } else {
+ lastBolusView.setText("");
+ }
+
+ // base basal rate
+ basaBasalRateView.setText("(" + (pumpStatus.activeProfileName) + ") "
+ + MainApp.gs(R.string.pump_basebasalrate, plugin.getBaseBasalRate()));
+
+ if (ConfigBuilderPlugin.getPlugin().getActivePump().isFakingTempsByExtendedBoluses()) {
+ if (TreatmentsPlugin.getPlugin().isInHistoryRealTempBasalInProgress()) {
+ tempBasalView.setText(TreatmentsPlugin.getPlugin()
+ .getRealTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
+ } else {
+ tempBasalView.setText("");
+ }
+ } else {
+ // v2 plugin
+ if (TreatmentsPlugin.getPlugin().isTempBasalInProgress()) {
+ tempBasalView.setText(TreatmentsPlugin.getPlugin()
+ .getTempBasalFromHistory(System.currentTimeMillis()).toStringFull());
+ } else {
+ tempBasalView.setText("");
+ }
+ }
+
+ // battery
+ // TODO this might need to be removed, I am not sure if pods have battery status
+ batteryView.setText("{fa-battery-" + (pumpStatus.batteryRemaining / 25) + "} ");
+// if (MedtronicUtil.getBatteryType() == BatteryType.None || pumpStatus.batteryVoltage == null) {
+// batteryView.setText("{fa-battery-" + (pumpStatus.batteryRemaining / 25) + "} ");
+// } else {
+// batteryView.setText("{fa-battery-" + (pumpStatus.batteryRemaining / 25) + "} " + pumpStatus.batteryRemaining + "%" + String.format(" (%.2f V)", pumpStatus.batteryVoltage));
+// }
+ SetWarnColor.setColorInverse(batteryView, pumpStatus.batteryRemaining, 25d, 10d);
+
+ // reservoir
+ reservoirView.setText(DecimalFormatter.to0Decimal(pumpStatus.reservoirRemainingUnits) + " / "
+ + pumpStatus.reservoirFullUnits + " " + MainApp.gs(R.string.insulin_unit_shortname));
+ SetWarnColor.setColorInverse(reservoirView, pumpStatus.reservoirRemainingUnits, 50d, 20d);
+
+ errorsView.setText(pumpStatus.getErrorInfo());
+
+ });
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMP);
+ }
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java
new file mode 100644
index 0000000000..aadbb1ad58
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java
@@ -0,0 +1,848 @@
+package info.nightscout.androidaps.plugins.pump.omnipod;
+
+import android.content.ComponentName;
+import android.content.ServiceConnection;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.SystemClock;
+
+import androidx.annotation.NonNull;
+
+import org.joda.time.LocalDateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import info.nightscout.androidaps.BuildConfig;
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.data.DetailedBolusInfo;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.data.PumpEnactResult;
+import info.nightscout.androidaps.db.Source;
+import info.nightscout.androidaps.db.TemporaryBasal;
+import info.nightscout.androidaps.events.EventRefreshOverview;
+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.general.actions.defs.CustomAction;
+import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
+import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract;
+import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
+import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState;
+import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.ui.OmnipodUIComm;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.ui.OmnipodUITask;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCustomActionType;
+import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged;
+import info.nightscout.androidaps.plugins.pump.omnipod.service.OmnipodPumpStatus;
+import info.nightscout.androidaps.plugins.pump.omnipod.service.RileyLinkOmnipodService;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
+import info.nightscout.androidaps.utils.SP;
+
+/**
+ * Created by andy on 23.04.18.
+ *
+ * @author Andy Rozman (andy.rozman@gmail.com)
+ */
+public class OmnipodPumpPlugin extends PumpPluginAbstract implements PumpInterface {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
+
+ protected static OmnipodPumpPlugin plugin = null;
+ private RileyLinkOmnipodService omnipodService;
+ private OmnipodPumpStatus pumpStatusLocal = null;
+ private OmnipodUIComm omnipodUIComm = new OmnipodUIComm();
+
+ // variables for handling statuses and history
+ private boolean firstRun = true;
+ private boolean isRefresh = false;
+ private boolean isBasalProfileInvalid = false;
+ private boolean basalProfileChanged = false;
+ private boolean isInitialized = false;
+ private OmnipodCommunicationManager omnipodCommunicationManager;
+
+ public static boolean isBusy = false;
+ private List busyTimestamps = new ArrayList<>();
+ private boolean sentIdToFirebase = false;
+ private boolean hasTimeDateOrTimeZoneChanged = false;
+
+ private Profile currentProfile;
+
+
+ private OmnipodPumpPlugin() {
+
+ super(new PluginDescription() //
+ .mainType(PluginType.PUMP) //
+ .fragmentClass(OmnipodFragment.class.getName()) //
+ .pluginName(R.string.omnipod_name) //
+ .shortName(R.string.omnipod_name_short) //
+ .preferencesId(R.xml.pref_omnipod) //
+ .description(R.string.description_pump_omnipod), //
+ PumpType.Insulet_Omnipod
+ );
+
+ displayConnectionMessages = false;
+
+ serviceConnection = new ServiceConnection() {
+
+ public void onServiceDisconnected(ComponentName name) {
+ if (isLoggingEnabled())
+ LOG.debug("RileyLinkOmnipodService is disconnected");
+ omnipodService = null;
+ }
+
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ if (isLoggingEnabled())
+ LOG.debug("RileyLinkOmnipodService is connected");
+ RileyLinkOmnipodService.LocalBinder mLocalBinder = (RileyLinkOmnipodService.LocalBinder) service;
+ omnipodService = mLocalBinder.getServiceInstance();
+
+ new Thread(() -> {
+
+ for (int i = 0; i < 20; i++) {
+ SystemClock.sleep(5000);
+
+ if (OmnipodUtil.getPumpStatus() != null) {
+ if (isLoggingEnabled())
+ LOG.debug("Starting OmniPod-RileyLink service");
+ if (OmnipodUtil.getPumpStatus().setNotInPreInit()) {
+ break;
+ }
+ }
+ }
+ }).start();
+ }
+ };
+ }
+
+
+ public static OmnipodPumpPlugin getPlugin() {
+ if (plugin == null)
+ plugin = new OmnipodPumpPlugin();
+ return plugin;
+ }
+
+
+ private String getLogPrefix() {
+ return "OmnipodPlugin::";
+ }
+
+
+ @Override
+ public void initPumpStatusData() {
+
+ this.pumpStatusLocal = new OmnipodPumpStatus(pumpDescription);
+ OmnipodUtil.setPumpStatus(pumpStatusLocal);
+
+ pumpStatusLocal.lastConnection = SP.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L);
+ pumpStatusLocal.lastDataTime = new LocalDateTime(pumpStatusLocal.lastConnection);
+ pumpStatusLocal.previousConnection = pumpStatusLocal.lastConnection;
+
+ pumpStatusLocal.refreshConfiguration();
+
+ if (isLoggingEnabled())
+ LOG.debug("initPumpStatusData: {}", this.pumpStatusLocal);
+
+ this.pumpStatus = pumpStatusLocal;
+
+ // set first Omnipod Start
+ if (!SP.contains(OmnipodConst.Statistics.FirstPumpStart)) {
+ SP.putLong(OmnipodConst.Statistics.FirstPumpStart, System.currentTimeMillis());
+ }
+
+ }
+
+
+ public void onStartCustomActions() {
+
+ // check status every minute (if any status needs refresh we send readStatus command)
+ new Thread(() -> {
+
+ do {
+ SystemClock.sleep(60000);
+
+ if (this.isInitialized) {
+ clearBusyQueue();
+ }
+
+ } while (serviceRunning);
+
+ }).start();
+ }
+
+
+ public Class getServiceClass() {
+ return RileyLinkOmnipodService.class;
+ }
+
+
+ @Override
+ public String deviceID() {
+ return "Omnipod";
+ }
+
+
+ // Pump Plugin
+
+ private boolean isServiceSet() {
+ return omnipodService != null;
+ }
+
+
+ @Override
+ public boolean isInitialized() {
+ if (isLoggingEnabled() && displayConnectionMessages)
+ LOG.debug(getLogPrefix() + "isInitialized");
+ return isServiceSet() && isInitialized;
+ }
+
+
+ @Override
+ public boolean isBusy() {
+ if (isLoggingEnabled() && displayConnectionMessages)
+ LOG.debug(getLogPrefix() + "isBusy");
+
+ if (isServiceSet()) {
+
+ if (isBusy)
+ return true;
+
+ if (busyTimestamps.size() > 0) {
+
+ clearBusyQueue();
+
+ if (busyTimestamps.size() > 0) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+
+ private synchronized void clearBusyQueue() {
+
+ if (busyTimestamps.size() == 0) {
+ return;
+ }
+
+ Set deleteFromQueue = new HashSet<>();
+
+ for (Long busyTimestamp : busyTimestamps) {
+
+ if (System.currentTimeMillis() > busyTimestamp) {
+ deleteFromQueue.add(busyTimestamp);
+ }
+ }
+
+ if (deleteFromQueue.size() == busyTimestamps.size()) {
+ busyTimestamps.clear();
+ //setEnableCustomAction(MedtronicCustomActionType.ClearBolusBlock, false);
+ }
+
+ if (deleteFromQueue.size() > 0) {
+ busyTimestamps.removeAll(deleteFromQueue);
+ }
+
+ }
+
+
+ @Override
+ public boolean isConnected() {
+ if (isLoggingEnabled() && displayConnectionMessages)
+ LOG.debug(getLogPrefix() + "isConnected");
+ return isServiceSet() && omnipodService.isInitialized();
+ }
+
+
+ @Override
+ public boolean isConnecting() {
+ if (isLoggingEnabled() && displayConnectionMessages)
+ LOG.debug(getLogPrefix() + "isConnecting");
+ return !isServiceSet() || !omnipodService.isInitialized();
+ }
+
+
+ @Override
+ public void getPumpStatus() {
+
+ if (firstRun) {
+ initializePump(!isRefresh);
+ }
+
+// getPodPumpStatus();
+//
+// if (firstRun) {
+// initializePump(!isRefresh);
+// } else {
+// refreshAnyStatusThatNeedsToBeRefreshed();
+// }
+//
+// MainApp.bus().post(new EventMedtronicPumpValuesChanged());
+ }
+
+
+ void resetStatusState() {
+ firstRun = true;
+ isRefresh = true;
+ }
+
+
+ private void setRefreshButtonEnabled(boolean enabled) {
+ OmnipodFragment.refreshButtonEnabled(enabled);
+ }
+
+
+ private void initializePump(boolean realInit) {
+
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "initializePump - start");
+
+ if (omnipodCommunicationManager == null) {
+ omnipodCommunicationManager = OmnipodCommunicationManager.getInstance();
+ }
+
+// setRefreshButtonEnabled(false);
+//
+// getPodPumpStatus();
+//
+// if (isRefresh) {
+// if (isPumpNotReachable()) {
+// if (isLoggingEnabled())
+// LOG.error(getLogPrefix() + "initializePump::Pump unreachable.");
+// MedtronicUtil.sendNotification(MedtronicNotificationType.PumpUnreachable);
+//
+// setRefreshButtonEnabled(true);
+//
+// return;
+// }
+//
+// MedtronicUtil.dismissNotification(MedtronicNotificationType.PumpUnreachable);
+// }
+//
+// this.pumpState = PumpDriverState.Connected;
+//
+// pumpStatusLocal.setLastCommunicationToNow();
+// setRefreshButtonEnabled(true);
+
+ // TODO need to read status and BasalProfile if pod inited and pod status and set correct commands enabled
+
+ if (!isRefresh) {
+ pumpState = PumpDriverState.Initialized;
+ }
+
+ if (!sentIdToFirebase) {
+ Bundle params = new Bundle();
+ params.putString("version", BuildConfig.VERSION);
+ MainApp.getFirebaseAnalytics().logEvent("OmnipodPumpInit", params);
+
+ sentIdToFirebase = true;
+ }
+
+ isInitialized = true;
+ // this.pumpState = PumpDriverState.Initialized;
+
+ this.firstRun = false;
+ }
+
+
+ @Override
+ public boolean isThisProfileSet(Profile profile) {
+
+ // status was not yet read from pod
+ if (currentProfile == null) {
+ return true;
+ }
+
+ return (currentProfile.isProfileTheSame(profile));
+ }
+
+
+ @Override
+ public long lastDataTime() {
+ getPodPumpStatusObject();
+
+ if (pumpStatusLocal.lastConnection != 0) {
+ return pumpStatusLocal.lastConnection;
+ }
+
+ return System.currentTimeMillis();
+ }
+
+
+ @Override
+ public double getBaseBasalRate() {
+
+ if (currentProfile != null) {
+ int hour = (new GregorianCalendar()).get(Calendar.HOUR_OF_DAY);
+ return currentProfile.getBasalTimeFromMidnight(getTimeInS(hour * 60));
+ } else {
+ return 0.0d;
+ }
+ }
+
+
+ @Override
+ public double getReservoirLevel() {
+ // TODO
+ return getPodPumpStatusObject().reservoirRemainingUnits;
+ }
+
+
+ @Override
+ public int getBatteryLevel() {
+ // TODO
+ return getPodPumpStatusObject().batteryRemaining;
+ }
+
+
+ private OmnipodPumpStatus getPodPumpStatusObject() {
+ if (pumpStatusLocal == null) {
+ // FIXME I don't know why this happens
+ if (isLoggingEnabled())
+ LOG.warn("!!!! Reset Pump Status Local");
+ pumpStatusLocal = OmnipodUtil.getPumpStatus();
+ }
+
+ return pumpStatusLocal;
+ }
+
+
+ protected void triggerUIChange() {
+ MainApp.bus().post(new EventOmnipodPumpValuesChanged());
+ }
+
+
+ @NonNull
+ protected PumpEnactResult deliverBolus(final DetailedBolusInfo detailedBolusInfo) {
+
+ LOG.info(getLogPrefix() + "deliverBolus - {}", detailedBolusInfo);
+
+ setRefreshButtonEnabled(false);
+
+ try {
+
+ OmnipodUITask responseTask = omnipodUIComm.executeCommand(OmnipodCommandType.SetBolus,
+ detailedBolusInfo.insulin);
+
+ Boolean response = (Boolean) responseTask.returnData;
+
+ setRefreshButtonEnabled(true);
+
+ if (response) {
+
+ TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
+
+ // we subtract insulin, exact amount will be visible with next remainingInsulin update.
+ getPodPumpStatusObject().reservoirRemainingUnits -= detailedBolusInfo.insulin;
+
+ incrementStatistics(detailedBolusInfo.isSMB ? OmnipodConst.Statistics.SMBBoluses
+ : OmnipodConst.Statistics.StandardBoluses);
+
+ // calculate time for bolus and set driver to busy for that time
+ // TODO fix this
+ int bolusTime = (int) (detailedBolusInfo.insulin * 42.0d);
+ long time = System.currentTimeMillis() + (bolusTime * 1000);
+
+ this.busyTimestamps.add(time);
+
+ return new PumpEnactResult().success(true) //
+ .enacted(true) //
+ .bolusDelivered(detailedBolusInfo.insulin) //
+ .carbsDelivered(detailedBolusInfo.carbs);
+
+ } else {
+ return new PumpEnactResult() //
+ .success(false) //
+ .enacted(false) //
+ .comment(MainApp.gs(R.string.medtronic_cmd_bolus_could_not_be_delivered));
+ }
+
+ } finally {
+ finishAction("Bolus");
+ }
+ }
+
+
+ private PumpEnactResult setNotReachable(boolean isBolus, boolean success) {
+ setRefreshButtonEnabled(true);
+
+ if (success) {
+ return new PumpEnactResult() //
+ .success(true) //
+ .enacted(false);
+ } else {
+ return new PumpEnactResult() //
+ .success(false) //
+ .enacted(false) //
+ .comment(MainApp.gs(R.string.medtronic_pump_status_pump_unreachable));
+ }
+ }
+
+
+ public void stopBolusDelivering() {
+
+ LOG.info(getLogPrefix() + "stopBolusDelivering");
+
+ setRefreshButtonEnabled(false);
+
+ try {
+
+ OmnipodUITask responseTask = omnipodUIComm.executeCommand(OmnipodCommandType.CancelBolus);
+
+ Boolean response = (Boolean) responseTask.returnData;
+
+ setRefreshButtonEnabled(true);
+
+ LOG.info(getLogPrefix() + "stopBolusDelivering - wasSuccess={}", response);
+
+ if (response) {
+ // TODO fix bolus record with cancel
+
+ //TreatmentsPlugin.getPlugin().addToHistoryTreatment(detailedBolusInfo, true);
+ }
+
+ } finally {
+ finishAction("Bolus");
+ }
+ }
+
+
+ private void incrementStatistics(String statsKey) {
+ long currentCount = SP.getLong(statsKey, 0L);
+ currentCount++;
+ SP.putLong(statsKey, currentCount);
+ }
+
+
+ // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged),
+ // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed
+ @Override
+ public PumpEnactResult setTempBasalAbsolute(Double absoluteRate, Integer durationInMinutes, Profile profile,
+ boolean enforceNew) {
+
+ getPodPumpStatusObject();
+
+ setRefreshButtonEnabled(false);
+
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setTempBasalAbsolute: rate: {}, duration={}", absoluteRate, durationInMinutes);
+
+ // read current TBR
+ TempBasalPair tbrCurrent = readTBR();
+
+ if (tbrCurrent != null) {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setTempBasalAbsolute: Current Basal: duration: {} min, rate={}",
+ tbrCurrent.getDurationMinutes(), tbrCurrent.getInsulinRate());
+ }
+
+ if (tbrCurrent != null && !enforceNew) {
+
+ if (OmnipodUtil.isSame(tbrCurrent.getInsulinRate(), absoluteRate)) {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setTempBasalAbsolute - No enforceNew and same rate. Exiting.");
+ finishAction("TBR");
+ return new PumpEnactResult().success(true).enacted(false);
+ }
+ }
+
+ // if TBR is running we will cancel it.
+ if (tbrCurrent != null) {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setTempBasalAbsolute - TBR running - so canceling it.");
+
+ // CANCEL
+ OmnipodUITask responseTask2 = omnipodUIComm.executeCommand(OmnipodCommandType.CancelTemporaryBasal);
+
+ Boolean response = (Boolean) responseTask2.returnData;
+
+ if (response) {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setTempBasalAbsolute - Current TBR cancelled.");
+ } else {
+ if (isLoggingEnabled())
+ LOG.error(getLogPrefix() + "setTempBasalAbsolute - Cancel TBR failed.");
+
+ finishAction("TBR");
+
+ return new PumpEnactResult().success(false).enacted(false)
+ .comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr_stop_op));
+ }
+ }
+
+ // now start new TBR
+ OmnipodUITask responseTask = omnipodUIComm.executeCommand(OmnipodCommandType.SetTemporaryBasal,
+ absoluteRate, durationInMinutes);
+
+ Boolean response = (Boolean) responseTask.returnData;
+
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setTempBasalAbsolute - setTBR. Response: " + response);
+
+ if (response) {
+ pumpStatusLocal.tempBasalStart = System.currentTimeMillis();
+ pumpStatusLocal.tempBasalAmount = absoluteRate;
+ pumpStatusLocal.tempBasalLength = durationInMinutes;
+ pumpStatusLocal.tempBasalEnd = getTimeInFutureFromMinutes(durationInMinutes);
+
+ TemporaryBasal tempStart = new TemporaryBasal() //
+ .date(System.currentTimeMillis()) //
+ .duration(durationInMinutes) //
+ .absolute(absoluteRate) //
+ .source(Source.USER);
+
+ TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempStart);
+
+ incrementStatistics(OmnipodConst.Statistics.TBRsSet);
+
+ finishAction("TBR");
+
+ return new PumpEnactResult().success(true).enacted(true) //
+ .absolute(absoluteRate).duration(durationInMinutes);
+
+ } else {
+ finishAction("TBR");
+
+ return new PumpEnactResult().success(false).enacted(false) //
+ .comment(MainApp.gs(R.string.medtronic_cmd_tbr_could_not_be_delivered));
+ }
+
+ }
+
+ private TempBasalPair readTBR() {
+ // TODO we can do it like this or read status from pod ??
+ if (pumpStatusLocal.tempBasalEnd < System.currentTimeMillis()) {
+ // TBR done
+ pumpStatusLocal.clearTemporaryBasal();
+
+ return null;
+ }
+
+ return pumpStatusLocal.getTemporaryBasal();
+ }
+
+
+ private void finishAction(String overviewKey) {
+ if (overviewKey != null)
+ MainApp.bus().post(new EventRefreshOverview(overviewKey));
+
+ triggerUIChange();
+
+ setRefreshButtonEnabled(true);
+ }
+
+
+ private long getTimeInFutureFromMinutes(int minutes) {
+ return System.currentTimeMillis() + getTimeInMs(minutes);
+ }
+
+
+ private long getTimeInMs(int minutes) {
+ return getTimeInS(minutes) * 1000L;
+ }
+
+ private int getTimeInS(int minutes) {
+ return minutes * 60;
+ }
+
+
+ @Override
+ public PumpEnactResult cancelTempBasal(boolean enforceNew) {
+
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "cancelTempBasal - started");
+
+ setRefreshButtonEnabled(false);
+
+ TempBasalPair tbrCurrent = readTBR();
+
+ if (tbrCurrent == null) {
+
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "cancelTempBasal - TBR already canceled.");
+ finishAction("TBR");
+ return new PumpEnactResult().success(true).enacted(false);
+
+ }
+
+ OmnipodUITask responseTask2 = omnipodUIComm.executeCommand(OmnipodCommandType.CancelTemporaryBasal);
+
+ Boolean response = (Boolean) responseTask2.returnData;
+
+ finishAction("TBR");
+
+ if (response) {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR successful.");
+
+ TemporaryBasal tempBasal = new TemporaryBasal() //
+ .date(System.currentTimeMillis()) //
+ .duration(0) //
+ .source(Source.USER);
+
+ TreatmentsPlugin.getPlugin().addToHistoryTempBasal(tempBasal);
+
+ return new PumpEnactResult().success(true).enacted(true) //
+ .isTempCancel(true);
+ } else {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "cancelTempBasal - Cancel TBR failed.");
+
+ return new PumpEnactResult().success(response).enacted(response) //
+ .comment(MainApp.gs(R.string.medtronic_cmd_cant_cancel_tbr));
+ }
+
+ }
+
+ @Override
+ public String serialNumber() {
+ return getPodPumpStatusObject().podNumber;
+ }
+
+ @Override
+ public PumpEnactResult setNewBasalProfile(Profile profile) {
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "setNewBasalProfile");
+
+ // this shouldn't be needed, but let's do check if profile setting we are setting is same as current one
+ if (this.currentProfile != null && this.currentProfile.isProfileTheSame(profile)) {
+ return new PumpEnactResult() //
+ .success(true) //
+ .enacted(false) //
+ .comment(MainApp.gs(R.string.medtronic_cmd_basal_profile_not_set_is_same));
+ }
+
+ setRefreshButtonEnabled(false);
+
+ OmnipodUITask responseTask = omnipodUIComm.executeCommand(OmnipodCommandType.SetBasalProfile,
+ profile);
+
+ Boolean response = (Boolean) responseTask.returnData;
+
+ if (isLoggingEnabled())
+ LOG.info(getLogPrefix() + "Basal Profile was set: " + response);
+
+ if (response) {
+ this.currentProfile = profile;
+ return new PumpEnactResult().success(true).enacted(true);
+ } else {
+ return new PumpEnactResult().success(response).enacted(response) //
+ .comment(MainApp.gs(R.string.medtronic_cmd_basal_profile_could_not_be_set));
+ }
+
+ }
+
+
+ // OPERATIONS not supported by Pump or Plugin
+
+ private List customActions = null;
+
+ private CustomAction customActionResetRLConfig = new CustomAction(
+ R.string.medtronic_custom_action_reset_rileylink, OmnipodCustomActionType.ResetRileyLinkConfiguration, true);
+
+ private CustomAction customActionInitPod = new CustomAction(
+ R.string.omnipod_cmd_init_pod, OmnipodCustomActionType.InitPod, true);
+
+ private CustomAction customActionDeactivatePod = new CustomAction(
+ R.string.omnipod_cmd_deactivate_pod, OmnipodCustomActionType.DeactivatePod, false);
+
+ private CustomAction customActionResetPod = new CustomAction(
+ R.string.omnipod_cmd_reset_pod, OmnipodCustomActionType.ResetPodStatus, true);
+
+
+ @Override
+ public List getCustomActions() {
+
+ if (customActions == null) {
+ this.customActions = Arrays.asList(
+ customActionResetRLConfig);
+ }
+
+ return this.customActions;
+ }
+
+ // TODO we need to brainstorm how we want to do this -- Andy
+ @Override
+ public void executeCustomAction(CustomActionType customActionType) {
+
+ OmnipodCustomActionType mcat = (OmnipodCustomActionType) customActionType;
+
+ switch (mcat) {
+
+ case ResetRileyLinkConfiguration: {
+ ServiceTaskExecutor.startTask(new ResetRileyLinkConfigurationTask());
+ }
+ break;
+
+ case InitPod: {
+ omnipodUIComm.executeCommand(OmnipodCommandType.InitPod);
+ }
+ break;
+
+ case DeactivatePod: {
+ omnipodUIComm.executeCommand(OmnipodCommandType.DeactivatePod);
+ }
+ break;
+
+ case ResetPodStatus: {
+ omnipodUIComm.executeCommand(OmnipodCommandType.ResetPodStatus);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+ @Override
+ public void timeDateOrTimeZoneChanged() {
+
+// if (isLoggingEnabled())
+// LOG.warn(getLogPrefix() + "Time, Date and/or TimeZone changed. ");
+//
+// this.hasTimeDateOrTimeZoneChanged = true;
+ }
+
+
+ public void setEnableCustomAction(OmnipodCustomActionType customAction, boolean isEnabled) {
+
+ switch (customAction) {
+
+ case InitPod: {
+ this.customActionInitPod.setEnabled(isEnabled);
+ }
+ break;
+
+ case DeactivatePod: {
+ this.customActionDeactivatePod.setEnabled(isEnabled);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ refreshCustomActionsList();
+ }
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java
new file mode 100644
index 0000000000..ec4d286313
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java
@@ -0,0 +1,121 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.comm;
+
+import android.content.Context;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType;
+import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair;
+import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.data.PodCommResponse;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+import info.nightscout.androidaps.utils.SP;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+public class OmnipodCommunicationManager extends RileyLinkCommunicationManager implements OmnipodCommunicationManagerInterface {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
+
+ private static OmnipodCommunicationManager omnipodCommunicationManager;
+ String errorMessage;
+
+
+ public OmnipodCommunicationManager(Context context, RFSpy rfspy) {
+ super(rfspy);
+ omnipodCommunicationManager = this;
+ OmnipodUtil.getPumpStatus().previousConnection = SP.getLong(
+ RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L);
+ }
+
+
+ public static OmnipodCommunicationManager getInstance() {
+ return omnipodCommunicationManager;
+ }
+
+
+ @Override
+ protected void configurePumpSpecificSettings() {
+ pumpStatus = MedtronicUtil.getPumpStatus();
+ }
+
+
+ @Override
+ public E createResponseMessage(byte[] payload, Class clazz) {
+ //PumpMessage pumpMessage = new PumpMessage(payload);
+ //eturn (E) pumpMessage;
+ return null;
+ }
+
+
+ @Override
+ public boolean tryToConnectToDevice() {
+ return false; //isDeviceReachable(true);
+ }
+
+
+ public String getErrorResponse() {
+ return this.errorMessage;
+ }
+
+
+ @Override
+ public byte[] createPumpMessageContent(RLMessageType type) {
+ return new byte[0];
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMPCOMM);
+ }
+
+
+ // This are just skeleton methods, we need to see what we can get returned and act accordingly
+
+ public PodCommResponse initPod() {
+ return null;
+ }
+
+
+ public PodCommResponse getPodStatus() {
+ return null;
+ }
+
+
+ public PodCommResponse deactivatePod() {
+ return null;
+ }
+
+ public PodCommResponse setBasalProfile(Profile profile) {
+ return null;
+ }
+
+ public PodCommResponse resetPodStatus() {
+ return null;
+ }
+
+ public PodCommResponse setBolus(Double parameter) {
+ return null;
+ }
+
+ public PodCommResponse cancelBolus() {
+ return null;
+ }
+
+ public PodCommResponse setTemporaryBasal(TempBasalPair tbr) {
+ return null;
+ }
+
+ public PodCommResponse cancelTemporaryBasal() {
+ return null;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManagerInterface.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManagerInterface.java
new file mode 100644
index 0000000000..02cae9d180
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManagerInterface.java
@@ -0,0 +1,61 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.comm;
+
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.data.PodCommResponse;
+
+public interface OmnipodCommunicationManagerInterface {
+
+ // TODO add methods that can be used by OmniPod Eros and Omnipod Dash
+
+ /**
+ * Initialize Pod
+ */
+ PodCommResponse initPod();
+
+ /**
+ * Get Pod Status (is pod running, battery left ?, reservoir, etc)
+ */
+ PodCommResponse getPodStatus();
+
+ /**
+ * Deactivate Pod
+ */
+ PodCommResponse deactivatePod();
+
+ /**
+ * Set Basal Profile
+ */
+ PodCommResponse setBasalProfile(Profile profile);
+
+ /**
+ * Reset Pod status (if we forget to disconnect Pod and want to init new pod, and want to forget current pod)
+ */
+ PodCommResponse resetPodStatus();
+
+ /**
+ * Set Bolus
+ *
+ * @param amount amount of bolus in U
+ */
+ PodCommResponse setBolus(Double amount);
+
+ /**
+ * Cancel Bolus (if bolus is already stopped, return acknowledgment)
+ */
+ PodCommResponse cancelBolus();
+
+ /**
+ * Set Temporary Basal
+ *
+ * @param tbr TempBasalPair object containg amount and duration in minutes
+ */
+ PodCommResponse setTemporaryBasal(TempBasalPair tbr);
+
+ /**
+ * Cancel Temporary Basal (if TB is already stopped, return acknowledgment)
+ */
+ PodCommResponse cancelTemporaryBasal();
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/data/PodCommResponse.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/data/PodCommResponse.java
new file mode 100644
index 0000000000..ebc7ccf966
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/data/PodCommResponse.java
@@ -0,0 +1,15 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.comm.data;
+
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodResponseType;
+
+public class PodCommResponse {
+
+ PodResponseType podResponseType;
+
+ Boolean acknowledged;
+ Object customData;
+ Object errorResponse;
+
+ // some status data if it can be returned (battery, reservoir, etc)
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUIComm.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUIComm.java
new file mode 100644
index 0000000000..09647186f7
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUIComm.java
@@ -0,0 +1,83 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.comm.ui;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+public class OmnipodUIComm {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
+
+ OmnipodCommunicationManager ocmInstance = null;
+ OmnipodUIPostprocessor uiPostprocessor = new OmnipodUIPostprocessor();
+
+
+ private OmnipodCommunicationManager getCommunicationManager() {
+ if (ocmInstance == null) {
+ ocmInstance = OmnipodCommunicationManager.getInstance();
+ }
+
+ return ocmInstance;
+ }
+
+
+ public synchronized OmnipodUITask executeCommand(OmnipodCommandType commandType, Object... parameters) {
+
+ if (isLogEnabled())
+ LOG.warn("Execute Command: " + commandType.name());
+
+ OmnipodUITask task = new OmnipodUITask(commandType, parameters);
+
+ OmnipodUtil.setCurrentCommand(commandType);
+
+ // new Thread(() -> {
+ // LOG.warn("@@@ Start Thread");
+ //
+ // task.execute(getCommunicationManager());
+ //
+ // LOG.warn("@@@ End Thread");
+ // });
+
+ task.execute(getCommunicationManager());
+
+ // for (int i = 0; i < getMaxWaitTime(commandType); i++) {
+ // synchronized (task) {
+ // // try {
+ // //
+ // // //task.wait(1000);
+ // // } catch (InterruptedException e) {
+ // // LOG.error("executeCommand InterruptedException", e);
+ // // }
+ //
+ //
+ // SystemClock.sleep(1000);
+ // }
+ //
+ // if (task.isReceived()) {
+ // break;
+ // }
+ // }
+
+ if (!task.isReceived() && isLogEnabled()) {
+ LOG.warn("Reply not received for " + commandType);
+ }
+
+ task.postProcess(uiPostprocessor);
+
+ return task;
+
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMP);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUIPostprocessor.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUIPostprocessor.java
new file mode 100644
index 0000000000..03d3a21504
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUIPostprocessor.java
@@ -0,0 +1,63 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.comm.ui;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCustomActionType;
+import info.nightscout.androidaps.plugins.pump.omnipod.service.OmnipodPumpStatus;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+
+public class OmnipodUIPostprocessor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
+
+ OmnipodPumpStatus pumpStatus;
+ OmnipodPumpPlugin omnipodPumpPlugin;
+
+
+ public OmnipodUIPostprocessor() {
+ pumpStatus = OmnipodUtil.getPumpStatus();
+ omnipodPumpPlugin = OmnipodPumpPlugin.getPlugin();
+ }
+
+
+ // this is mostly intended for command that return certain statuses (Remaining Insulin, ...), and
+ // where responses won't be directly used
+ public void postProcessData(OmnipodUITask uiTask) {
+
+ switch (uiTask.commandType) {
+
+ case InitPod: {
+ omnipodPumpPlugin.setEnableCustomAction(OmnipodCustomActionType.InitPod, false);
+ omnipodPumpPlugin.setEnableCustomAction(OmnipodCustomActionType.DeactivatePod, true);
+ }
+ break;
+
+ case DeactivatePod:
+ case ResetPodStatus: {
+ omnipodPumpPlugin.setEnableCustomAction(OmnipodCustomActionType.InitPod, true);
+ omnipodPumpPlugin.setEnableCustomAction(OmnipodCustomActionType.DeactivatePod, false);
+ }
+ break;
+
+
+ default:
+ if (isLogEnabled())
+ LOG.trace("Post-processing not implemented for {}.", uiTask.commandType.name());
+
+ }
+
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMP);
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUITask.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUITask.java
new file mode 100644
index 0000000000..350ea34f15
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/ui/OmnipodUITask.java
@@ -0,0 +1,184 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.comm.ui;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.data.Profile;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair;
+import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
+import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicPumpValuesChanged;
+import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodResponseType;
+import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+
+public class OmnipodUITask {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMP);
+
+ public OmnipodCommandType commandType;
+ public Object returnData;
+ private String errorDescription;
+ private Object[] parameters;
+ private PodResponseType responseType;
+
+
+ public OmnipodUITask(OmnipodCommandType commandType) {
+ this.commandType = commandType;
+ }
+
+
+ public OmnipodUITask(OmnipodCommandType commandType, Object... parameters) {
+ this.commandType = commandType;
+ this.parameters = parameters;
+ }
+
+
+ public void execute(OmnipodCommunicationManager communicationManager) {
+
+ if (isLogEnabled())
+ LOG.debug("OmnipodUITask: @@@ In execute. {}", commandType);
+
+ switch (commandType) {
+ // TODO add commands this is just sample
+// case PumpModel: {
+// returnData = communicationManager.getPumpModel();
+// }
+// break;
+
+ case InitPod:
+ returnData = communicationManager.initPod();
+ break;
+
+ case DeactivatePod:
+ returnData = communicationManager.deactivatePod();
+ break;
+
+ case ResetPodStatus:
+ returnData = communicationManager.resetPodStatus();
+ break;
+
+ case SetBasalProfile:
+ returnData = communicationManager.setBasalProfile((Profile) parameters[0]);
+ break;
+
+ case SetBolus: {
+ Double amount = getDoubleFromParameters(0);
+
+ if (amount != null)
+ returnData = communicationManager.setBolus(amount);
+ }
+ break;
+
+ case CancelBolus:
+ returnData = communicationManager.cancelBolus();
+ break;
+
+ case SetTemporaryBasal: {
+ TempBasalPair tbr = getTBRSettings();
+ if (tbr != null) {
+ returnData = communicationManager.setTemporaryBasal(tbr);
+ }
+ }
+ break;
+
+ case CancelTemporaryBasal:
+ returnData = communicationManager.cancelTemporaryBasal();
+ break;
+
+
+ default: {
+ LOG.warn("This commandType is not supported (yet) - {}.", commandType);
+ }
+
+ }
+
+ }
+
+
+ private TempBasalPair getTBRSettings() {
+ return new TempBasalPair(getDoubleFromParameters(0), //
+ false, //
+ getIntegerFromParameters(1));
+ }
+
+
+ private Float getFloatFromParameters(int index) {
+ return (Float) parameters[index];
+ }
+
+
+ public Double getDoubleFromParameters(int index) {
+ return (Double) parameters[index];
+ }
+
+
+ public Integer getIntegerFromParameters(int index) {
+ return (Integer) parameters[index];
+ }
+
+
+ public Object getResult() {
+ return returnData;
+ }
+
+
+ public boolean isReceived() {
+ return (returnData != null || errorDescription != null);
+ }
+
+
+ public void postProcess(OmnipodUIPostprocessor postprocessor) {
+
+ EventOmnipodDeviceStatusChange statusChange;
+ if (isLogEnabled())
+ LOG.debug("OmnipodUITask: @@@ In execute. {}", commandType);
+
+ if (responseType == PodResponseType.Data || responseType == PodResponseType.Acknowledgment) {
+ postprocessor.postProcessData(this);
+ }
+
+ if (responseType == PodResponseType.Invalid) {
+ statusChange = new EventOmnipodDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating,
+ "Unsupported command in OmnipodUITask");
+ MainApp.bus().post(statusChange);
+ } else if (responseType == PodResponseType.Error) {
+ statusChange = new EventOmnipodDeviceStatusChange(PumpDeviceState.ErrorWhenCommunicating,
+ errorDescription);
+ MainApp.bus().post(statusChange);
+ } else {
+ MainApp.bus().post(new EventMedtronicPumpValuesChanged());
+ MedtronicUtil.getPumpStatus().setLastCommunicationToNow();
+ }
+
+ MedtronicUtil.setCurrentCommand(null);
+ }
+
+
+ public boolean hasData() {
+ return (responseType == PodResponseType.Data || responseType == PodResponseType.Acknowledgment);
+ }
+
+
+ public Object getParameter(int index) {
+ return parameters[index];
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMP);
+ }
+
+
+ public PodResponseType getResponseType() {
+ return this.responseType;
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommandType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommandType.java
new file mode 100644
index 0000000000..ea0c74feb9
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommandType.java
@@ -0,0 +1,18 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.defs;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+public enum OmnipodCommandType {
+
+ InitPod, //
+ DeactivatePod, //
+ SetBasalProfile, //
+ SetBolus, //
+ CancelBolus, //
+ SetTemporaryBasal,
+ CancelTemporaryBasal,
+ ResetPodStatus;
+
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCustomActionType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCustomActionType.java
new file mode 100644
index 0000000000..bc75946c48
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCustomActionType.java
@@ -0,0 +1,22 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.defs;
+
+import info.nightscout.androidaps.plugins.general.actions.defs.CustomActionType;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+
+public enum OmnipodCustomActionType implements CustomActionType {
+
+ ResetRileyLinkConfiguration(), //
+ InitPod(), //
+ DeactivatePod(), //
+ ResetPodStatus(), //
+ ;
+
+ @Override
+ public String getKey() {
+ return this.name();
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodUIResponseType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodUIResponseType.java
new file mode 100644
index 0000000000..b135c3f590
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodUIResponseType.java
@@ -0,0 +1,13 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.defs;
+
+/**
+ * Created by andy on 10/18/18.
+ */
+
+public enum OmnipodUIResponseType {
+
+ Data,
+ Error,
+ Invalid;
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodDeviceState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodDeviceState.java
new file mode 100644
index 0000000000..5e903b5ae4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodDeviceState.java
@@ -0,0 +1,38 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.defs;
+
+import info.nightscout.androidaps.R;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+
+public enum PodDeviceState {
+
+ // FIXME
+ NeverContacted(R.string.medtronic_pump_status_never_contacted), //
+ Sleeping(R.string.medtronic_pump_status_sleeping), //
+ WakingUp(R.string.medtronic_pump_status_waking_up), //
+ Active(R.string.medtronic_pump_status_active), //
+ ErrorWhenCommunicating(R.string.medtronic_pump_status_error_comm), //
+ TimeoutWhenCommunicating(R.string.medtronic_pump_status_timeout_comm), //
+ // ProblemContacting(R.string.medtronic_pump_status_problem_contacting), //
+ PumpUnreachable(R.string.medtronic_pump_status_pump_unreachable), //
+ InvalidConfiguration(R.string.medtronic_pump_status_invalid_config);
+
+ Integer resourceId = null;
+
+
+ PodDeviceState() {
+
+ }
+
+
+ PodDeviceState(int resourceId) {
+ this.resourceId = resourceId;
+ }
+
+
+ public Integer getResourceId() {
+ return resourceId;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodResponseType.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodResponseType.java
new file mode 100644
index 0000000000..7314ae9591
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/PodResponseType.java
@@ -0,0 +1,9 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.defs;
+
+public enum PodResponseType {
+
+ Acknowledgment, // set commands would just acknowledge if data was sent
+ Data, // query commands would return data
+ Error, // communication/response produced an error
+ Invalid // invalid response (not supported, should never be returned)
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.java
new file mode 100644
index 0000000000..30be8cdb71
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.java
@@ -0,0 +1,47 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.events;
+
+import info.nightscout.androidaps.events.Event;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
+import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+public class EventOmnipodDeviceStatusChange extends Event {
+
+ public RileyLinkServiceState rileyLinkServiceState;
+ public RileyLinkError rileyLinkError;
+
+ public PumpDeviceState pumpDeviceState;
+ public String errorDescription;
+
+
+ public EventOmnipodDeviceStatusChange(RileyLinkServiceState rileyLinkServiceState) {
+ this(rileyLinkServiceState, null);
+ }
+
+
+ public EventOmnipodDeviceStatusChange(RileyLinkServiceState rileyLinkServiceState, RileyLinkError rileyLinkError) {
+ this.rileyLinkServiceState = rileyLinkServiceState;
+ this.rileyLinkError = rileyLinkError;
+ }
+
+
+ public EventOmnipodDeviceStatusChange(PumpDeviceState pumpDeviceState) {
+ this.pumpDeviceState = pumpDeviceState;
+ }
+
+
+ public EventOmnipodDeviceStatusChange(PumpDeviceState pumpDeviceState, String errorDescription) {
+ this.pumpDeviceState = pumpDeviceState;
+ this.errorDescription = errorDescription;
+ }
+
+
+ @Override
+ public String toString() {
+ return "EventOmnipodDeviceStatusChange [" + "rileyLinkServiceState=" + rileyLinkServiceState
+ + ", rileyLinkError=" + rileyLinkError + ", pumpDeviceState=" + pumpDeviceState + ']';
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodPumpValuesChanged.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodPumpValuesChanged.java
new file mode 100644
index 0000000000..b12b32007f
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodPumpValuesChanged.java
@@ -0,0 +1,9 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.events;
+
+import info.nightscout.androidaps.events.Event;
+
+/**
+ * Created by andy on 04.06.2018.
+ */
+public class EventOmnipodPumpValuesChanged extends Event {
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/OmnipodPumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/OmnipodPumpStatus.java
new file mode 100644
index 0000000000..af1b95c956
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/OmnipodPumpStatus.java
@@ -0,0 +1,157 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.service;
+
+import org.joda.time.LocalDateTime;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.interfaces.PumpDescription;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus;
+import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
+import info.nightscout.androidaps.plugins.pump.common.defs.PumpType;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkError;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+import info.nightscout.androidaps.utils.SP;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+public class OmnipodPumpStatus extends PumpStatus {
+
+ private static Logger LOG = LoggerFactory.getLogger(L.PUMP);
+
+ public String errorDescription = null;
+ public String rileyLinkAddress = null;
+ public boolean inPreInit = true;
+
+ // statuses
+ public RileyLinkServiceState rileyLinkServiceState = RileyLinkServiceState.NotStarted;
+ public RileyLinkError rileyLinkError;
+ public double currentBasal = 0;
+ public long tempBasalStart;
+ public long tempBasalEnd;
+ public Double tempBasalAmount = 0.0d;
+ public Integer tempBasalLength;
+
+ private boolean rileyLinkAddressChanged = false;
+ private String regexMac = "([\\da-fA-F]{1,2}(?:\\:|$)){6}";
+
+
+ public String podNumber;
+
+
+ public OmnipodPumpStatus(PumpDescription pumpDescription) {
+ super(pumpDescription);
+ }
+
+
+ @Override
+ public void initSettings() {
+ this.activeProfileName = "";
+ this.reservoirRemainingUnits = 75d;
+ this.batteryRemaining = 75;
+ this.lastConnection = SP.getLong(OmnipodConst.Statistics.LastGoodPumpCommunicationTime, 0L);
+ this.lastDataTime = new LocalDateTime(this.lastConnection);
+ this.pumpType = PumpType.Insulet_Omnipod;
+ }
+
+
+ public boolean verifyConfiguration() {
+ try {
+
+ this.errorDescription = "-";
+
+ String rileyLinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, null);
+
+ if (rileyLinkAddress == null) {
+ if (isLogEnabled())
+ LOG.debug("RileyLink address invalid: null");
+ this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid);
+ return false;
+ } else {
+ if (!rileyLinkAddress.matches(regexMac)) {
+ this.errorDescription = MainApp.gs(R.string.medtronic_error_rileylink_address_invalid);
+ if (isLogEnabled())
+ LOG.debug("RileyLink address invalid: {}", rileyLinkAddress);
+ } else {
+ if (!rileyLinkAddress.equals(this.rileyLinkAddress)) {
+ this.rileyLinkAddress = rileyLinkAddress;
+ rileyLinkAddressChanged = true;
+ }
+ }
+ }
+
+ reconfigureService();
+
+ return true;
+
+ } catch (Exception ex) {
+ this.errorDescription = ex.getMessage();
+ LOG.error("Error on Verification: " + ex.getMessage(), ex);
+ return false;
+ }
+ }
+
+
+ private boolean reconfigureService() {
+
+ if (!inPreInit && OmnipodUtil.getOmnipodService() != null) {
+
+ if (rileyLinkAddressChanged) {
+ OmnipodUtil.sendBroadcastMessage(RileyLinkConst.Intents.RileyLinkNewAddressSet);
+ rileyLinkAddressChanged = false;
+ }
+ }
+
+ return (!rileyLinkAddressChanged);
+ }
+
+
+ public String getErrorInfo() {
+ verifyConfiguration();
+
+ return (this.errorDescription == null) ? "-" : this.errorDescription;
+ }
+
+
+ @Override
+ public void refreshConfiguration() {
+ verifyConfiguration();
+ }
+
+
+ public boolean setNotInPreInit() {
+ this.inPreInit = false;
+
+ return reconfigureService();
+ }
+
+
+ public void clearTemporaryBasal() {
+ this.tempBasalStart = 0L;
+ this.tempBasalEnd = 0L;
+ this.tempBasalAmount = 0.0d;
+ this.tempBasalLength = 0;
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMP);
+ }
+
+ public TempBasalPair getTemporaryBasal() {
+
+ TempBasalPair tbr = new TempBasalPair();
+ tbr.setDurationMinutes(tempBasalLength);
+ tbr.setInsulinRate(tempBasalAmount);
+ tbr.setStartTime(tempBasalStart);
+ tbr.setEndTime(tempBasalEnd);
+
+ return tbr;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java
new file mode 100644
index 0000000000..67c280ce3c
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java
@@ -0,0 +1,155 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.service;
+
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.os.Binder;
+import android.os.IBinder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RFSpy;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLinkBLE;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkEncodingType;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkServiceState;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLinkTargetDevice;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkService;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData;
+import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
+import info.nightscout.androidaps.utils.SP;
+
+/**
+ * Created by andy on 4.8.2019
+ * RileyLinkOmnipodService is intended to stay running when the gui-app is closed.
+ */
+public class RileyLinkOmnipodService extends RileyLinkService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
+
+ private static RileyLinkOmnipodService instance;
+
+ OmnipodCommunicationManager omnipodCommunicationManager;
+ OmnipodPumpStatus pumpStatus = null;
+ private IBinder mBinder = new LocalBinder();
+
+
+ public RileyLinkOmnipodService() {
+ super(MainApp.instance().getApplicationContext());
+ instance = this;
+ if (isLogEnabled())
+ LOG.debug("RileyLinkOmnipodService newly constructed");
+ OmnipodUtil.setOmnipodService(this);
+ pumpStatus = (OmnipodPumpStatus) OmnipodPumpPlugin.getPlugin().getPumpStatusData();
+ }
+
+
+ public static RileyLinkOmnipodService getInstance() {
+ return instance;
+ }
+
+
+// public static MedtronicCommunicationManager getCommunicationManager() {
+// return instance.medtronicCommunicationManager;
+// }
+
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ if (isLogEnabled())
+ LOG.warn("onConfigurationChanged");
+ super.onConfigurationChanged(newConfig);
+ }
+
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mBinder;
+ }
+
+
+ @Override
+ public RileyLinkEncodingType getEncoding() {
+ return RileyLinkEncodingType.Manchester;
+ }
+
+
+ /**
+ * If you have customized RileyLinkServiceData you need to override this
+ */
+ public void initRileyLinkServiceData() {
+
+ rileyLinkServiceData = new RileyLinkServiceData(RileyLinkTargetDevice.Omnipod);
+
+ RileyLinkUtil.setRileyLinkServiceData(rileyLinkServiceData);
+ RileyLinkUtil.setTargetDevice(RileyLinkTargetDevice.Omnipod);
+
+ // get most recently used RileyLink address
+ rileyLinkServiceData.rileylinkAddress = SP.getString(RileyLinkConst.Prefs.RileyLinkAddress, "");
+
+ rileyLinkBLE = new RileyLinkBLE(this.context); // or this
+ rfspy = new RFSpy(rileyLinkBLE);
+ rfspy.startReader();
+
+ RileyLinkUtil.setRileyLinkBLE(rileyLinkBLE);
+
+ // init rileyLinkCommunicationManager
+ omnipodCommunicationManager = new OmnipodCommunicationManager(context, rfspy);
+ }
+
+
+ public void resetRileyLinkConfiguration() {
+ rfspy.resetRileyLinkConfiguration();
+ }
+
+
+ @Override
+ public RileyLinkCommunicationManager getDeviceCommunicationManager() {
+ return this.omnipodCommunicationManager;
+ }
+
+
+ public class LocalBinder extends Binder {
+
+ public RileyLinkOmnipodService getServiceInstance() {
+ return RileyLinkOmnipodService.this;
+ }
+ }
+
+
+ /* private functions */
+
+ // PumpInterface - REMOVE
+
+ public boolean isInitialized() {
+ return RileyLinkServiceState.isReady(RileyLinkUtil.getRileyLinkServiceData().serviceState);
+ }
+
+
+ @Override
+ public String getDeviceSpecificBroadcastsIdentifierPrefix() {
+ return null;
+ }
+
+
+ public boolean handleDeviceSpecificBroadcasts(Intent intent) {
+ return false;
+ }
+
+
+ @Override
+ public void registerDeviceSpecificBroadcasts(IntentFilter intentFilter) {
+ }
+
+
+ private boolean isLogEnabled() {
+ return L.isEnabled(L.PUMPCOMM);
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java
new file mode 100644
index 0000000000..0364541af4
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java
@@ -0,0 +1,28 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.util;
+
+/**
+ * Created by andy on 4.8.2019
+ */
+
+public class OmnipodConst {
+
+ static final String Prefix = "AAPS.Omnipod.";
+
+ public class Prefs {
+
+ //public static final int BatteryType = R.string.pref_key_medtronic_battery_type;
+ }
+
+ public class Statistics {
+
+ public static final String StatsPrefix = "omnipod_";
+ public static final String FirstPumpStart = Prefix + "first_pump_use";
+ public static final String LastGoodPumpCommunicationTime = Prefix + "lastGoodPumpCommunicationTime";
+ public static final String LastGoodPumpFrequency = Prefix + "LastGoodPumpFrequency";
+ public static final String TBRsSet = StatsPrefix + "tbrs_set";
+ public static final String StandardBoluses = StatsPrefix + "std_boluses_delivered";
+ public static final String SMBBoluses = StatsPrefix + "smb_boluses_delivered";
+ public static final String LastPumpHistoryEntry = StatsPrefix + "pump_history_entry";
+ }
+
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java
new file mode 100644
index 0000000000..1e3f6e9214
--- /dev/null
+++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java
@@ -0,0 +1,170 @@
+package info.nightscout.androidaps.plugins.pump.omnipod.util;
+
+import android.content.Context;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+import info.nightscout.androidaps.MainApp;
+import info.nightscout.androidaps.R;
+import info.nightscout.androidaps.logging.L;
+import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification;
+import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification;
+import info.nightscout.androidaps.plugins.general.overview.notifications.Notification;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkUtil;
+import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.data.RLHistoryItem;
+import info.nightscout.androidaps.plugins.pump.medtronic.defs.MedtronicNotificationType;
+import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager;
+import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType;
+import info.nightscout.androidaps.plugins.pump.omnipod.service.OmnipodPumpStatus;
+import info.nightscout.androidaps.plugins.pump.omnipod.service.RileyLinkOmnipodService;
+import info.nightscout.androidaps.utils.OKDialog;
+
+/**
+ * Created by andy on 4/8/19.
+ */
+// FIXME
+public class OmnipodUtil extends RileyLinkUtil {
+
+ private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
+
+ private static boolean lowLevelDebug = true;
+ private static RileyLinkOmnipodService omnipodService;
+ private static OmnipodPumpStatus omnipodPumpStatus;
+ private static OmnipodCommandType currentCommand;
+ public static Gson gsonInstance = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
+ public static Gson gsonInstancePretty = new GsonBuilder().excludeFieldsWithoutExposeAnnotation()
+ .setPrettyPrinting().create();
+
+
+ public static Gson getGsonInstance() {
+ return gsonInstance;
+ }
+
+ public static Gson getGsonInstancePretty() {
+ return gsonInstancePretty;
+ }
+
+
+ public static int makeUnsignedShort(int b2, int b1) {
+ int k = (b2 & 0xff) << 8 | b1 & 0xff;
+ return k;
+ }
+
+ public static byte[] getByteArrayFromUnsignedShort(int shortValue, boolean returnFixedSize) {
+ byte highByte = (byte) (shortValue >> 8 & 0xFF);
+ byte lowByte = (byte) (shortValue & 0xFF);
+
+ if (highByte > 0) {
+ return createByteArray(highByte, lowByte);
+ } else {
+ return returnFixedSize ? createByteArray(highByte, lowByte) : createByteArray(lowByte);
+ }
+
+ }
+
+
+ public static byte[] createByteArray(byte... data) {
+ return data;
+ }
+
+
+ public static byte[] createByteArray(List data) {
+
+ byte[] array = new byte[data.size()];
+
+ for (int i = 0; i < data.size(); i++) {
+ array[i] = data.get(i);
+ }
+
+ return array;
+ }
+
+
+ public static void sendNotification(MedtronicNotificationType notificationType) {
+ Notification notification = new Notification( //
+ notificationType.getNotificationType(), //
+ MainApp.gs(notificationType.getResourceId()), //
+ notificationType.getNotificationUrgency());
+ MainApp.bus().post(new EventNewNotification(notification));
+ }
+
+
+ public static void sendNotification(MedtronicNotificationType notificationType, Object... parameters) {
+ Notification notification = new Notification( //
+ notificationType.getNotificationType(), //
+ MainApp.gs(notificationType.getResourceId(), parameters), //
+ notificationType.getNotificationUrgency());
+ MainApp.bus().post(new EventNewNotification(notification));
+ }
+
+
+ public static void dismissNotification(MedtronicNotificationType notificationType) {
+ MainApp.bus().post(new EventDismissNotification(notificationType.getNotificationType()));
+ }
+
+
+ public static boolean isLowLevelDebug() {
+ return lowLevelDebug;
+ }
+
+
+ public static void setLowLevelDebug(boolean lowLevelDebug) {
+ OmnipodUtil.lowLevelDebug = lowLevelDebug;
+ }
+
+
+ public static OmnipodCommunicationManager getOmnipodCommunicationManager() {
+ return (OmnipodCommunicationManager) RileyLinkUtil.rileyLinkCommunicationManager;
+ }
+
+
+ public static RileyLinkOmnipodService getOmnipodService() {
+ return OmnipodUtil.omnipodService;
+ }
+
+
+ public static void setOmnipodService(RileyLinkOmnipodService medtronicService) {
+ OmnipodUtil.omnipodService = medtronicService;
+ }
+
+ public static OmnipodCommandType getCurrentCommand() {
+ return OmnipodUtil.currentCommand;
+ }
+
+
+ // FIXME
+ public static void setCurrentCommand(OmnipodCommandType currentCommand) {
+ OmnipodUtil.currentCommand = currentCommand;
+
+ if (currentCommand != null)
+ historyRileyLink.add(new RLHistoryItem(currentCommand));
+
+ }
+
+
+ public static boolean isSame(Double d1, Double d2) {
+ double diff = d1 - d2;
+
+ return (Math.abs(diff) <= 0.000001);
+ }
+
+
+ public static void displayNotConfiguredDialog(Context context) {
+ OKDialog.show(context, MainApp.gs(R.string.combo_warning),
+ MainApp.gs(R.string.medtronic_error_operation_not_possible_no_configuration), null);
+ }
+
+ public static OmnipodPumpStatus getPumpStatus() {
+ return omnipodPumpStatus;
+ }
+
+ public static void setPumpStatus(OmnipodPumpStatus omnipodPumpStatus) {
+ OmnipodUtil.omnipodPumpStatus = omnipodPumpStatus;
+ }
+}
diff --git a/app/src/main/java/info/nightscout/androidaps/utils/Round.java b/app/src/main/java/info/nightscout/androidaps/utils/Round.java
index ba7f7e3f86..b8e8d65ce4 100644
--- a/app/src/main/java/info/nightscout/androidaps/utils/Round.java
+++ b/app/src/main/java/info/nightscout/androidaps/utils/Round.java
@@ -10,16 +10,25 @@ public class Round {
}
return 0d;
}
+
public static Double floorTo(Double x, Double step) {
if (x != 0d) {
return Math.floor(x / step) * step;
}
return 0d;
}
+
public static Double ceilTo(Double x, Double step) {
if (x != 0d) {
return Math.ceil(x / step) * step;
}
return 0d;
}
+
+ public static boolean isSame(Double d1, Double d2) {
+ double diff = d1 - d2;
+
+ return (Math.abs(diff) <= 0.000001);
+ }
+
}
diff --git a/app/src/main/res/layout/omnipod_fragment.xml b/app/src/main/res/layout/omnipod_fragment.xml
new file mode 100644
index 0000000000..e017a35329
--- /dev/null
+++ b/app/src/main/res/layout/omnipod_fragment.xml
@@ -0,0 +1,533 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index dafefab09a..e04734f77a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1557,6 +1557,31 @@
No connection for %1$d hour(s) %2$d min
No connection for %1$d day(s) %2$d hours
+
+
+
+ Omnipod
+ POD
+ Pump integration for Omnipod, requires RileyLink (with at least 2.0 firmware) device.
+
+
+ Pod Mgmt
+ Pod Status
+
+
+ Operation is not possible.\n\n You need to configure Omnipod first, before you can use this operation.
+
+
+ Init Pod
+ Deactivate Pod
+ Reset Pod
+
+
+ Omnipod
+ Omnipod
+ Omnipod
+
+
- %1$d day
- %1$d days
diff --git a/app/src/main/res/xml/pref_omnipod.xml b/app/src/main/res/xml/pref_omnipod.xml
new file mode 100644
index 0000000000..ab78d0dc8e
--- /dev/null
+++ b/app/src/main/res/xml/pref_omnipod.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file