Merge branch 'omnipod_eros' of https://github.com/AAPS-Omnipod/AndroidAPS into omnipod_eros
This commit is contained in:
commit
b4abf00d98
|
@ -164,10 +164,6 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
|
||||||
// We actually ignore previous (ack) responses if it was not last packet to send
|
// We actually ignore previous (ack) responses if it was not last packet to send
|
||||||
response = exchangePackets(podState, packet);
|
response = exchangePackets(podState, packet);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// If this is not the last packet, the message wasn't fully sent,
|
|
||||||
// so it's impossible for the pod to have received the message
|
|
||||||
boolean isCertainFailure = encodedMessage.length > 0;
|
|
||||||
|
|
||||||
OmnipodException newException;
|
OmnipodException newException;
|
||||||
if (ex instanceof OmnipodException) {
|
if (ex instanceof OmnipodException) {
|
||||||
newException = (OmnipodException) ex;
|
newException = (OmnipodException) ex;
|
||||||
|
@ -175,10 +171,15 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
|
||||||
newException = new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
|
newException = new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean lastPacket = encodedMessage.length == 0;
|
||||||
|
|
||||||
|
// If this is not the last packet, the message wasn't fully sent,
|
||||||
|
// so it's impossible for the pod to have received the message
|
||||||
|
newException.setCertainFailure(!lastPacket);
|
||||||
|
|
||||||
if (isLoggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.debug("Caught exception in transportMessages. Setting certainFailure to {} because encodedMessage.length={}", isCertainFailure, encodedMessage.length);
|
LOG.debug("Caught exception in transportMessages. Set certainFailure to {} because encodedMessage.length={}", newException.isCertainFailure(), encodedMessage.length);
|
||||||
}
|
}
|
||||||
newException.setCertainFailure(isCertainFailure);
|
|
||||||
|
|
||||||
throw newException;
|
throw newException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,6 +83,9 @@ public class OmnipodManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Single<SetupActionResult> pairAndPrime() {
|
public synchronized Single<SetupActionResult> pairAndPrime() {
|
||||||
|
logStartingCommandExecution("pairAndPrime");
|
||||||
|
|
||||||
|
try {
|
||||||
if (podState == null) {
|
if (podState == null) {
|
||||||
podState = communicationService.executeAction(
|
podState = communicationService.executeAction(
|
||||||
new PairAction(new PairService(), podStateChangedHandler));
|
new PairAction(new PairService(), podStateChangedHandler));
|
||||||
|
@ -92,7 +95,9 @@ public class OmnipodManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
communicationService.executeAction(new PrimeAction(new PrimeService(), podState));
|
communicationService.executeAction(new PrimeAction(new PrimeService(), podState));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("pairAndPrime");
|
||||||
|
}
|
||||||
long delayInSeconds = calculateBolusDuration(OmnipodConst.POD_PRIME_BOLUS_UNITS, OmnipodConst.POD_PRIMING_DELIVERY_RATE).getStandardSeconds();
|
long delayInSeconds = calculateBolusDuration(OmnipodConst.POD_PRIME_BOLUS_UNITS, OmnipodConst.POD_PRIMING_DELIVERY_RATE).getStandardSeconds();
|
||||||
|
|
||||||
return Single.timer(delayInSeconds, TimeUnit.SECONDS) //
|
return Single.timer(delayInSeconds, TimeUnit.SECONDS) //
|
||||||
|
@ -108,9 +113,16 @@ public class OmnipodManager {
|
||||||
throw new IllegalSetupProgressException(SetupProgress.CANNULA_INSERTING, podState.getSetupProgress());
|
throw new IllegalSetupProgressException(SetupProgress.CANNULA_INSERTING, podState.getSetupProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podState, basalSchedule));
|
communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podState, basalSchedule));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("insertCannula");
|
||||||
|
}
|
||||||
|
|
||||||
long delayInSeconds = calculateBolusDuration(OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConst.POD_CANNULA_INSERTION_DELIVERY_RATE).getStandardSeconds();
|
long delayInSeconds = calculateBolusDuration(OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConst.POD_CANNULA_INSERTION_DELIVERY_RATE).getStandardSeconds();
|
||||||
|
|
||||||
return Single.timer(delayInSeconds, TimeUnit.SECONDS) //
|
return Single.timer(delayInSeconds, TimeUnit.SECONDS) //
|
||||||
.map(o -> verifySetupAction(statusResponse ->
|
.map(o -> verifySetupAction(statusResponse ->
|
||||||
InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse), SetupProgress.COMPLETED)) //
|
InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse), SetupProgress.COMPLETED)) //
|
||||||
|
@ -122,40 +134,109 @@ public class OmnipodManager {
|
||||||
throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, null);
|
throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("getPodStatus");
|
||||||
|
|
||||||
|
try {
|
||||||
return communicationService.executeAction(new GetStatusAction(podState));
|
return communicationService.executeAction(new GetStatusAction(podState));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("getPodStatus");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized PodInfoResponse getPodInfo(PodInfoType podInfoType) {
|
public synchronized PodInfoResponse getPodInfo(PodInfoType podInfoType) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("getPodInfo");
|
||||||
|
|
||||||
|
try {
|
||||||
return communicationService.executeAction(new GetPodInfoAction(podState, podInfoType));
|
return communicationService.executeAction(new GetPodInfoAction(podState, podInfoType));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("getPodInfo");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void acknowledgeAlerts() {
|
public synchronized void acknowledgeAlerts() {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("acknowledgeAlerts");
|
||||||
|
|
||||||
|
try {
|
||||||
executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podState, podState.getActiveAlerts())));
|
executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podState, podState.getActiveAlerts())));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("acknowledgeAlerts");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CAUTION: cancels all delivery
|
||||||
|
// CAUTION: suspends and then resumes delivery. An OmnipodException[certainFailure=false] indicates that the pod is or might be suspended
|
||||||
public synchronized void setBasalSchedule(BasalSchedule schedule, boolean acknowledgementBeep) {
|
public synchronized void setBasalSchedule(BasalSchedule schedule, boolean acknowledgementBeep) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("setBasalSchedule [basalSchedule=" + schedule + ", acknowledgementBeep=" + acknowledgementBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Never emit a beep for suspending delivery, so if the user has beeps enabled,
|
||||||
|
// they can verify that setting the basal schedule succeeded (not suspending the delivery)
|
||||||
|
cancelDelivery(EnumSet.allOf(DeliveryType.class), false);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logCommandExecutionFinished("setBasalSchedule");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, schedule,
|
executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, schedule,
|
||||||
false, podState.getScheduleOffset(), acknowledgementBeep)));
|
false, podState.getScheduleOffset(), acknowledgementBeep)));
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
// Treat all exceptions as uncertain failures, because all delivery has been suspended here.
|
||||||
|
// Setting this to an uncertain failure will enable for the user to get an appropriate warning
|
||||||
|
ex.setCertainFailure(false);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("setBasalSchedule");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void setTemporaryBasal(TempBasalPair tempBasalPair, boolean acknowledgementBeep, boolean completionBeep) {
|
public synchronized void setTemporaryBasal(TempBasalPair tempBasalPair, boolean acknowledgementBeep, boolean completionBeep) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("setTemporaryBasal [tempBasalPair=" + tempBasalPair + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction(new SetTempBasalService(),
|
executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction(new SetTempBasalService(),
|
||||||
podState, tempBasalPair.getInsulinRate(), Duration.standardMinutes(tempBasalPair.getDurationMinutes()),
|
podState, tempBasalPair.getInsulinRate(), Duration.standardMinutes(tempBasalPair.getDurationMinutes()),
|
||||||
acknowledgementBeep, completionBeep)));
|
acknowledgementBeep, completionBeep)));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("setTemporaryBasal");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void cancelTemporaryBasal(boolean acknowledgementBeep) {
|
public synchronized void cancelTemporaryBasal(boolean acknowledgementBeep) {
|
||||||
|
cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep);
|
||||||
|
}
|
||||||
|
|
||||||
|
private synchronized void cancelDelivery(EnumSet<DeliveryType> deliveryTypes, boolean acknowledgementBeep) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
executeAndVerify(() -> communicationService.executeAction(new CancelDeliveryAction(podState, DeliveryType.TEMP_BASAL, acknowledgementBeep)));
|
logStartingCommandExecution("cancelDelivery [deliveryTypes=" + deliveryTypes + ", acknowledgementBeep=" + acknowledgementBeep + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// As the cancel delivery command is a single packet command,
|
||||||
|
// first verify that the pod is reachable by obtaining a status response
|
||||||
|
// FIXME is this actually necessary?
|
||||||
|
StatusResponse podStatus = getPodStatus();
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
logCommandExecutionFinished("cancelDelivery");
|
||||||
|
ex.setCertainFailure(true);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
executeAndVerify(() -> communicationService.executeAction(new CancelDeliveryAction(podState, deliveryTypes, acknowledgementBeep)));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("cancelDelivery");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a SingleSubject that returns when the bolus has finished.
|
// Returns a SingleSubject that returns when the bolus has finished.
|
||||||
|
@ -164,6 +245,8 @@ public class OmnipodManager {
|
||||||
public synchronized BolusCommandResult bolus(Double units, boolean acknowledgementBeep, boolean completionBeep, BolusProgressIndicationConsumer progressIndicationConsumer) {
|
public synchronized BolusCommandResult bolus(Double units, boolean acknowledgementBeep, boolean completionBeep, BolusProgressIndicationConsumer progressIndicationConsumer) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
|
logStartingCommandExecution("bolus [units=" + units + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]");
|
||||||
|
|
||||||
CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS;
|
CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -178,6 +261,8 @@ public class OmnipodManager {
|
||||||
LOG.error("Caught exception[certainFailure=false] in bolus", ex);
|
LOG.error("Caught exception[certainFailure=false] in bolus", ex);
|
||||||
}
|
}
|
||||||
commandDeliveryStatus = CommandDeliveryStatus.UNCERTAIN_FAILURE;
|
commandDeliveryStatus = CommandDeliveryStatus.UNCERTAIN_FAILURE;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("bolus");
|
||||||
}
|
}
|
||||||
|
|
||||||
DateTime startDate = DateTime.now().minus(OmnipodConst.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION);
|
DateTime startDate = DateTime.now().minus(OmnipodConst.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION);
|
||||||
|
@ -245,12 +330,16 @@ public class OmnipodManager {
|
||||||
throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podState.getLastDeliveryStatus());
|
throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podState.getLastDeliveryStatus());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("cancelBolus [acknowledgementBeep=" + acknowledgementBeep + "]");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
executeAndVerify(() -> communicationService.executeAction(new CancelDeliveryAction(podState, DeliveryType.BOLUS, acknowledgementBeep)));
|
cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep);
|
||||||
} catch (PodFaultException ex) {
|
} catch (PodFaultException ex) {
|
||||||
if (isLoggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.info("Ignoring PodFaultException in cancelBolus", ex);
|
LOG.info("Ignoring PodFaultException in cancelBolus", ex);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("cancelBolus");
|
||||||
}
|
}
|
||||||
|
|
||||||
activeBolusData.getDisposables().dispose();
|
activeBolusData.getDisposables().dispose();
|
||||||
|
@ -259,33 +348,54 @@ public class OmnipodManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CAUTION: cancels TBR and bolus
|
|
||||||
public synchronized void suspendDelivery(boolean acknowledgementBeep) {
|
public synchronized void suspendDelivery(boolean acknowledgementBeep) {
|
||||||
assertReadyForDelivery();
|
cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeep);
|
||||||
|
|
||||||
executeAndVerify(() -> communicationService.executeAction(new CancelDeliveryAction(podState, EnumSet.allOf(DeliveryType.class), acknowledgementBeep)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Same as setting basal schedule, but without suspending delivery first
|
||||||
public synchronized void resumeDelivery(boolean acknowledgementBeep) {
|
public synchronized void resumeDelivery(boolean acknowledgementBeep) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
logStartingCommandExecution("resumeDelivery");
|
||||||
|
|
||||||
|
try {
|
||||||
executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, podState.getBasalSchedule(),
|
executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, podState.getBasalSchedule(),
|
||||||
true, podState.getScheduleOffset(), acknowledgementBeep)));
|
false, podState.getScheduleOffset(), acknowledgementBeep)));
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("resumeDelivery");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CAUTION: cancels TBR and bolus
|
// CAUTION: cancels all delivery
|
||||||
// CAUTION: suspends and then resumes delivery.
|
// CAUTION: suspends and then resumes delivery. An OmnipodException[certainFailure=false] indicates that the pod is or might be suspended
|
||||||
// If any error occurs during the command sequence, delivery could be suspended
|
|
||||||
public synchronized void setTime(boolean acknowledgementBeeps) {
|
public synchronized void setTime(boolean acknowledgementBeeps) {
|
||||||
assertReadyForDelivery();
|
assertReadyForDelivery();
|
||||||
|
|
||||||
suspendDelivery(acknowledgementBeeps);
|
logStartingCommandExecution("setTime [acknowledgementBeeps=" + acknowledgementBeeps + "]");
|
||||||
|
|
||||||
|
try {
|
||||||
|
cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeeps);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logCommandExecutionFinished("setTime");
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTimeZone oldTimeZone = podState.getTimeZone();
|
||||||
|
|
||||||
|
try {
|
||||||
// Joda seems to cache the default time zone, so we use the JVM's
|
// Joda seems to cache the default time zone, so we use the JVM's
|
||||||
DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault()));
|
DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault()));
|
||||||
podState.setTimeZone(DateTimeZone.getDefault());
|
podState.setTimeZone(DateTimeZone.getDefault());
|
||||||
|
|
||||||
resumeDelivery(acknowledgementBeeps);
|
setBasalSchedule(podState.getBasalSchedule(), acknowledgementBeeps);
|
||||||
|
} catch (OmnipodException ex) {
|
||||||
|
// Treat all exceptions as uncertain failures, because all delivery has been suspended here.
|
||||||
|
// Setting this to an uncertain failure will enable for the user to get an appropriate warning
|
||||||
|
podState.setTimeZone(oldTimeZone);
|
||||||
|
ex.setCertainFailure(false);
|
||||||
|
throw ex;
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("setTime");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void deactivatePod() {
|
public synchronized void deactivatePod() {
|
||||||
|
@ -293,6 +403,8 @@ public class OmnipodManager {
|
||||||
throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, null);
|
throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logStartingCommandExecution("deactivatePod");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Never send acknowledgement beeps here. Matches the PDM's behavior
|
// Never send acknowledgement beeps here. Matches the PDM's behavior
|
||||||
executeAndVerify(() -> communicationService.executeAction(new DeactivatePodAction(podState, false)));
|
executeAndVerify(() -> communicationService.executeAction(new DeactivatePodAction(podState, false)));
|
||||||
|
@ -300,6 +412,8 @@ public class OmnipodManager {
|
||||||
if (isLoggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.info("Ignoring PodFaultException in deactivatePod", ex);
|
LOG.info("Ignoring PodFaultException in deactivatePod", ex);
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
logCommandExecutionFinished("deactivatePod");
|
||||||
}
|
}
|
||||||
|
|
||||||
resetPodState();
|
resetPodState();
|
||||||
|
@ -416,6 +530,18 @@ public class OmnipodManager {
|
||||||
return CommandDeliveryStatus.SUCCESS;
|
return CommandDeliveryStatus.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logStartingCommandExecution(String action) {
|
||||||
|
if (isLoggingEnabled()) {
|
||||||
|
LOG.debug("Starting command execution for action: " + action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logCommandExecutionFinished(String action) {
|
||||||
|
if (isLoggingEnabled()) {
|
||||||
|
LOG.debug("Command execution finished for action: " + action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isLoggingEnabled() {
|
private boolean isLoggingEnabled() {
|
||||||
return L.isEnabled(L.PUMP);
|
return L.isEnabled(L.PUMP);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,7 @@ public enum DeliveryType {
|
||||||
NONE((byte) 0x00),
|
NONE((byte) 0x00),
|
||||||
BASAL((byte) 0x01),
|
BASAL((byte) 0x01),
|
||||||
TEMP_BASAL((byte) 0x02),
|
TEMP_BASAL((byte) 0x02),
|
||||||
BOLUS((byte) 0x04),
|
BOLUS((byte) 0x04);
|
||||||
EXTENDED_BOLUS((byte) 0x08);
|
|
||||||
|
|
||||||
private byte value;
|
private byte value;
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,9 @@ public class BasalSchedule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "BasalSchedule (" + entries.size() + " entries)";
|
return "BasalSchedule{" +
|
||||||
|
"entries=" + entries +
|
||||||
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BasalScheduleDurationEntry {
|
public static class BasalScheduleDurationEntry {
|
||||||
|
|
|
@ -2,7 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule;
|
||||||
|
|
||||||
import org.joda.time.Duration;
|
import org.joda.time.Duration;
|
||||||
|
|
||||||
import info.nightscout.androidaps.Constants;
|
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
|
||||||
|
|
||||||
public class BasalScheduleEntry {
|
public class BasalScheduleEntry {
|
||||||
|
@ -31,7 +30,7 @@ public class BasalScheduleEntry {
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "BasalScheduleEntry{" +
|
return "BasalScheduleEntry{" +
|
||||||
"rate=" + rate +
|
"rate=" + rate +
|
||||||
", startTime=" + startTime +
|
", startTime=" + startTime.getStandardSeconds() + "s" +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,15 @@ import info.nightscout.androidaps.MainApp;
|
||||||
import info.nightscout.androidaps.R;
|
import info.nightscout.androidaps.R;
|
||||||
import info.nightscout.androidaps.data.Profile;
|
import info.nightscout.androidaps.data.Profile;
|
||||||
import info.nightscout.androidaps.data.PumpEnactResult;
|
import info.nightscout.androidaps.data.PumpEnactResult;
|
||||||
|
import info.nightscout.androidaps.db.Source;
|
||||||
|
import info.nightscout.androidaps.db.TemporaryBasal;
|
||||||
import info.nightscout.androidaps.events.Event;
|
import info.nightscout.androidaps.events.Event;
|
||||||
import info.nightscout.androidaps.logging.L;
|
import info.nightscout.androidaps.logging.L;
|
||||||
import info.nightscout.androidaps.plugins.bus.RxBus;
|
import info.nightscout.androidaps.plugins.bus.RxBus;
|
||||||
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
|
import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
|
import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair;
|
||||||
import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType;
|
import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService;
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager;
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult;
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.SetupActionResult;
|
||||||
|
@ -31,6 +34,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.Sta
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
|
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot;
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType;
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType;
|
||||||
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface;
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType;
|
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType;
|
||||||
|
@ -59,6 +63,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodExceptio
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodFaultException;
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodFaultException;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodReturnedErrorResponseException;
|
import info.nightscout.androidaps.plugins.pump.omnipod.exception.PodReturnedErrorResponseException;
|
||||||
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
|
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil;
|
||||||
|
import info.nightscout.androidaps.plugins.treatments.TreatmentsPlugin;
|
||||||
import io.reactivex.disposables.Disposable;
|
import io.reactivex.disposables.Disposable;
|
||||||
|
|
||||||
public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface {
|
public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface {
|
||||||
|
@ -205,10 +210,16 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
try {
|
try {
|
||||||
delegate.setBasalSchedule(mapProfileToBasalSchedule(basalProfile), isBasalBeepsEnabled());
|
delegate.setBasalSchedule(mapProfileToBasalSchedule(basalProfile), isBasalBeepsEnabled());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
|
||||||
|
return new PumpEnactResult().success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_set_basal_failed_uncertain));
|
||||||
|
}
|
||||||
String comment = handleAndTranslateException(ex);
|
String comment = handleAndTranslateException(ex);
|
||||||
return new PumpEnactResult().success(false).enacted(false).comment(comment);
|
return new PumpEnactResult().success(false).enacted(false).comment(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because setting a basal profile actually suspends and then resumes delivery, TBR is implicitly cancelled
|
||||||
|
reportImplicitlyCanceledTbr();
|
||||||
|
|
||||||
return new PumpEnactResult().success(true).enacted(true);
|
return new PumpEnactResult().success(true).enacted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +256,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
return new PumpEnactResult().success(false).enacted(false).comment(comment);
|
return new PumpEnactResult().success(false).enacted(false).comment(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus()) && !isSmb /* TODO or should we also warn for SMB? */) {
|
if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus())) {
|
||||||
// TODO notify user about uncertain failure ---> we're unsure whether or not the bolus has been delivered
|
// TODO notify user about uncertain failure ---> we're unsure whether or not the bolus has been delivered
|
||||||
// For safety reasons, we should treat this as a bolus that has been delivered, in order to prevent insulin overdose
|
// For safety reasons, we should treat this as a bolus that has been delivered, in order to prevent insulin overdose
|
||||||
}
|
}
|
||||||
|
@ -360,13 +371,18 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
// Updates the pods current time based on the device timezone and the pod's time zone
|
// Updates the pods current time based on the device timezone and the pod's time zone
|
||||||
public PumpEnactResult setTime() {
|
public PumpEnactResult setTime() {
|
||||||
try {
|
try {
|
||||||
// CAUTION cancels TBR
|
|
||||||
delegate.setTime(isBasalBeepsEnabled());
|
delegate.setTime(isBasalBeepsEnabled());
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// CAUTION pod could be suspended
|
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
|
||||||
|
return new PumpEnactResult().success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_set_time_failed_uncertain));
|
||||||
|
}
|
||||||
String comment = handleAndTranslateException(ex);
|
String comment = handleAndTranslateException(ex);
|
||||||
return new PumpEnactResult().success(false).enacted(false).comment(comment);
|
return new PumpEnactResult().success(false).enacted(false).comment(comment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Because set time actually suspends and then resumes delivery, TBR is implicitly cancelled
|
||||||
|
reportImplicitlyCanceledTbr();
|
||||||
|
|
||||||
return new PumpEnactResult().success(true).enacted(true);
|
return new PumpEnactResult().success(true).enacted(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,26 +402,40 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
return delegate.getPodStateAsString();
|
return delegate.getPodStateAsString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void reportImplicitlyCanceledTbr() {
|
||||||
|
TreatmentsPlugin plugin = TreatmentsPlugin.getPlugin();
|
||||||
|
if (plugin.isTempBasalInProgress()) {
|
||||||
|
if (isLoggingEnabled()) {
|
||||||
|
LOG.debug("Reporting implicitly cancelled TBR to Treatments plugin");
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryBasal temporaryBasal = new TemporaryBasal() //
|
||||||
|
.date(System.currentTimeMillis()) //
|
||||||
|
.duration(0) //
|
||||||
|
// TODO bs should be Source.PUMP imo, but that doesn't work:
|
||||||
|
// it says a TEMPBASAL record already exists
|
||||||
|
.source(Source.USER);
|
||||||
|
plugin.addToHistoryTempBasal(temporaryBasal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void addToHistory(long requestTime, PodHistoryEntryType entryType, String data, boolean success) {
|
private void addToHistory(long requestTime, PodHistoryEntryType entryType, String data, boolean success) {
|
||||||
// TODO andy needs to be refactored
|
// TODO andy needs to be refactored
|
||||||
|
|
||||||
//PodDbEntry entry = new PodDbEntry(requestTime, entryType);
|
//PodDbEntry entry = new PodDbEntry(requestTime, entryType);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleSetupActionResult(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, SetupActionResult res) {
|
private void handleSetupActionResult(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, SetupActionResult res) {
|
||||||
String comment = null;
|
String comment = null;
|
||||||
switch (res.getResultType()) {
|
switch (res.getResultType()) {
|
||||||
case FAILURE:
|
case FAILURE:
|
||||||
if (loggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.error("Setup action failed: illegal setup progress: {}", res.getSetupProgress());
|
LOG.error("Setup action failed: illegal setup progress: {}", res.getSetupProgress());
|
||||||
}
|
}
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state, res.getSetupProgress());
|
comment = getStringResource(R.string.omnipod_driver_error_invalid_progress_state, res.getSetupProgress());
|
||||||
break;
|
break;
|
||||||
case VERIFICATION_FAILURE:
|
case VERIFICATION_FAILURE:
|
||||||
if (loggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.error("Setup action verification failed: caught exception", res.getException());
|
LOG.error("Setup action verification failed: caught exception", res.getException());
|
||||||
}
|
}
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_setup_action_verification_failed);
|
comment = getStringResource(R.string.omnipod_driver_error_setup_action_verification_failed);
|
||||||
|
@ -442,19 +472,21 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_not_enough_data);
|
comment = getStringResource(R.string.omnipod_driver_error_not_enough_data);
|
||||||
} else if (ex instanceof PodFaultException) {
|
} else if (ex instanceof PodFaultException) {
|
||||||
// TODO handle pod fault with some kind of dialog that has a button to start pod deactivation
|
// TODO handle pod fault with some kind of dialog that has a button to start pod deactivation
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_pod_fault, ((PodFaultException) ex).getFaultEvent().getFaultEventCode().name());
|
FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode();
|
||||||
|
comment = getStringResource(R.string.omnipod_driver_error_pod_fault,
|
||||||
|
ByteUtil.convertUnsignedByteToInt(faultEventCode.getValue()), faultEventCode.name());
|
||||||
} else if (ex instanceof PodReturnedErrorResponseException) {
|
} else if (ex instanceof PodReturnedErrorResponseException) {
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_pod_returned_error_response);
|
comment = getStringResource(R.string.omnipod_driver_error_pod_returned_error_response);
|
||||||
} else {
|
} else {
|
||||||
// Shouldn't be reachable
|
// Shouldn't be reachable
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
|
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
|
||||||
}
|
}
|
||||||
if (loggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.error(String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager (user-friendly error message: %s)", ((OmnipodException) ex).isCertainFailure(), comment), ex);
|
LOG.error(String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager (user-friendly error message: %s)", ((OmnipodException) ex).isCertainFailure(), comment), ex);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
|
comment = getStringResource(R.string.omnipod_driver_error_unexpected_exception_type, ex.getClass().getName());
|
||||||
if (loggingEnabled()) {
|
if (isLoggingEnabled()) {
|
||||||
LOG.error(String.format("Caught unexpected exception type[certainFailure=false] from OmnipodManager (user-friendly error message: %s)", comment), ex);
|
LOG.error(String.format("Caught unexpected exception type[certainFailure=false] from OmnipodManager (user-friendly error message: %s)", comment), ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -504,7 +536,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
|
||||||
return MainApp.gs(id, args);
|
return MainApp.gs(id, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean loggingEnabled() {
|
private boolean isLoggingEnabled() {
|
||||||
return L.isEnabled(L.PUMP);
|
return L.isEnabled(L.PUMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1686,7 +1686,7 @@
|
||||||
<string name="omnipod_driver_error_nonce_resync_failed">Communication failed: nonce resync failed.</string>
|
<string name="omnipod_driver_error_nonce_resync_failed">Communication failed: nonce resync failed.</string>
|
||||||
<string name="omnipod_driver_error_nonce_out_of_sync">Communication failed: nonce out of sync.</string>
|
<string name="omnipod_driver_error_nonce_out_of_sync">Communication failed: nonce out of sync.</string>
|
||||||
<string name="omnipod_driver_error_not_enough_data">Communication failed: not enough data received from the pod.</string>
|
<string name="omnipod_driver_error_not_enough_data">Communication failed: not enough data received from the pod.</string>
|
||||||
<string name="omnipod_driver_error_pod_fault">A pod fault (%1$s) has been detected. Please deactivate your pod and start a new one.</string>
|
<string name="omnipod_driver_error_pod_fault">A pod fault (%1$03d %2$s) has been detected. Please deactivate your pod and start a new one.</string>
|
||||||
<string name="omnipod_driver_error_pod_returned_error_response">Communication failed: the pod returned an error response.</string>
|
<string name="omnipod_driver_error_pod_returned_error_response">Communication failed: the pod returned an error response.</string>
|
||||||
|
|
||||||
<!-- Omnipod - Pod Mgmt -->
|
<!-- Omnipod - Pod Mgmt -->
|
||||||
|
@ -1742,6 +1742,8 @@
|
||||||
<string name="omnipod_alert_shutdown_imminent">Shutdown is imminent</string>
|
<string name="omnipod_alert_shutdown_imminent">Shutdown is imminent</string>
|
||||||
<string name="omnipod_alert_low_reservoir">Low reservoir</string>
|
<string name="omnipod_alert_low_reservoir">Low reservoir</string>
|
||||||
<string name="omnipod_alert_unknown_alert">Unknown alert</string>
|
<string name="omnipod_alert_unknown_alert">Unknown alert</string>
|
||||||
|
<string name="omnipod_error_set_basal_failed_uncertain">Setting basal profile failed. Delivery might be suspended! Please refresh pod status.</string>
|
||||||
|
<string name="omnipod_error_set_time_failed_uncertain">Setting time failed. Delivery might be suspended! Please refresh pod status.</string>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
Loading…
Reference in a new issue