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

This commit is contained in:
Andy Rozman 2019-12-08 16:21:47 +00:00
commit 2132bf1675
14 changed files with 203 additions and 38 deletions

View file

@ -175,6 +175,10 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump
public void initPumpStatusData() { public void initPumpStatusData() {
this.pumpStatusLocal = new OmnipodPumpStatus(pumpDescription); this.pumpStatusLocal = new OmnipodPumpStatus(pumpDescription);
if (omnipodCommunicationManager != null) {
omnipodCommunicationManager.setPumpStatus(pumpStatusLocal);
}
OmnipodUtil.setPumpStatus(pumpStatusLocal); OmnipodUtil.setPumpStatus(pumpStatusLocal);
pumpStatusLocal.lastConnection = SP.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); pumpStatusLocal.lastConnection = SP.getLong(RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L);
@ -495,6 +499,9 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump
if (isLoggingEnabled()) if (isLoggingEnabled())
LOG.warn("!!!! Reset Pump Status Local"); LOG.warn("!!!! Reset Pump Status Local");
pumpStatusLocal = OmnipodUtil.getPumpStatus(); pumpStatusLocal = OmnipodUtil.getPumpStatus();
if (omnipodCommunicationManager != null) {
omnipodCommunicationManager.setPumpStatus(pumpStatusLocal);
}
} }
return pumpStatusLocal; return pumpStatusLocal;

View file

@ -160,14 +160,14 @@ public class OmnipodCommunicationService extends RileyLinkCommunicationManager {
encodedMessage = ByteUtil.substring(encodedMessage, encodedMessageInPacket.length, encodedMessage.length - encodedMessageInPacket.length); encodedMessage = ByteUtil.substring(encodedMessage, encodedMessageInPacket.length, encodedMessage.length - encodedMessageInPacket.length);
firstPacket = false; firstPacket = false;
// 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;
try { try {
// 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;

View file

@ -26,6 +26,9 @@ public class InsertCannulaService {
public StatusResponse executeExpirationRemindersAlertCommand(OmnipodCommunicationService communicationService, public StatusResponse executeExpirationRemindersAlertCommand(OmnipodCommunicationService communicationService,
PodSessionState podState) { PodSessionState podState) {
AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationFactory.createLowReservoirAlertConfiguration(OmnipodConst.LOW_RESERVOIR_ALERT);
DateTime endOfServiceTime = podState.getActivatedAt().plus(OmnipodConst.SERVICE_DURATION); DateTime endOfServiceTime = podState.getActivatedAt().plus(OmnipodConst.SERVICE_DURATION);
Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(), Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(),
@ -41,6 +44,7 @@ public class InsertCannulaService {
false, Duration.ZERO); false, Duration.ZERO);
List<AlertConfiguration> alertConfigurations = Arrays.asList( // List<AlertConfiguration> alertConfigurations = Arrays.asList( //
lowReservoirAlertConfiguration, //
expirationAdvisoryAlertConfiguration, // expirationAdvisoryAlertConfiguration, //
shutdownImminentAlertConfiguration, // shutdownImminentAlertConfiguration, //
autoOffAlertConfiguration // autoOffAlertConfiguration //

View file

@ -20,7 +20,7 @@ public class StatusResponse extends MessageBlock {
private final PodProgressStatus podProgressStatus; private final PodProgressStatus podProgressStatus;
private final Duration timeActive; private final Duration timeActive;
private final Double reservoirLevel; private final Double reservoirLevel;
private final double insulin; private final double insulinDelivered;
private final double insulinNotDelivered; private final double insulinNotDelivered;
private final byte podMessageCounter; private final byte podMessageCounter;
private final AlertSet alerts; private final AlertSet alerts;
@ -40,7 +40,7 @@ public class StatusResponse extends MessageBlock {
int highInsulinBits = (encodedData[2] & 0xF) << 9; int highInsulinBits = (encodedData[2] & 0xF) << 9;
int middleInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[3]) << 1; int middleInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[3]) << 1;
int lowInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[4]) >>> 7; int lowInsulinBits = ByteUtil.convertUnsignedByteToInt(encodedData[4]) >>> 7;
this.insulin = OmnipodConst.POD_PULSE_SIZE * (highInsulinBits | middleInsulinBits | lowInsulinBits); this.insulinDelivered = OmnipodConst.POD_PULSE_SIZE * (highInsulinBits | middleInsulinBits | lowInsulinBits);
this.podMessageCounter = (byte) ((encodedData[4] >>> 3) & 0xf); this.podMessageCounter = (byte) ((encodedData[4] >>> 3) & 0xf);
this.insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * (((encodedData[4] & 0x03) << 8) | ByteUtil.convertUnsignedByteToInt(encodedData[5])); this.insulinNotDelivered = OmnipodConst.POD_PULSE_SIZE * (((encodedData[4] & 0x03) << 8) | ByteUtil.convertUnsignedByteToInt(encodedData[5]));
@ -75,8 +75,8 @@ public class StatusResponse extends MessageBlock {
return reservoirLevel; return reservoirLevel;
} }
public double getInsulin() { public double getInsulinDelivered() {
return insulin; return insulinDelivered;
} }
public double getInsulinNotDelivered() { public double getInsulinNotDelivered() {
@ -110,7 +110,7 @@ public class StatusResponse extends MessageBlock {
", podProgressStatus=" + podProgressStatus + ", podProgressStatus=" + podProgressStatus +
", timeActive=" + timeActive + ", timeActive=" + timeActive +
", reservoirLevel=" + reservoirLevel + ", reservoirLevel=" + reservoirLevel +
", insulin=" + insulin + ", insulinDelivered=" + insulinDelivered +
", insulinNotDelivered=" + insulinNotDelivered + ", insulinNotDelivered=" + insulinNotDelivered +
", podMessageCounter=" + podMessageCounter + ", podMessageCounter=" + podMessageCounter +
", alerts=" + alerts + ", alerts=" + alerts +

View file

@ -3,6 +3,11 @@ package info.nightscout.androidaps.plugins.pump.omnipod.defs;
import org.joda.time.Duration; import org.joda.time.Duration;
public class AlertConfigurationFactory { public class AlertConfigurationFactory {
public static AlertConfiguration createLowReservoirAlertConfiguration(Double units) {
return new AlertConfiguration(AlertType.LOW_RESERVOIR_ALERT, AlertSlot.SLOT4, true, false, Duration.ZERO,
new UnitsRemainingAlertTrigger(units), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_15_MINUTES);
}
public static AlertConfiguration createExpirationAdvisoryAlertConfiguration(Duration timeUntilAlert, Duration duration) { public static AlertConfiguration createExpirationAdvisoryAlertConfiguration(Duration timeUntilAlert, Duration duration) {
return new AlertConfiguration(AlertType.EXPIRATION_ADVISORY_ALERT, AlertSlot.SLOT7, true, false, duration, return new AlertConfiguration(AlertType.EXPIRATION_ADVISORY_ALERT, AlertSlot.SLOT7, true, false, duration,
new TimerAlertTrigger(timeUntilAlert), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_60_MINUTES); new TimerAlertTrigger(timeUntilAlert), BeepType.BIP_BEEP_BIP_BEEP_BIP_BEEP_BIP_BEEP, BeepRepeat.EVERY_60_MINUTES);

View file

@ -1,11 +1,11 @@
package info.nightscout.androidaps.plugins.pump.omnipod.defs; package info.nightscout.androidaps.plugins.pump.omnipod.defs;
public enum AlertType { public enum AlertType {
WAITING_FOR_PAIRING_REMINDER, FINISH_PAIRING_REMINDER,
FINISH_SETUP_REMINDER, FINISH_SETUP_REMINDER,
EXPIRATION_ALERT, EXPIRATION_ALERT,
EXPIRATION_ADVISORY_ALERT, EXPIRATION_ADVISORY_ALERT,
SHUTDOWN_IMMINENT_ALARM, SHUTDOWN_IMMINENT_ALARM,
LOW_RESERVOIC_ALERT, LOW_RESERVOIR_ALERT,
AUTO_OFF_ALARM AUTO_OFF_ALARM
} }

View file

@ -33,6 +33,7 @@ public class PodSessionState extends PodState {
private final FirmwareVersion pmVersion; private final FirmwareVersion pmVersion;
private final int lot; private final int lot;
private final int tid; private final int tid;
private Double reservoirLevel;
private boolean suspended; private boolean suspended;
private DateTimeZone timeZone; private DateTimeZone timeZone;
@ -98,7 +99,6 @@ public class PodSessionState extends PodState {
return expiresAt == null ? "???" : DateUtil.dateAndTimeString(expiresAt.toDate()); return expiresAt == null ? "???" : DateUtil.dateAndTimeString(expiresAt.toDate());
} }
public FirmwareVersion getPiVersion() { public FirmwareVersion getPiVersion() {
return piVersion; return piVersion;
} }
@ -115,6 +115,10 @@ public class PodSessionState extends PodState {
return tid; return tid;
} }
public Double getReservoirLevel() {
return reservoirLevel;
}
public synchronized void resyncNonce(int syncWord, int sentNonce, int sequenceNumber) { public synchronized void resyncNonce(int syncWord, int sentNonce, int sequenceNumber) {
int sum = (sentNonce & 0xFFFF) int sum = (sentNonce & 0xFFFF)
+ OmniCRC.crc16lookup[sequenceNumber] + OmniCRC.crc16lookup[sequenceNumber]
@ -225,6 +229,7 @@ public class PodSessionState extends PodState {
suspended = (statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED); suspended = (statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED);
activeAlerts = statusResponse.getAlerts(); activeAlerts = statusResponse.getAlerts();
lastDeliveryStatus = statusResponse.getDeliveryStatus(); lastDeliveryStatus = statusResponse.getDeliveryStatus();
reservoirLevel = statusResponse.getReservoirLevel();
store(); store();
} }
@ -251,6 +256,7 @@ public class PodSessionState extends PodState {
", pmVersion=" + pmVersion + ", pmVersion=" + pmVersion +
", lot=" + lot + ", lot=" + lot +
", tid=" + tid + ", tid=" + tid +
", reservoirLevel=" + reservoirLevel +
", suspended=" + suspended + ", suspended=" + suspended +
", timeZone=" + timeZone + ", timeZone=" + timeZone +
", nonceState=" + nonceState + ", nonceState=" + nonceState +

View file

@ -1,17 +1,23 @@
package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm; package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm;
import android.text.TextUtils;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects;
import info.nightscout.androidaps.MainApp; 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.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;
@ -21,6 +27,8 @@ 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;
import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse;
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.AlertType;
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;
@ -29,7 +37,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedu
import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalScheduleEntry; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalScheduleEntry;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.db.PodHistoryEntryType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.db.PodDbEntryType;
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodAcknowledgeAlertsChanged;
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.ActionInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.CommandInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.CommandInitializationException;
import info.nightscout.androidaps.plugins.pump.omnipod.exception.CommunicationException; import info.nightscout.androidaps.plugins.pump.omnipod.exception.CommunicationException;
@ -56,19 +66,68 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
private static AapsOmnipodManager instance; private static AapsOmnipodManager instance;
private OmnipodPumpStatus pumpStatus; private OmnipodPumpStatus pumpStatus;
private Date lastBolusTime;
private Double lastBolusUnits;
public static AapsOmnipodManager getInstance() { public static AapsOmnipodManager getInstance() {
return instance; return instance;
} }
public AapsOmnipodManager(OmnipodCommunicationService communicationService, PodSessionState podState, OmnipodPumpStatus pumpStatus) { public AapsOmnipodManager(OmnipodCommunicationService communicationService, PodSessionState podState, OmnipodPumpStatus _pumpStatus) {
delegate = new OmnipodManager(communicationService, podState, podSessionState -> { delegate = new OmnipodManager(communicationService, podState, podSessionState -> {
// Handle pod state changes
OmnipodUtil.setPodSessionState(podSessionState); OmnipodUtil.setPodSessionState(podSessionState);
// TODO update active alerts (and other stuff(?)) in UI
if (pumpStatus != null) {
// Update active alerts
if (podSessionState.hasActiveAlerts()) {
List<String> alerts = translateActiveAlerts(podSessionState);
String alertsText = TextUtils.join("\n", alerts);
if (!pumpStatus.ackAlertsAvailable || !alertsText.equals(pumpStatus.ackAlertsText)) {
pumpStatus.ackAlertsAvailable = true;
pumpStatus.ackAlertsText = TextUtils.join("\n", alerts);
sendEvent(new EventOmnipodAcknowledgeAlertsChanged());
}
} else {
if (pumpStatus.ackAlertsAvailable) {
pumpStatus.ackAlertsAvailable = false;
sendEvent(new EventOmnipodAcknowledgeAlertsChanged());
}
}
// Update other info: last bolus, units remaining
if (!Objects.equals(lastBolusTime, pumpStatus.lastBolusTime) //
|| !Objects.equals(lastBolusUnits, pumpStatus.lastBolusAmount) //
|| !isReservoirStatusUpToDate(pumpStatus, podSessionState.getReservoirLevel())) {
pumpStatus.lastBolusTime = lastBolusTime;
pumpStatus.lastBolusAmount = lastBolusUnits;
pumpStatus.reservoirRemainingUnits = podSessionState.getReservoirLevel() == null ? 75.0 : podSessionState.getReservoirLevel();
sendEvent(new EventOmnipodPumpValuesChanged());
}
}
}); });
this.pumpStatus = pumpStatus; this.pumpStatus = _pumpStatus;
instance = this; instance = this;
} }
private static boolean isReservoirStatusUpToDate(OmnipodPumpStatus pumpStatus, Double unitsRemaining) {
double expectedUnitsRemaining = unitsRemaining == null ? 75.0 : unitsRemaining;
return Math.abs(expectedUnitsRemaining - pumpStatus.reservoirRemainingUnits) < 0.000001;
}
@NotNull
private List<String> translateActiveAlerts(PodSessionState podSessionState) {
List<String> alerts = new ArrayList<>();
for (AlertSlot alertSlot : podSessionState.getActiveAlerts().getAlertSlots()) {
alerts.add(translateAlertType(podSessionState.getConfiguredAlertType(alertSlot)));
}
return alerts;
}
@Override @Override
public PumpEnactResult initPod(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, Profile profile) { public PumpEnactResult initPod(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, Profile profile) {
if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) { if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) {
@ -153,35 +212,36 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
boolean beepsEnabled = isSmb ? isSmbBeepsEnabled() : isBolusBeepsEnabled(); boolean beepsEnabled = isSmb ? isSmbBeepsEnabled() : isBolusBeepsEnabled();
Date bolusStarted;
try { try {
bolusCommandResult = delegate.bolus(units, beepsEnabled, beepsEnabled, isSmb ? null : bolusCommandResult = delegate.bolus(units, beepsEnabled, beepsEnabled, isSmb ? null :
(estimatedUnitsDelivered, percentage) -> { (estimatedUnitsDelivered, percentage) -> {
EventOverviewBolusProgress progressUpdateEvent = EventOverviewBolusProgress.INSTANCE; EventOverviewBolusProgress progressUpdateEvent = EventOverviewBolusProgress.INSTANCE;
progressUpdateEvent.setStatus(getStringResource(R.string.bolusdelivering, units)); progressUpdateEvent.setStatus(getStringResource(R.string.bolusdelivering, units));
progressUpdateEvent.setPercent(percentage); progressUpdateEvent.setPercent(percentage);
RxBus.INSTANCE.send(progressUpdateEvent); sendEvent(progressUpdateEvent);
}); });
bolusStarted = new Date();
} catch (Exception ex) { } catch (Exception ex) {
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);
} }
if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus()) /* && !isSmb */) { if (OmnipodManager.CommandDeliveryStatus.UNCERTAIN_FAILURE.equals(bolusCommandResult.getCommandDeliveryStatus()) && !isSmb /* TODO or should we also warn for SMB? */) {
// 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
} }
double unitsDelivered = units;
try {
// Wait for the bolus to finish // Wait for the bolus to finish
OmnipodManager.BolusDeliveryResult bolusDeliveryResult = OmnipodManager.BolusDeliveryResult bolusDeliveryResult =
bolusCommandResult.getDeliveryResultSubject().blockingGet(); bolusCommandResult.getDeliveryResultSubject().blockingGet();
unitsDelivered = bolusDeliveryResult.getUnitsDelivered();
} catch (Exception ex) { double unitsDelivered = bolusDeliveryResult.getUnitsDelivered();
if (loggingEnabled()) {
LOG.debug("Ignoring failed status response for bolus completion verification", ex); if (pumpStatus != null && !isSmb) {
} lastBolusTime = bolusStarted;
lastBolusUnits = unitsDelivered;
} }
return new PumpEnactResult().success(true).enacted(true).bolusDelivered(unitsDelivered); return new PumpEnactResult().success(true).enacted(true).bolusDelivered(unitsDelivered);
@ -279,6 +339,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
} }
// TODO should we add this to the OmnipodCommunicationManager interface? // TODO should we add this to the OmnipodCommunicationManager interface?
// 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 // CAUTION cancels TBR
@ -308,7 +369,7 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
} }
private void addToHistory(long requestTime, PodHistoryEntryType entryType, String data, boolean success) { private void addToHistory(long requestTime, PodDbEntryType 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);
@ -383,6 +444,32 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface
return comment; return comment;
} }
private void sendEvent(Event event) {
RxBus.INSTANCE.send(event);
}
private String translateAlertType(AlertType alertType) {
if (alertType == null) {
return getStringResource(R.string.omnipod_alert_unknown_alert);
}
switch (alertType) {
case FINISH_PAIRING_REMINDER:
return getStringResource(R.string.omnipod_alert_finish_pairing_reminder);
case FINISH_SETUP_REMINDER:
return getStringResource(R.string.omnipod_alert_finish_setup_reminder_reminder);
case EXPIRATION_ALERT:
return getStringResource(R.string.omnipod_alert_expiration);
case EXPIRATION_ADVISORY_ALERT:
return getStringResource(R.string.omnipod_alert_expiration_advisory);
case SHUTDOWN_IMMINENT_ALARM:
return getStringResource(R.string.omnipod_alert_shutdown_imminent);
case LOW_RESERVOIR_ALERT:
return getStringResource(R.string.omnipod_alert_low_reservoir);
default:
return alertType.name();
}
}
private boolean isBolusBeepsEnabled() { private boolean isBolusBeepsEnabled() {
// TODO // TODO
return true; return true;

View file

@ -42,6 +42,9 @@ public class PodHistory implements DbObjectBase {
@DatabaseField @DatabaseField
private Boolean successConfirmed; private Boolean successConfirmed;
public PodHistory() {
generatePumpId();
}
public PodHistory(PodHistoryEntryType podDbEntryType) { public PodHistory(PodHistoryEntryType podDbEntryType) {

View file

@ -41,6 +41,7 @@ public class OmnipodConst {
public static final Duration EXPIRATION_ADVISORY_WINDOW = Duration.standardHours(2); public static final Duration EXPIRATION_ADVISORY_WINDOW = Duration.standardHours(2);
public static final Duration END_OF_SERVICE_IMMINENT_WINDOW = Duration.standardHours(1); public static final Duration END_OF_SERVICE_IMMINENT_WINDOW = Duration.standardHours(1);
public static final Duration NOMINAL_POD_LIFE = SERVICE_DURATION.minus(END_OF_SERVICE_IMMINENT_WINDOW).minus(EXPIRATION_ADVISORY_WINDOW); public static final Duration NOMINAL_POD_LIFE = SERVICE_DURATION.minus(END_OF_SERVICE_IMMINENT_WINDOW).minus(EXPIRATION_ADVISORY_WINDOW);
public static final double LOW_RESERVOIR_ALERT = 20.0;
public static final double POD_PRIME_BOLUS_UNITS = 2.6; public static final double POD_PRIME_BOLUS_UNITS = 2.6;
public static final double POD_CANNULA_INSERTION_BOLUS_UNITS = 0.5; public static final double POD_CANNULA_INSERTION_BOLUS_UNITS = 0.5;

View file

@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodDeviceState;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState;
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange; import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange;
import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged;
import info.nightscout.androidaps.plugins.pump.omnipod.service.RileyLinkOmnipodService; import info.nightscout.androidaps.plugins.pump.omnipod.service.RileyLinkOmnipodService;
import info.nightscout.androidaps.utils.OKDialog; import info.nightscout.androidaps.utils.OKDialog;
@ -171,8 +172,8 @@ public class OmnipodUtil extends RileyLinkUtil {
} }
public static void setPodDeviceState(PodDeviceState podSessionState) { public static void setPodDeviceState(PodDeviceState podDeviceState) {
omnipodPumpStatus.podDeviceState = podSessionState; omnipodPumpStatus.podDeviceState = podDeviceState;
} }

View file

@ -1727,6 +1727,13 @@
<string name="omnipod_dash_name" translatable="false">Omnipod Dash</string> <string name="omnipod_dash_name" translatable="false">Omnipod Dash</string>
<string name="omnipod_dash_name_short" translatable="false">DASH</string> <string name="omnipod_dash_name_short" translatable="false">DASH</string>
<string name="description_pump_omnipod_dash">Pump integration for Omnipod Dash.</string> <string name="description_pump_omnipod_dash">Pump integration for Omnipod Dash.</string>
<string name="omnipod_alert_finish_pairing_reminder">Finish pairing reminder</string>
<string name="omnipod_alert_finish_setup_reminder_reminder">Finish setup reminder</string>
<string name="omnipod_alert_expiration">Pod wil expire soon</string>
<string name="omnipod_alert_expiration_advisory">Pod will expire soon</string>
<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>
</resources> </resources>

View file

@ -4,6 +4,7 @@ import org.joda.time.Duration;
import org.junit.Test; import org.junit.Test;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration;
@ -12,6 +13,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepRepeat; import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepRepeat;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.TimerAlertTrigger; import info.nightscout.androidaps.plugins.pump.omnipod.defs.TimerAlertTrigger;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.UnitsRemainingAlertTrigger;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
@ -73,5 +75,24 @@ public class ConfigureAlertsCommandTest {
configureAlertsCommand.getRawData()); configureAlertsCommand.getRawData());
} }
// TODO add tests @Test
public void testLowReservoirAlert() {
AlertConfiguration alertConfiguration = new AlertConfiguration(//
AlertType.LOW_RESERVOIR_ALERT, //
AlertSlot.SLOT4, //
true, //
false, //
Duration.ZERO, //
new UnitsRemainingAlertTrigger(10.0), //
BeepType.BEEP_BEEP_BEEP_BEEP, //
BeepRepeat.EVERY_MINUTE_FOR_15_MINUTES);
ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand( //
0xae01a66c, //
Collections.singletonList(alertConfiguration));
assertArrayEquals(
ByteUtil.fromHexString("190aae01a66c4c0000640102"), //
configureAlertsCommand.getRawData());
}
} }

View file

@ -4,6 +4,7 @@ import org.joda.time.Duration;
import org.junit.Test; import org.junit.Test;
import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus; import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus;
import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst;
@ -44,7 +45,7 @@ public class StatusResponseTest {
assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, statusResponse.getPodProgressStatus()); assertEquals(PodProgressStatus.RUNNING_ABOVE_FIFTY_UNITS, statusResponse.getPodProgressStatus());
assertNull("Reservoir level should be null", statusResponse.getReservoirLevel()); assertNull("Reservoir level should be null", statusResponse.getReservoirLevel());
assertEquals(Duration.standardMinutes(1307).getMillis(), statusResponse.getTimeActive().getMillis()); assertEquals(Duration.standardMinutes(1307).getMillis(), statusResponse.getTimeActive().getMillis());
assertEquals(60.05, statusResponse.getInsulin(), 0.000001); assertEquals(60.05, statusResponse.getInsulinDelivered(), 0.000001);
assertEquals(15, statusResponse.getPodMessageCounter()); assertEquals(15, statusResponse.getPodMessageCounter());
assertEquals(0, statusResponse.getInsulinNotDelivered(), 0.000001); assertEquals(0, statusResponse.getInsulinNotDelivered(), 0.000001);
assertEquals(0, statusResponse.getAlerts().getAlertSlots().size()); assertEquals(0, statusResponse.getAlerts().getAlertSlots().size());
@ -52,30 +53,52 @@ public class StatusResponseTest {
assertArrayEquals(ByteUtil.fromHexString("1d180258f80000146fff"), statusResponse.getRawData()); assertArrayEquals(ByteUtil.fromHexString("1d180258f80000146fff"), statusResponse.getRawData());
} }
@Test
public void testWithSampleCaptureWithReplacePodSoonAlert() {
byte[] bytes = ByteUtil.fromHexString("1d19061f6800044295e8"); // From https://github.com/openaps/openomni/wiki/Status-Response-1D-long-run-%28Lytrix%29
StatusResponse statusResponse = new StatusResponse(bytes);
assertEquals(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus());
assertEquals(PodProgressStatus.RUNNING_BELOW_FIFTY_UNITS, statusResponse.getPodProgressStatus());
assertEquals(24.4, statusResponse.getReservoirLevel(), 0.000001);
assertEquals(Duration.standardMinutes(4261).getMillis(), statusResponse.getTimeActive().getMillis());
assertEquals(156.7, statusResponse.getInsulinDelivered(), 0.000001);
assertEquals(13, statusResponse.getPodMessageCounter());
assertEquals(0, statusResponse.getInsulinNotDelivered(), 0.000001);
assertEquals(1, statusResponse.getAlerts().getAlertSlots().size());
assertEquals(AlertSlot.SLOT3, statusResponse.getAlerts().getAlertSlots().get(0));
assertArrayEquals(ByteUtil.fromHexString("1d19061f6800044295e8"), statusResponse.getRawData());
}
@Test @Test
public void testLargeValues() { public void testLargeValues() {
byte[] bytes = ByteUtil.fromHexString("0011ffffffffffffffffff"); byte[] bytes = ByteUtil.fromHexString("1d11ffffffffffffffff");
StatusResponse statusResponse = new StatusResponse(bytes); StatusResponse statusResponse = new StatusResponse(bytes);
assertEquals(Duration.standardMinutes(8191).getMillis(), statusResponse.getTimeActive().getMillis()); assertEquals(Duration.standardMinutes(8191).getMillis(), statusResponse.getTimeActive().getMillis());
assertEquals(OmnipodConst.POD_PULSE_SIZE * 1023, statusResponse.getInsulinNotDelivered(), 0.000001); assertEquals(OmnipodConst.POD_PULSE_SIZE * 1023, statusResponse.getInsulinNotDelivered(), 0.000001);
assertNull("Reservoir level should be null", statusResponse.getReservoirLevel()); assertNull("Reservoir level should be null", statusResponse.getReservoirLevel());
assertEquals(OmnipodConst.POD_PULSE_SIZE * 8191, statusResponse.getInsulin(), 0.0000001); assertEquals(OmnipodConst.POD_PULSE_SIZE * 8191, statusResponse.getInsulinDelivered(), 0.0000001);
assertEquals(15, statusResponse.getPodMessageCounter()); assertEquals(15, statusResponse.getPodMessageCounter());
assertEquals(8, statusResponse.getAlerts().getAlertSlots().size()); assertEquals(8, statusResponse.getAlerts().getAlertSlots().size());
assertArrayEquals(ByteUtil.fromHexString("1d11ffffffffffffffff"), statusResponse.getRawData());
} }
@Test @Test
public void testWithReservoirLevel() { public void testWithReservoirLevel() {
byte[] bytes = ByteUtil.fromHexString("1d19050ec82c08376f9801dc"); byte[] bytes = ByteUtil.fromHexString("1d19050ec82c08376f98");
StatusResponse statusResponse = new StatusResponse(bytes); StatusResponse statusResponse = new StatusResponse(bytes);
assertTrue(Duration.standardMinutes(3547).isEqual(statusResponse.getTimeActive())); assertTrue(Duration.standardMinutes(3547).isEqual(statusResponse.getTimeActive()));
assertEquals(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus()); assertEquals(DeliveryStatus.NORMAL, statusResponse.getDeliveryStatus());
assertEquals(PodProgressStatus.RUNNING_BELOW_FIFTY_UNITS, statusResponse.getPodProgressStatus()); assertEquals(PodProgressStatus.RUNNING_BELOW_FIFTY_UNITS, statusResponse.getPodProgressStatus());
assertEquals(129.45, statusResponse.getInsulin(), 0.00001); assertEquals(129.45, statusResponse.getInsulinDelivered(), 0.00001);
assertEquals(46.00, statusResponse.getReservoirLevel(), 0.00001); assertEquals(46.00, statusResponse.getReservoirLevel(), 0.00001);
assertEquals(2.2, statusResponse.getInsulinNotDelivered(), 0.0001); assertEquals(2.2, statusResponse.getInsulinNotDelivered(), 0.0001);
assertEquals(9, statusResponse.getPodMessageCounter()); assertEquals(9, statusResponse.getPodMessageCounter());
assertArrayEquals(ByteUtil.fromHexString("1d19050ec82c08376f98"), statusResponse.getRawData());
} }
} }