Merge branch 'omnipod_eros' of https://github.com/AAPS-Omnipod/AndroidAPS into omnipod_eros

This commit is contained in:
Andy Rozman 2019-12-25 19:24:47 +01:00
commit b80fc3851c
11 changed files with 80 additions and 71 deletions

View file

@ -18,6 +18,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodPacket;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.DeactivatePodCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.ErrorResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent;
@ -149,7 +150,9 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
boolean firstPacket = true;
byte[] encodedMessage;
if (message.isNonceResyncable()) {
// this does not work well with the deactivate pod command, we somehow either
// receive an ACK instead of a normal response, or a partial response and a communication timeout
if (message.isNonceResyncable() && !message.containsBlock(DeactivatePodCommand.class)) {
OmnipodMessage paddedMessage = new OmnipodMessage(message);
// If messages are nonce resyncable, we want do distinguish between certain and uncertain failures for verification purposes
// However, some commands (e.g. cancel delivery) are single packet command by nature. When we get a timeout with a single packet,

View file

@ -26,9 +26,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetBasalSched
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.SetTempBasalAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.InsertCannulaService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.PrimeService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.SetTempBasalService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.CancelDeliveryCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentHighFlashLogDump;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
@ -202,15 +202,30 @@ public class OmnipodManager {
}
}
// CAUTION: cancels temp basal and then sets new temp basal. An OmnipodException[certainFailure=false] indicates that the pod might have cancelled the previous temp basal, but did not set a new temp basal
public synchronized void setTemporaryBasal(TempBasalPair tempBasalPair, boolean acknowledgementBeep, boolean completionBeep) {
assertReadyForDelivery();
logStartingCommandExecution("setTemporaryBasal [tempBasalPair=" + tempBasalPair + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]");
try {
executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction(new SetTempBasalService(),
// Never emit a beep for cancelling temp basal, so if the user has beeps enabled,
// they can verify that setting the temp basal succeeded (and not cancelling it)
cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), false);
} catch (Exception ex) {
logCommandExecutionFinished("setTemporaryBasal");
throw ex;
}
try {
executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction(
podState, tempBasalPair.getInsulinRate(), Duration.standardMinutes(tempBasalPair.getDurationMinutes()),
acknowledgementBeep, completionBeep)));
} 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("setTemporaryBasal");
}
@ -401,9 +416,21 @@ public class OmnipodManager {
logStartingCommandExecution("deactivatePod");
// Try to get pulse log for diagnostics
// FIXME replace by storing to file
if (isLoggingEnabled()) {
try {
PodInfoResponse podInfoResponse = communicationService.executeAction(new GetPodInfoAction(podState, PodInfoType.RECENT_HIGH_FLASH_LOG_DUMP));
PodInfoRecentHighFlashLogDump pulseLogInfo = podInfoResponse.getPodInfo();
LOG.info("Retrieved pulse log from the pod: {}", pulseLogInfo.toString());
} catch (Exception ex) {
LOG.warn("Failed to retrieve pulse log from the pod", ex);
}
}
try {
// Always send acknowledgement beeps here. Matches the PDM's behavior
executeAndVerify(() -> communicationService.executeAction(new DeactivatePodAction(podState, true)));
communicationService.executeAction(new DeactivatePodAction(podState, true));
} catch (PodFaultException ex) {
if (isLoggingEnabled()) {
LOG.info("Ignoring PodFaultException in deactivatePod", ex);

View file

@ -34,11 +34,6 @@ public class CancelDeliveryAction implements OmnipodAction<StatusResponse> {
this.acknowledgementBeep = acknowledgementBeep;
}
public CancelDeliveryAction(PodSessionState podState, DeliveryType deliveryType,
boolean acknowledgementBeep) {
this(podState, EnumSet.of(deliveryType), acknowledgementBeep);
}
@Override
public StatusResponse execute(OmnipodCommunicationService communicationService) {
List<MessageBlock> messageBlocks = new ArrayList<>();

View file

@ -28,7 +28,6 @@ public class DeactivatePodAction implements OmnipodAction<StatusResponse> {
EnumSet.allOf(DeliveryType.class), acknowledgementBeep));
}
DeactivatePodCommand deactivatePodCommand = new DeactivatePodCommand(podState.getCurrentNonce());
return communicationService.sendCommand(StatusResponse.class, podState, deactivatePodCommand);
return communicationService.sendCommand(StatusResponse.class, podState, new DeactivatePodCommand(podState.getCurrentNonce()));
}
}

View file

@ -9,9 +9,12 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessa
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.BasalScheduleExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalDeliveryStatusException;
public class SetBasalScheduleAction implements OmnipodAction<StatusResponse> {
private final PodSessionState podState;

View file

@ -2,34 +2,33 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action;
import org.joda.time.Duration;
import java.util.Arrays;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service.SetTempBasalService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.TempBasalExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.IllegalDeliveryStatusException;
public class SetTempBasalAction implements OmnipodAction<StatusResponse> {
private final SetTempBasalService service;
private final PodSessionState podState;
private final double rate;
private final Duration duration;
private final boolean acknowledgementBeep;
private final boolean completionBeep;
public SetTempBasalAction(SetTempBasalService setTempBasalService, PodSessionState podState,
double rate, Duration duration, boolean acknowledgementBeep, boolean completionBeep) {
if (setTempBasalService == null) {
throw new ActionInitializationException("Set temp basal service cannot be null");
}
public SetTempBasalAction(PodSessionState podState, double rate, Duration duration,
boolean acknowledgementBeep, boolean completionBeep) {
if (podState == null) {
throw new ActionInitializationException("Pod state cannot be null");
}
if (duration == null) {
throw new ActionInitializationException("Duration cannot be null");
}
this.service = setTempBasalService;
this.podState = podState;
this.rate = rate;
this.duration = duration;
@ -39,13 +38,11 @@ public class SetTempBasalAction implements OmnipodAction<StatusResponse> {
@Override
public StatusResponse execute(OmnipodCommunicationService communicationService) {
StatusResponse statusResponse = service.cancelTempBasal(communicationService, podState);
List<MessageBlock> messageBlocks = Arrays.asList( //
new SetInsulinScheduleCommand(podState.getCurrentNonce(), rate, duration),
new TempBasalExtraCommand(rate, duration, acknowledgementBeep, completionBeep, Duration.ZERO));
if (statusResponse.getDeliveryStatus() != DeliveryStatus.NORMAL) {
throw new IllegalDeliveryStatusException(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus());
}
return service.executeTempBasalCommand(communicationService, podState, rate, duration,
acknowledgementBeep, completionBeep);
OmnipodMessage message = new OmnipodMessage(podState.getAddress(), messageBlocks, podState.getMessageNumber());
return communicationService.exchangeMessages(StatusResponse.class, podState, message);
}
}

View file

@ -1,33 +0,0 @@
package info.nightscout.androidaps.plugins.pump.omnipod.comm.action.service;
import org.joda.time.Duration;
import java.util.Arrays;
import java.util.List;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationService;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.CancelDeliveryAction;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.TempBasalExtraCommand;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
public class SetTempBasalService {
public StatusResponse cancelTempBasal(OmnipodCommunicationService communicationService, PodSessionState podState) {
return communicationService.executeAction(new CancelDeliveryAction(podState, DeliveryType.TEMP_BASAL, false));
}
public StatusResponse executeTempBasalCommand(OmnipodCommunicationService communicationService,
PodSessionState podState, double rate, Duration duration,
boolean acknowledgementBeep, boolean completionBeep) {
List<MessageBlock> messageBlocks = Arrays.asList( //
new SetInsulinScheduleCommand(podState.getCurrentNonce(), rate, duration),
new TempBasalExtraCommand(rate, duration, acknowledgementBeep, completionBeep, Duration.ZERO));
OmnipodMessage message = new OmnipodMessage(podState.getAddress(), messageBlocks, podState.getMessageNumber());
return communicationService.exchangeMessages(StatusResponse.class, podState, message);
}
}

View file

@ -115,12 +115,7 @@ public class OmnipodMessage {
}
public boolean isNonceResyncable() {
for (MessageBlock messageBlock : messageBlocks) {
if (messageBlock instanceof NonceResyncableMessageBlock) {
return true;
}
}
return false;
return containsBlock(NonceResyncableMessageBlock.class);
}
public int getSentNonce() {
@ -139,4 +134,13 @@ public class OmnipodMessage {
}
}
}
public boolean containsBlock(Class<? extends MessageBlock> blockType) {
for (MessageBlock messageBlock : messageBlocks) {
if (blockType.isInstance(messageBlock)) {
return true;
}
}
return false;
}
}

View file

@ -5,10 +5,13 @@ import com.google.gson.Gson;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Duration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
import info.nightscout.androidaps.logging.L;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet;
@ -26,6 +29,8 @@ import info.nightscout.androidaps.utils.DateUtil;
import info.nightscout.androidaps.utils.SP;
public class PodSessionState extends PodState {
private static final Logger LOG = LoggerFactory.getLogger(L.PUMPCOMM);
private final Map<AlertSlot, AlertType> configuredAlerts;
private transient PodStateChangedHandler stateChangedHandler;
private DateTime activatedAt;
@ -234,7 +239,11 @@ public class PodSessionState extends PodState {
expiresAt = expiresAtCalculated;
}
suspended = (statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED);
boolean newSuspendedState = statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED;
if (suspended != newSuspendedState) {
LOG.info("Updating pod suspended state in updateFromStatusResponse. newSuspendedState={}, statusResponse={}", newSuspendedState, statusResponse.toString());
suspended = newSuspendedState;
}
activeAlerts = statusResponse.getAlerts();
lastDeliveryStatus = statusResponse.getDeliveryStatus();
reservoirLevel = statusResponse.getReservoirLevel();

View file

@ -316,7 +316,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
try {
delegate.cancelBolus(isBolusBeepsEnabled());
addSuccessToHistory(time, PodHistoryEntryType.CancelBolus, null);
} catch(PodFaultException ex) {
} catch (PodFaultException ex) {
showNotificationWithDialog(createPodFaultErrorMessage(ex.getFaultEvent().getFaultEventType()), Notification.URGENT, null);
} catch (Exception ex) {
String comment = handleAndTranslateException(ex);
@ -335,6 +335,10 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
delegate.setTemporaryBasal(tempBasalPair, beepsEnabled, beepsEnabled);
addSuccessToHistory(time, PodHistoryEntryType.SetTemporaryBasal, tempBasalPair);
} catch (Exception ex) {
if ((ex instanceof OmnipodException) && !((OmnipodException) ex).isCertainFailure()) {
addToHistory(time, PodHistoryEntryType.SetTemporaryBasal, "Uncertain failure", false);
return new PumpEnactResult().success(false).enacted(false).comment(getStringResource(R.string.omnipod_error_set_temp_basal_failed_uncertain));
}
String comment = handleAndTranslateException(ex);
addFailureToHistory(time, PodHistoryEntryType.SetTemporaryBasal, comment);
return new PumpEnactResult().success(false).enacted(false).comment(comment);

View file

@ -1760,8 +1760,9 @@
<string name="omnipod_alert_shutdown_imminent">Shutdown is imminent</string>
<string name="omnipod_alert_low_reservoir">Low reservoir</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>
<string name="omnipod_error_set_basal_failed_uncertain">Setting basal profile might have failed. Delivery might be suspended! Please refresh pod status.</string>
<string name="omnipod_error_set_temp_basal_failed_uncertain">Setting temp basal might have failed. If there was a temp basal already running, that may have been cancelled! Please refresh pod status.</string>
<string name="omnipod_error_set_time_failed_uncertain">Setting time might have failed. Delivery might be suspended! Please refresh pod status.</string>
<string name="omnipod_bolus_failed_uncertain">Unable to verify whether the bolus succeeded. Please verify that your pod is bolusing or cancel the bolus.</string>