diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt index 1d7c37929f..eb6e39d0ac 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWDefinition.kt @@ -30,6 +30,7 @@ import info.nightscout.androidaps.plugins.profile.local.LocalProfileFragment import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.plugins.profile.ns.NSProfileFragment import info.nightscout.androidaps.plugins.profile.ns.NSProfilePlugin +import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin import info.nightscout.androidaps.setupwizard.elements.* import info.nightscout.androidaps.setupwizard.events.EventSWUpdate @@ -324,6 +325,12 @@ class SWDefinition @Inject constructor( val activePump = activePlugin.activePump activePump is OmnipodPumpPlugin && !activePump.isRileyLinkReady })) + .add( // Omnipod only + SWEventListener(injector, EventRileyLinkDeviceStatusChange::class.java) + .label(R.string.setupwizard_pump_riley_link_status) + .visibility(SWValidator { + activePlugin.activePump is OmnipodPumpPlugin + })) .add(SWButton(injector) .text(R.string.readstatus) .action(Runnable { commandQueue.readStatus("Clicked connect to pump", null) }) @@ -332,7 +339,8 @@ class SWDefinition @Inject constructor( // Getting the status might not be possible activePlugin.activePump !is OmnipodPumpPlugin })) - .add(SWEventListener(injector, EventPumpStatusChanged::class.java)) + .add(SWEventListener(injector, EventPumpStatusChanged::class.java) + .visibility(SWValidator { activePlugin.activePump !is OmnipodPumpPlugin })) .validator(SWValidator { isPumpInitialized() }) diff --git a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.kt b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.kt index 9757cbca32..5a7806b9a7 100644 --- a/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.kt +++ b/app/src/main/java/info/nightscout/androidaps/setupwizard/SWEventListener.kt @@ -11,7 +11,7 @@ import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable class SWEventListener constructor( - injector:HasAndroidInjector, + injector: HasAndroidInjector, clazz: Class ) : SWItem(injector, Type.LISTENER) { @@ -19,6 +19,7 @@ class SWEventListener constructor( private var textLabel = 0 private var status = "" private var textView: TextView? = null + private var visibilityValidator: SWValidator? = null // TODO: Adrian how to clear disposable in this case? init { @@ -43,6 +44,11 @@ class SWEventListener constructor( return this } + fun visibility(visibilityValidator: SWValidator): SWEventListener { + this.visibilityValidator = visibilityValidator + return this + } + @SuppressLint("SetTextI18n") override fun generateDialog(layout: LinearLayout) { val context = layout.context @@ -51,4 +57,8 @@ class SWEventListener constructor( textView?.text = (if (textLabel != 0) resourceHelper.gs(textLabel) else "") + " " + status layout.addView(textView) } + + override fun processVisibility() { + if (visibilityValidator != null && !visibilityValidator!!.isValid) textView?.visibility = View.GONE else textView?.visibility = View.VISIBLE + } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 18821434c3..891c266dd0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1446,4 +1446,5 @@ Worker State: %s Uploaded Data The following data will be uploaded to your Open Humans account: Glucose values, boluses, carbs, careportal events (except notes), extended boluses, profile switches, total daily doses, temporary basals, temp targets, preferences, application version, device model and screen dimensions. Secret or private information such as your Nightscout URL or API secret will not be uploaded. + RileyLink status: diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index b036d0b02c..a3320cf61a 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -72,6 +72,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodCustomA import info.nightscout.androidaps.plugins.pump.omnipod.definition.OmnipodStorageKeys; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.ExpirationReminderBuilder; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; @@ -254,6 +255,13 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, // When PodStateManager is created, which causes an IllegalArgumentException for DateTimeZones not being recognized podStateManager.loadPodState(); + // BS @ 2020-10-17 FIXME: for backwards compatibility; remove before release + if (podStateManager.isPodInitialized() && + podStateManager.getActivationProgress() == ActivationProgress.NONE && + podStateManager.getPodProgressStatus().isAtLeast(PodProgressStatus.ABOVE_FIFTY_UNITS)) { + podStateManager.setActivationProgress(ActivationProgress.COMPLETED); + } + lastConnectionTimeMillis = sp.getLong( RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); @@ -895,8 +903,14 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, @NonNull @Override public PumpEnactResult setTempBasalPercent(Integer percent, Integer durationInMinutes, Profile profile, boolean enforceNew) { - aapsLogger.debug(LTag.PUMP, "setTempBasalPercent [OmnipodPumpPlugin] - Not implemented."); - return getOperationNotSupportedWithCustomText(info.nightscout.androidaps.core.R.string.pump_operation_not_supported_by_pump_driver); + if (percent == 0) { + return setTempBasalAbsolute(0.0d, durationInMinutes, profile, enforceNew); + } else { + double absoluteValue = profile.getBasal() * (percent / 100.0d); + absoluteValue = pumpDescription.pumpType.determineCorrectBasalSize(absoluteValue); + aapsLogger.warn(LTag.PUMP, "setTempBasalPercent [OmnipodPumpPlugin] - You are trying to use setTempBasalPercent with percent other then 0% (" + percent + "). This will start setTempBasalAbsolute, with calculated value (" + absoluteValue + "). Result might not be 100% correct."); + return setTempBasalAbsolute(absoluteValue, durationInMinutes, profile, enforceNew); + } } @NonNull @Override public PumpEnactResult setExtendedBolus(Double insulin, Integer @@ -916,7 +930,7 @@ public class OmnipodPumpPlugin extends PumpPluginBase implements PumpInterface, } private void initializeAfterRileyLinkConnection() { - if (podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus().isAtLeast(PodProgressStatus.PAIRING_COMPLETED)) { + if (podStateManager.getActivationProgress().isAtLeast(ActivationProgress.PAIRING_COMPLETED)) { for (int i = 0; STARTUP_STATUS_REQUEST_TRIES > i; i++) { PumpEnactResult result = executeCommand(OmnipodCommandType.GET_POD_STATUS, aapsOmnipodManager::getPodStatus); if (result.success) { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java index 9f8fc4296a..fb1127cecc 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/AssignAddressAction.java @@ -5,54 +5,68 @@ import org.joda.time.DateTimeZone; import java.util.Collections; import java.util.Random; +import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.AssignAddressCommand; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.VersionResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class AssignAddressAction implements OmnipodAction { +public class AssignAddressAction implements OmnipodAction { private final PodStateManager podStateManager; + private final AAPSLogger aapsLogger; - public AssignAddressAction(PodStateManager podStateManager) { + public AssignAddressAction(PodStateManager podStateManager, AAPSLogger aapsLogger) { if (podStateManager == null) { throw new IllegalArgumentException("podStateManager can not be null"); } + if (aapsLogger == null) { + throw new IllegalArgumentException("Logger can not be null"); + } this.podStateManager = podStateManager; + this.aapsLogger = aapsLogger; } @Override - public VersionResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { if (!podStateManager.hasPodState()) { podStateManager.initState(generateRandomAddress()); } - if (podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.REMINDER_INITIALIZED)) { - throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, podStateManager.getPodProgressStatus()); + + if (podStateManager.getActivationProgress().needsPairing()) { + AssignAddressCommand assignAddress = new AssignAddressCommand(podStateManager.getAddress()); + OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, + Collections.singletonList(assignAddress), podStateManager.getMessageNumber()); + + try { + VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, assignAddressMessage, + OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); + + if (!assignAddressResponse.isAssignAddressVersionResponse()) { + throw new IllegalVersionResponseTypeException("assignAddress", "setupPod"); + } + if (assignAddressResponse.getAddress() != podStateManager.getAddress()) { + throw new IllegalMessageAddressException(podStateManager.getAddress(), assignAddressResponse.getAddress()); + } + + podStateManager.setInitializationParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), // + assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus()); + } catch (IllegalPacketTypeException ex) { + if (ex.getActual() == PacketType.ACK && podStateManager.isPodInitialized()) { + // When we already assigned the address before, it's possible to only get an ACK here + aapsLogger.debug("Received ACK instead of response in AssignAddressAction. Ignoring because we already assigned the address successfully"); + } else { + throw ex; + } + } } - AssignAddressCommand assignAddress = new AssignAddressCommand(podStateManager.getAddress()); - OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, - Collections.singletonList(assignAddress), podStateManager.getMessageNumber()); - - VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, assignAddressMessage, - OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); - - if (!assignAddressResponse.isAssignAddressVersionResponse()) { - throw new IllegalVersionResponseTypeException("assignAddress", "setupPod"); - } - if (assignAddressResponse.getAddress() != podStateManager.getAddress()) { - throw new IllegalMessageAddressException(podStateManager.getAddress(), assignAddressResponse.getAddress()); - } - - podStateManager.setInitializationParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), // - assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault(), assignAddressResponse.getPodProgressStatus()); - - return assignAddressResponse; + return null; } private static int generateRandomAddress() { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java index 7dae20fea9..ff47b1b900 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/InsertCannulaAction.java @@ -6,16 +6,15 @@ import java.util.List; import java.util.Optional; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.ExpirationReminderBuilder; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalActivationProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class InsertCannulaAction implements OmnipodAction { +public class InsertCannulaAction implements OmnipodAction { private final PodStateManager podStateManager; private final BasalSchedule initialBasalSchedule; @@ -37,31 +36,33 @@ public class InsertCannulaAction implements OmnipodAction { } @Override - public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) { - throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null); + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { + if (podStateManager.getActivationProgress().isBefore(ActivationProgress.PRIMING_COMPLETED)) { + throw new IllegalActivationProgressException(ActivationProgress.PRIMING_COMPLETED, podStateManager.getActivationProgress()); } - if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.BASAL_INITIALIZED)) { + if (podStateManager.getActivationProgress().needsBasalSchedule()) { podStateManager.setBasalSchedule(initialBasalSchedule); communicationService.executeAction(new SetBasalScheduleAction(podStateManager, initialBasalSchedule, true, podStateManager.getScheduleOffset(), false)); + podStateManager.setActivationProgress(ActivationProgress.BASAL_INITIALIZED); } - if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.INSERTING_CANNULA)) { + if (podStateManager.getActivationProgress().needsExpirationReminders()) { communicationService.executeAction(new ConfigureAlertsAction(podStateManager, buildAlertConfigurations())); podStateManager.setExpirationAlertTimeBeforeShutdown(expirationReminderTimeBeforeShutdown); podStateManager.setLowReservoirAlertUnits(lowReservoirAlertUnits); - - return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, - Duration.standardSeconds(1), false, false)); - } else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.INSERTING_CANNULA)) { - // Check status - return communicationService.executeAction(new GetStatusAction(podStateManager)); - } else { - throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus()); + podStateManager.setActivationProgress(ActivationProgress.EXPIRATION_REMINDERS_SET); } + + if (podStateManager.getActivationProgress().needsCannulaInsertion()) { + communicationService.executeAction(new BolusAction(podStateManager, OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, + Duration.standardSeconds(1), false, false)); + podStateManager.setActivationProgress(ActivationProgress.INSERTING_CANNULA); + } + + return null; } private List buildAlertConfigurations() { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java index 44c50e1a38..c1269e3e39 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/PrimeAction.java @@ -1,13 +1,12 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.action.service.PrimeService; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalActivationProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class PrimeAction implements OmnipodAction { +public class PrimeAction implements OmnipodAction { private final PrimeService service; private final PodStateManager podStateManager; @@ -24,21 +23,27 @@ public class PrimeAction implements OmnipodAction { } @Override - public StatusResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) { - throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null); + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { + if (podStateManager.getActivationProgress().isBefore(ActivationProgress.PAIRING_COMPLETED)) { + throw new IllegalActivationProgressException(ActivationProgress.PAIRING_COMPLETED, podStateManager.getActivationProgress()); } - if (podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING)) { + + if (podStateManager.getActivationProgress().needsDisableTab5Sub16And17()) { // FaultConfigCommand sets internal pod variables to effectively disable $6x faults which occur more often with a 0 TBR service.executeDisableTab5Sub16And17FaultConfigCommand(communicationService, podStateManager); - - service.executeFinishSetupReminderAlertCommand(communicationService, podStateManager); - return service.executePrimeBolusCommand(communicationService, podStateManager); - } else if (podStateManager.getPodProgressStatus().equals(PodProgressStatus.PRIMING)) { - // Check status - return communicationService.executeAction(new GetStatusAction(podStateManager)); - } else { - throw new IllegalPodProgressException(null, podStateManager.getPodProgressStatus()); + podStateManager.setActivationProgress(ActivationProgress.TAB_5_SUB_16_AND_17_DISABLED); } + + if (podStateManager.getActivationProgress().needsSetupReminders()) { + service.executeFinishSetupReminderAlertCommand(communicationService, podStateManager); + podStateManager.setActivationProgress(ActivationProgress.SETUP_REMINDERS_SET); + } + + if (podStateManager.getActivationProgress().needsPriming()) { + service.executePrimeBolusCommand(communicationService, podStateManager); + podStateManager.setActivationProgress(ActivationProgress.PRIMING); + } + + return null; } } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java index f811e711db..8cb2a1ddde 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/action/SetupPodAction.java @@ -4,49 +4,72 @@ import org.joda.time.DateTime; import java.util.Collections; +import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.command.SetupPodCommand; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.VersionResponse; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.rileylink.manager.OmnipodRileyLinkCommunicationManager; -public class SetupPodAction implements OmnipodAction { +public class SetupPodAction implements OmnipodAction { private final PodStateManager podStateManager; + private final AAPSLogger aapsLogger; - public SetupPodAction(PodStateManager podStateManager) { + public SetupPodAction(PodStateManager podStateManager, AAPSLogger aapsLogger) { if (podStateManager == null) { throw new IllegalArgumentException("Pod state manager can not be null"); } + if (aapsLogger == null) { + throw new IllegalArgumentException("Logger can not be null"); + } this.podStateManager = podStateManager; + this.aapsLogger = aapsLogger; } @Override - public VersionResponse execute(OmnipodRileyLinkCommunicationManager communicationService) { - if (!podStateManager.isPodInitialized() || !podStateManager.getPodProgressStatus().equals(PodProgressStatus.REMINDER_INITIALIZED)) { + public Void execute(OmnipodRileyLinkCommunicationManager communicationService) { + if (!podStateManager.isPodInitialized()) { throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, podStateManager.isPodInitialized() ? podStateManager.getPodProgressStatus() : null); } - DateTime activationDate = DateTime.now(podStateManager.getTimeZone()); - SetupPodCommand setupPodCommand = new SetupPodCommand(podStateManager.getAddress(), activationDate, - podStateManager.getLot(), podStateManager.getTid()); - OmnipodMessage message = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, - Collections.singletonList(setupPodCommand), podStateManager.getMessageNumber()); - VersionResponse setupPodResponse; - setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, - message, OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); + if (podStateManager.getActivationProgress().needsPairing()) { + DateTime activationDate = DateTime.now(podStateManager.getTimeZone()); - if (!setupPodResponse.isSetupPodVersionResponse()) { - throw new IllegalVersionResponseTypeException("setupPod", "assignAddress"); - } - if (setupPodResponse.getAddress() != podStateManager.getAddress()) { - throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress()); + SetupPodCommand setupPodCommand = new SetupPodCommand(podStateManager.getAddress(), activationDate, + podStateManager.getLot(), podStateManager.getTid()); + OmnipodMessage message = new OmnipodMessage(OmnipodConstants.DEFAULT_ADDRESS, + Collections.singletonList(setupPodCommand), podStateManager.getMessageNumber()); + + try { + VersionResponse setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, + message, OmnipodConstants.DEFAULT_ADDRESS, podStateManager.getAddress()); + + if (!setupPodResponse.isSetupPodVersionResponse()) { + throw new IllegalVersionResponseTypeException("setupPod", "assignAddress"); + } + if (setupPodResponse.getAddress() != podStateManager.getAddress()) { + throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress()); + } + } catch (IllegalPacketTypeException ex) { + if (PacketType.ACK.equals(ex.getActual())) { + // Pod is already configured + aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring"); + } else { + throw ex; + } + } + + podStateManager.setActivationProgress(ActivationProgress.PAIRING_COMPLETED); } - return setupPodResponse; + return null; } } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/TempBasalExtraCommand.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/TempBasalExtraCommand.java index baac0f9305..8f5cf5053b 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/TempBasalExtraCommand.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/TempBasalExtraCommand.java @@ -27,7 +27,10 @@ public class TempBasalExtraCommand extends MessageBlock { } else if (rate > OmnipodConstants.MAX_BASAL_RATE) { throw new IllegalArgumentException("Rate exceeds max basal rate"); } - if (duration.isLongerThan(OmnipodConstants.MAX_TEMP_BASAL_DURATION)) { + + if (duration.isShorterThan(Duration.ZERO) || duration.equals(Duration.ZERO)) { + throw new IllegalArgumentException("Duration should be > 0"); + } else if (duration.isLongerThan(OmnipodConstants.MAX_TEMP_BASAL_DURATION)) { throw new IllegalArgumentException("Duration exceeds max temp basal duration"); } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/ErrorResponse.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/ErrorResponse.java index 2ef230ba2f..58f68ca6fd 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/ErrorResponse.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/ErrorResponse.java @@ -12,9 +12,11 @@ public class ErrorResponse extends MessageBlock { private static final int MESSAGE_LENGTH = 5; private final byte errorResponseCode; - private Integer nonceSearchKey; // only valid for BAD_NONCE - private FaultEventCode faultEventCode; // valid for all but BAD_NONCE - private PodProgressStatus podProgressStatus; // valid for all but BAD_NONCE + + private final Integer nonceSearchKey; // only valid for BAD_NONCE + private final FaultEventCode faultEventCode; // valid for all but BAD_NONCE + + private final PodProgressStatus podProgressStatus; // valid for all but BAD_NONCE public ErrorResponse(byte[] encodedData) { if (encodedData.length < MESSAGE_LENGTH) { @@ -24,11 +26,16 @@ public class ErrorResponse extends MessageBlock { errorResponseCode = encodedData[2]; - if (this.errorResponseCode == ERROR_RESPONSE_CODE_BAD_NONCE) { + if (errorResponseCode == ERROR_RESPONSE_CODE_BAD_NONCE) { nonceSearchKey = ByteUtil.makeUnsignedShort(encodedData[3], encodedData[4]); + + faultEventCode = null; + podProgressStatus = null; } else { faultEventCode = FaultEventCode.fromByte(encodedData[3]); podProgressStatus = PodProgressStatus.fromByte(encodedData[4]); + + nonceSearchKey = null; } } @@ -53,8 +60,7 @@ public class ErrorResponse extends MessageBlock { return nonceSearchKey; } - @Override - public String toString() { + @Override public String toString() { return "ErrorResponse{" + "errorResponseCode=" + errorResponseCode + ", nonceSearchKey=" + nonceSearchKey + diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoActiveAlerts.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoActiveAlerts.java index 6723a0a0da..36e1b1a213 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoActiveAlerts.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoActiveAlerts.java @@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mes import org.joda.time.Duration; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; @@ -54,7 +53,7 @@ public class PodInfoActiveAlerts extends PodInfo { @Override public String toString() { return "PodInfoActiveAlerts{" + - "word278=" + Arrays.toString(word278) + + "word278=" + ByteUtil.shortHexString(word278) + ", alertActivations=" + alertActivations + '}'; } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoFaultEvent.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoDetailedStatus.java similarity index 79% rename from omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoFaultEvent.java rename to omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoDetailedStatus.java index 13a782fdf7..0db5ed2b53 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoFaultEvent.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoDetailedStatus.java @@ -6,13 +6,13 @@ import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ErrorEventInfo; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.LogEventErrorCode; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; -public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableResponse { +public class PodInfoDetailedStatus extends PodInfo implements StatusUpdatableResponse { private static final int MINIMUM_MESSAGE_LENGTH = 21; private final PodProgressStatus podProgressStatus; @@ -27,14 +27,13 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons private final Duration timeActive; private final AlertSet unacknowledgedAlerts; private final boolean faultAccessingTables; - private final LogEventErrorCode logEventErrorType; - private final PodProgressStatus logEventErrorPodProgressStatus; + private final ErrorEventInfo errorEventInfo; private final byte receiverLowGain; private final byte radioRSSI; - private final PodProgressStatus podProgressStatusAtTimeOfFirstLoggedFaultEvent; + private final PodProgressStatus previousPodProgressStatus; private final byte[] unknownValue; - public PodInfoFaultEvent(byte[] encodedData) { + public PodInfoDetailedStatus(byte[] encodedData) { super(encodedData); if (encodedData.length < MINIMUM_MESSAGE_LENGTH) { @@ -69,19 +68,33 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons unacknowledgedAlerts = new AlertSet(encodedData[15]); faultAccessingTables = encodedData[16] == 0x02; - int i = ByteUtil.convertUnsignedByteToInt(encodedData[17]); - byte value = (byte) (i >>> 4); - logEventErrorType = LogEventErrorCode.fromByte(value); - logEventErrorPodProgressStatus = PodProgressStatus.fromByte((byte) (encodedData[17] & 0x0f)); + byte rawErrorEventInfo = encodedData[17]; + if (rawErrorEventInfo == 0x00) { + errorEventInfo = null; + } else { + errorEventInfo = ErrorEventInfo.fromByte(rawErrorEventInfo); + } receiverLowGain = (byte) (ByteUtil.convertUnsignedByteToInt(encodedData[18]) >>> 6); radioRSSI = (byte) (encodedData[18] & 0x3f); - podProgressStatusAtTimeOfFirstLoggedFaultEvent = PodProgressStatus.fromByte((byte) (encodedData[19] & 0x0f)); + if (ByteUtil.convertUnsignedByteToInt(encodedData[19]) == 0xff) { // this byte is not valid (no fault has occurred) + previousPodProgressStatus = null; + } else { + previousPodProgressStatus = PodProgressStatus.fromByte((byte) (encodedData[19] & 0x0f)); + } unknownValue = ByteUtil.substring(encodedData, 20, 2); } @Override public PodInfoType getType() { - return PodInfoType.FAULT_EVENT; + return PodInfoType.DETAILED_STATUS; + } + + public boolean isFaulted() { + return faultEventCode != null; + } + + public boolean isActivationTimeExceeded() { + return podProgressStatus == PodProgressStatus.ACTIVATION_TIME_EXCEEDED; } @Override public PodProgressStatus getPodProgressStatus() { @@ -132,12 +145,8 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons return faultAccessingTables; } - public LogEventErrorCode getLogEventErrorType() { - return logEventErrorType; - } - - public PodProgressStatus getLogEventErrorPodProgressStatus() { - return logEventErrorPodProgressStatus; + public ErrorEventInfo getErrorEventInfo() { + return errorEventInfo; } public byte getReceiverLowGain() { @@ -148,8 +157,8 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons return radioRSSI; } - public PodProgressStatus getPodProgressStatusAtTimeOfFirstLoggedFaultEvent() { - return podProgressStatusAtTimeOfFirstLoggedFaultEvent; + public PodProgressStatus getPreviousPodProgressStatus() { + return previousPodProgressStatus; } public byte[] getUnknownValue() { @@ -157,7 +166,7 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons } @Override public String toString() { - return "PodInfoFaultEvent{" + + return "PodInfoDetailedStatus{" + "podProgressStatus=" + podProgressStatus + ", deliveryStatus=" + deliveryStatus + ", bolusNotDelivered=" + bolusNotDelivered + @@ -170,11 +179,10 @@ public class PodInfoFaultEvent extends PodInfo implements StatusUpdatableRespons ", timeActive=" + timeActive + ", unacknowledgedAlerts=" + unacknowledgedAlerts + ", faultAccessingTables=" + faultAccessingTables + - ", logEventErrorType=" + logEventErrorType + - ", logEventErrorPodProgressStatus=" + logEventErrorPodProgressStatus + + ", errorEventInfo=" + errorEventInfo + ", receiverLowGain=" + receiverLowGain + ", radioRSSI=" + radioRSSI + - ", podProgressStatusAtTimeOfFirstLoggedFaultEvent=" + podProgressStatusAtTimeOfFirstLoggedFaultEvent + + ", previousPodProgressStatus=" + previousPodProgressStatus + ", unknownValue=" + ByteUtil.shortHexString(unknownValue) + '}'; } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/ActivationProgress.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/ActivationProgress.java new file mode 100644 index 0000000000..9db21f5e59 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/ActivationProgress.java @@ -0,0 +1,66 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition; + +public enum ActivationProgress { + NONE, + PAIRING_COMPLETED, + TAB_5_SUB_16_AND_17_DISABLED, + SETUP_REMINDERS_SET, + PRIMING, + PRIMING_COMPLETED, + BASAL_INITIALIZED, + EXPIRATION_REMINDERS_SET, + INSERTING_CANNULA, + COMPLETED; + + public boolean needsPairing() { + return this == NONE; + } + + public boolean needsDisableTab5Sub16And17() { + return this == PAIRING_COMPLETED; + } + + public boolean needsSetupReminders() { + return this == TAB_5_SUB_16_AND_17_DISABLED; + } + + public boolean needsPriming() { + return this == SETUP_REMINDERS_SET; + } + + public boolean needsPrimingVerification() { + return this == PRIMING; + } + + public boolean needsBasalSchedule() { + return this == PRIMING_COMPLETED; + } + + public boolean needsExpirationReminders() { + return this == BASAL_INITIALIZED; + } + + public boolean needsCannulaInsertion() { + return this == EXPIRATION_REMINDERS_SET; + } + + public boolean needsCannulaInsertionVerification() { + return this == INSERTING_CANNULA; + } + + public boolean isCompleted() { + return this == COMPLETED; + } + + public boolean isBefore(ActivationProgress other) { + return ordinal() < other.ordinal(); + } + + public boolean isAtLeast(ActivationProgress other) { + return ordinal() >= other.ordinal(); + } + + public boolean isAfter(ActivationProgress other) { + return ordinal() > other.ordinal(); + } +} \ No newline at end of file diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/ErrorEventInfo.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/ErrorEventInfo.java new file mode 100644 index 0000000000..2f3e064d36 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/ErrorEventInfo.java @@ -0,0 +1,52 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; + +public final class ErrorEventInfo { + private final boolean insulinStateTableCorruption; + private final byte internalVariable; + private final boolean immediateBolusInProgress; + private final PodProgressStatus podProgressStatus; + + private ErrorEventInfo(boolean insulinStateTableCorruption, byte internalVariable, boolean immediateBolusInProgress, PodProgressStatus podProgressStatus) { + this.insulinStateTableCorruption = insulinStateTableCorruption; + this.internalVariable = internalVariable; + this.immediateBolusInProgress = immediateBolusInProgress; + this.podProgressStatus = podProgressStatus; + } + + public static ErrorEventInfo fromByte(byte faultEventInfo) { + int loggedFaultEventInfo = ByteUtil.convertUnsignedByteToInt(faultEventInfo); + boolean insulinStateTableCorruption = (loggedFaultEventInfo & 0x80) == 0x80; + byte internalVariable = (byte) ((loggedFaultEventInfo >>> 5) & 0x03); + boolean immediateBolusInProgress = (loggedFaultEventInfo & 0x10) == 0x10; + PodProgressStatus podProgressStatus = PodProgressStatus.fromByte((byte) (loggedFaultEventInfo & 0x0f)); + + return new ErrorEventInfo(insulinStateTableCorruption, internalVariable, immediateBolusInProgress, podProgressStatus); + } + + public boolean isInsulinStateTableCorruption() { + return insulinStateTableCorruption; + } + + public byte getInternalVariable() { + return internalVariable; + } + + public boolean isImmediateBolusInProgress() { + return immediateBolusInProgress; + } + + public PodProgressStatus getPodProgressStatus() { + return podProgressStatus; + } + + @Override public String toString() { + return "ErrorEventInfo{" + + "insulinStateTableCorruption=" + insulinStateTableCorruption + + ", internalVariable=" + internalVariable + + ", immediateBolusInProgress=" + immediateBolusInProgress + + ", podProgressStatus=" + podProgressStatus + + '}'; + } +} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/FaultEventCode.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/FaultEventCode.java index a6fac508db..0a42811848 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/FaultEventCode.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/FaultEventCode.java @@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition; import java.util.Locale; public enum FaultEventCode { - NO_FAULTS((byte) 0x00), FAILED_FLASH_ERASE((byte) 0x01), FAILED_FLASH_STORE((byte) 0x02), TABLE_CORRUPTION_BASAL_SUBCOMMAND((byte) 0x03), @@ -129,6 +128,9 @@ public enum FaultEventCode { } public static FaultEventCode fromByte(byte value) { + if (value == 0x00) { // No faults + return null; + } for (FaultEventCode type : values()) { if (type.value == value) { return type; diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/LogEventErrorCode.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/LogEventErrorCode.java deleted file mode 100644 index eb7223b4f0..0000000000 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/LogEventErrorCode.java +++ /dev/null @@ -1,24 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition; - -public enum LogEventErrorCode { - NONE((byte) 0x00), - IMMEDIATE_BOLUS_IN_PROGRESS((byte) 0x01), - INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_2((byte) 0x02), - INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_3((byte) 0x03), - INSULIN_STATE_TABLE_CORRUPTION((byte) 0x04); - - private final byte value; - - LogEventErrorCode(byte value) { - this.value = value; - } - - public static LogEventErrorCode fromByte(byte value) { - for (LogEventErrorCode type : values()) { - if (type.value == value) { - return type; - } - } - throw new IllegalArgumentException("Unknown LogEventErrorCode: " + value); - } -} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/PodInfoType.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/PodInfoType.java index d85ee9bd3f..4198810aa1 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/PodInfoType.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/definition/PodInfoType.java @@ -3,15 +3,15 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.definition; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfo; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoActiveAlerts; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDataLog; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultAndInitializationTime; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoOlderPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog; public enum PodInfoType { NORMAL((byte) 0x00), ACTIVE_ALERTS((byte) 0x01), - FAULT_EVENT((byte) 0x02), + DETAILED_STATUS((byte) 0x02), DATA_LOG((byte) 0x03), // Similar to types $50 & $51. Returns up to the last 60 dwords of data. FAULT_AND_INITIALIZATION_TIME((byte) 0x05), RECENT_PULSE_LOG((byte) 0x50), // Starting at $4200 @@ -44,8 +44,8 @@ public enum PodInfoType { throw new UnsupportedOperationException("Cannot decode PodInfoType.NORMAL"); case ACTIVE_ALERTS: return new PodInfoActiveAlerts(encodedData); - case FAULT_EVENT: - return new PodInfoFaultEvent(encodedData); + case DETAILED_STATUS: + return new PodInfoDetailedStatus(encodedData); case DATA_LOG: return new PodInfoDataLog(encodedData, bodyLength); case FAULT_AND_INITIALIZATION_TIME: diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/ActivationTimeExceededException.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/ActivationTimeExceededException.java new file mode 100644 index 0000000000..91e4c4bab3 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/ActivationTimeExceededException.java @@ -0,0 +1,7 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.exception; + +public class ActivationTimeExceededException extends OmnipodException { + public ActivationTimeExceededException() { + super("The Pod's activation time has been exceeded", true); + } +} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalActivationProgressException.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalActivationProgressException.java new file mode 100644 index 0000000000..0dffb93517 --- /dev/null +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalActivationProgressException.java @@ -0,0 +1,24 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.exception; + +import java.util.Locale; + +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; + +public class IllegalActivationProgressException extends OmnipodException { + private final ActivationProgress expected; + private final ActivationProgress actual; + + public IllegalActivationProgressException(ActivationProgress expected, ActivationProgress actual) { + super(String.format(Locale.getDefault(), "Illegal activation progress: %s, expected: %s", actual, expected), true); + this.expected = expected; + this.actual = actual; + } + + public ActivationProgress getExpected() { + return expected; + } + + public ActivationProgress getActual() { + return actual; + } +} diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java index da319d5d83..18719fa1ce 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/IllegalPodProgressException.java @@ -9,7 +9,7 @@ public class IllegalPodProgressException extends OmnipodException { private final PodProgressStatus actual; public IllegalPodProgressException(PodProgressStatus expected, PodProgressStatus actual) { - super(String.format(Locale.getDefault(), "Illegal setup state: %s, expected: %s", actual, expected), true); + super(String.format(Locale.getDefault(), "Illegal Pod progress: %s, expected: %s", actual, expected), true); this.expected = expected; this.actual = actual; } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/PodFaultException.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/PodFaultException.java index 884e7481eb..4786f241c7 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/PodFaultException.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/exception/PodFaultException.java @@ -1,16 +1,16 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.exception; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus; public class PodFaultException extends OmnipodException { - private final PodInfoFaultEvent faultEvent; + private final PodInfoDetailedStatus detailedStatus; - public PodFaultException(PodInfoFaultEvent faultEvent) { - super(faultEvent.getFaultEventCode().toString(), true); - this.faultEvent = faultEvent; + public PodFaultException(PodInfoDetailedStatus detailedStatus) { + super(detailedStatus.getFaultEventCode().toString(), true); + this.detailedStatus = detailedStatus; } - public PodInfoFaultEvent getFaultEvent() { - return faultEvent; + public PodInfoDetailedStatus getDetailedStatus() { + return detailedStatus; } } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java index e642fd1f71..e4601e2a68 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/OmnipodManager.java @@ -31,19 +31,19 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.BeepType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CommandFailedAfterChangingDeliveryStatusException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalActivationProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalDeliveryStatusException; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.NonceOutOfSyncException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.OmnipodException; @@ -59,7 +59,7 @@ import io.reactivex.schedulers.Schedulers; import io.reactivex.subjects.SingleSubject; public class OmnipodManager { - private static final int ACTION_VERIFICATION_TRIES = 2; + private static final int ACTION_VERIFICATION_TRIES = 1; private final OmnipodRileyLinkCommunicationManager communicationService; private PodStateManager podStateManager; @@ -88,76 +88,53 @@ public class OmnipodManager { } public synchronized Single pairAndPrime() { - logStartingCommandExecution("pairAndPrime"); - - try { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PAIRING_COMPLETED)) { - // Always send both 0x07 and 0x03 on retries - try { - communicationService.executeAction( - new AssignAddressAction(podStateManager)); - } catch (IllegalPacketTypeException ex) { - if (ex.getActual() == PacketType.ACK && podStateManager.isPodInitialized()) { - // When we already assigned the address before, it's possible to only get an ACK here - aapsLogger.debug("Received ACK instead of response in AssignAddressAction. Ignoring because we already assigned the address successfully"); - } else { - throw ex; - } - } - - try { - communicationService.executeAction(new SetupPodAction(podStateManager)); - } catch (IllegalPacketTypeException ex) { - if (PacketType.ACK.equals(ex.getActual())) { - // TODO is this true for the SetupPodCommand? - // Pod is already configured - aapsLogger.debug("Received ACK instead of response in SetupPodAction. Ignoring"); - } - } - } else if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.PRIMING)) { - throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, podStateManager.getPodProgressStatus()); + if (podStateManager.isPodInitialized()) { + if (podStateManager.getActivationProgress().isAfter(ActivationProgress.PRIMING)) { + return Single.just(true); + } + if (podStateManager.getActivationProgress().needsPrimingVerification()) { + return Single.fromCallable(() -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED, ActivationProgress.PRIMING_COMPLETED)); } - - // Make sure we have an up to date PodProgressStatus - getPodStatus(); - - communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager)); - } finally { - logCommandExecutionFinished("pairAndPrime"); } + // Always send both 0x07 and 0x03 on retries + if (podStateManager.getActivationProgress().isBefore(ActivationProgress.PAIRING_COMPLETED)) { + communicationService.executeAction( + new AssignAddressAction(podStateManager, aapsLogger)); + + communicationService.executeAction(new SetupPodAction(podStateManager, aapsLogger)); + } + + communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager)); + long delayInMillis = calculateEstimatedBolusDuration(DateTime.now().minus(OmnipodConstants.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION), OmnipodConstants.POD_PRIME_BOLUS_UNITS, OmnipodConstants.POD_PRIMING_DELIVERY_RATE).getMillis(); return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) // - .map(o -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED)) // + .map(o -> verifyPodProgressStatus(PodProgressStatus.PRIMING_COMPLETED, ActivationProgress.PRIMING_COMPLETED)) // .subscribeOn(Schedulers.io()); } public synchronized Single insertCannula( BasalSchedule basalSchedule, Duration expirationReminderTimeBeforeShutdown, Integer lowReservoirAlertUnits) { - if (!podStateManager.isPodInitialized() || podStateManager.getPodProgressStatus().isBefore(PodProgressStatus.PRIMING_COMPLETED)) { - throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, !podStateManager.isPodInitialized() ? null : podStateManager.getPodProgressStatus()); + if (podStateManager.getActivationProgress().isBefore(ActivationProgress.PRIMING_COMPLETED)) { + throw new IllegalActivationProgressException(ActivationProgress.PRIMING_COMPLETED, podStateManager.getActivationProgress()); } - // Make sure we have the latest PodProgressStatus - getPodStatus(); - - if (podStateManager.getPodProgressStatus().isAfter(PodProgressStatus.INSERTING_CANNULA)) { - throw new IllegalPodProgressException(PodProgressStatus.PRIMING_COMPLETED, podStateManager.getPodProgressStatus()); + if (podStateManager.isPodInitialized()) { + if (podStateManager.getActivationProgress().isCompleted()) { + return Single.just(true); + } + if (podStateManager.getActivationProgress().needsCannulaInsertionVerification()) { + return Single.fromCallable(() -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS, ActivationProgress.COMPLETED)); + } } - logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]"); - - try { - communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits)); - } finally { - logCommandExecutionFinished("insertCannula"); - } + communicationService.executeAction(new InsertCannulaAction(podStateManager, basalSchedule, expirationReminderTimeBeforeShutdown, lowReservoirAlertUnits)); long delayInMillis = calculateEstimatedBolusDuration(DateTime.now().minus(OmnipodConstants.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION), OmnipodConstants.POD_CANNULA_INSERTION_BOLUS_UNITS, OmnipodConstants.POD_CANNULA_INSERTION_DELIVERY_RATE).getMillis(); return Single.timer(delayInMillis, TimeUnit.MILLISECONDS) // - .map(o -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS)) // + .map(o -> verifyPodProgressStatus(PodProgressStatus.ABOVE_FIFTY_UNITS, ActivationProgress.COMPLETED)) // .subscribeOn(Schedulers.io()); } @@ -166,49 +143,29 @@ public class OmnipodManager { throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, null); } - logStartingCommandExecution("getPodStatus"); + return communicationService.executeAction(new GetStatusAction(podStateManager)); - try { - return communicationService.executeAction(new GetStatusAction(podStateManager)); - } finally { - logCommandExecutionFinished("getPodStatus"); - } } public synchronized PodInfoResponse getPodInfo(PodInfoType podInfoType) { assertReadyForDelivery(); - logStartingCommandExecution("getPodInfo"); - - try { - return communicationService.executeAction(new GetPodInfoAction(podStateManager, podInfoType)); - } finally { - logCommandExecutionFinished("getPodInfo"); - } + return communicationService.executeAction(new GetPodInfoAction(podStateManager, podInfoType)); } public synchronized StatusResponse configureAlerts(List alertConfigurations) { assertReadyForDelivery(); - logStartingCommandExecution("configureAlerts"); - try { - StatusResponse statusResponse = executeAndVerify(() -> communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations))); - ConfigureAlertsAction.updateConfiguredAlerts(podStateManager, alertConfigurations); - return statusResponse; - } finally { - logCommandExecutionFinished("configureAlerts"); - } + + StatusResponse statusResponse = executeAndVerify(() -> communicationService.executeAction(new ConfigureAlertsAction(podStateManager, alertConfigurations))); + ConfigureAlertsAction.updateConfiguredAlerts(podStateManager, alertConfigurations); + return statusResponse; + } public synchronized StatusResponse acknowledgeAlerts() { assertReadyForDelivery(); - logStartingCommandExecution("acknowledgeAlerts"); - - try { - return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podStateManager, podStateManager.getActiveAlerts()))); - } finally { - logCommandExecutionFinished("acknowledgeAlerts"); - } + return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podStateManager, podStateManager.getActiveAlerts()))); } // CAUTION: cancels all delivery @@ -216,41 +173,33 @@ public class OmnipodManager { public synchronized void setBasalSchedule(BasalSchedule schedule, boolean acknowledgementBeep) { assertReadyForDelivery(); - logStartingCommandExecution("setBasalSchedule [basalSchedule=" + schedule + ", acknowledgementBeep=" + acknowledgementBeep + "]"); + boolean wasSuspended = podStateManager.isSuspended(); + if (!wasSuspended) { + suspendDelivery(acknowledgementBeep); + } try { - boolean wasSuspended = podStateManager.isSuspended(); - if (!wasSuspended) { - suspendDelivery(acknowledgementBeep); + executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, schedule, + false, podStateManager.getScheduleOffset(), acknowledgementBeep))); + podStateManager.setBasalSchedule(schedule); + } catch (OmnipodException ex) { + if (ex.isCertainFailure()) { + if (!wasSuspended) { + throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); + } + throw ex; } - try { - executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, schedule, - false, podStateManager.getScheduleOffset(), acknowledgementBeep))); + // verifyDeliveryStatus will throw an exception if verification fails + if (verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { podStateManager.setBasalSchedule(schedule); - } catch (OmnipodException ex) { - if (ex.isCertainFailure()) { - if (!wasSuspended) { - throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); - } - throw ex; - } - - // verifyDeliveryStatus will throw an exception if verification fails - if (verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { - podStateManager.setBasalSchedule(schedule); - } else { - if (!wasSuspended) { - throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); - } - ex.setCertainFailure(true); - throw ex; + } else { + if (!wasSuspended) { + throw new CommandFailedAfterChangingDeliveryStatusException("Suspending delivery succeeded but setting the new basal schedule did not", ex); } + ex.setCertainFailure(true); + throw ex; } - - - } finally { - logCommandExecutionFinished("setBasalSchedule"); } } @@ -258,70 +207,64 @@ public class OmnipodManager { public synchronized void setTemporaryBasal(double rate, Duration duration, boolean acknowledgementBeep, boolean completionBeep) { assertReadyForDelivery(); - logStartingCommandExecution("setTemporaryBasal [rate=" + rate + ", duration=" + duration + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]"); - boolean cancelCurrentTbr = podStateManager.isTempBasalRunning(); - try { - if (cancelCurrentTbr) { - try { - cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep); - } catch (OmnipodException ex) { - if (ex.isCertainFailure()) { - throw ex; - } - - try { - if (!verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { - ex.setCertainFailure(true); - throw ex; - } - } catch (DeliveryStatusVerificationFailedException ex2) { - podStateManager.setTempBasalCertain(false); - throw ex2; - } - } - } - + if (cancelCurrentTbr) { try { - executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction( - podStateManager, rate, duration, acknowledgementBeep, completionBeep))); - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); + cancelDelivery(EnumSet.of(DeliveryType.TEMP_BASAL), acknowledgementBeep); } catch (OmnipodException ex) { if (ex.isCertainFailure()) { - if (cancelCurrentTbr) { - throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); - } throw ex; } - // verifyDeliveryStatus will throw an exception if verification fails try { - if (verifyDeliveryStatus(DeliveryStatus.TEMP_BASAL_RUNNING, ex)) { - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); - } else { - if (cancelCurrentTbr) { - throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); - } - + if (!verifyDeliveryStatus(DeliveryStatus.NORMAL, ex)) { ex.setCertainFailure(true); throw ex; } - } catch (CommandFailedAfterChangingDeliveryStatusException ex2) { - // Don't set temp basal in Pod State for this Exception - throw ex2; - } catch (OmnipodException ex2) { - if (!ex2.isCertainFailure()) { - // We're not sure that setting the new TBR failed, so we assume that it succeeded - // If it didn't, PodStateManager.updateFromResponse() will fix the state - // upon receiving the next StatusResponse - podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, false); - } + } catch (DeliveryStatusVerificationFailedException ex2) { + podStateManager.setTempBasalCertain(false); throw ex2; } } - } finally { - logCommandExecutionFinished("setTemporaryBasal"); + } + + try { + executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction( + podStateManager, rate, duration, acknowledgementBeep, completionBeep))); + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); + } catch (OmnipodException ex) { + if (ex.isCertainFailure()) { + if (cancelCurrentTbr) { + throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); + } + throw ex; + } + + // verifyDeliveryStatus will throw an exception if verification fails + try { + if (verifyDeliveryStatus(DeliveryStatus.TEMP_BASAL_RUNNING, ex)) { + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, true); + } else { + if (cancelCurrentTbr) { + throw new CommandFailedAfterChangingDeliveryStatusException("Failed to set new TBR while cancelling old TBR succeeded", ex); + } + + ex.setCertainFailure(true); + throw ex; + } + } catch (CommandFailedAfterChangingDeliveryStatusException ex2) { + // Don't set temp basal in Pod State for this Exception + throw ex2; + } catch (OmnipodException ex2) { + if (!ex2.isCertainFailure()) { + // We're not sure that setting the new TBR failed, so we assume that it succeeded + // If it didn't, PodStateManager.updateFromResponse() will fix the state + // upon receiving the next StatusResponse + podStateManager.setTempBasal(DateTime.now().minus(OmnipodConstants.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration, false); + } + throw ex2; + } } } @@ -348,17 +291,11 @@ public class OmnipodManager { private synchronized StatusResponse cancelDelivery(EnumSet deliveryTypes, boolean acknowledgementBeep) { assertReadyForDelivery(); - logStartingCommandExecution("cancelDelivery [deliveryTypes=" + deliveryTypes + ", acknowledgementBeep=" + acknowledgementBeep + "]"); - - try { - return executeAndVerify(() -> { - StatusResponse statusResponse = communicationService.executeAction(new CancelDeliveryAction(podStateManager, deliveryTypes, acknowledgementBeep)); - aapsLogger.info(LTag.PUMPCOMM, "Status response after cancel delivery[types={}]: {}", deliveryTypes.toString(), statusResponse.toString()); - return statusResponse; - }); - } finally { - logCommandExecutionFinished("cancelDelivery"); - } + return executeAndVerify(() -> { + StatusResponse statusResponse = communicationService.executeAction(new CancelDeliveryAction(podStateManager, deliveryTypes, acknowledgementBeep)); + aapsLogger.info(LTag.PUMPCOMM, "Status response after cancel delivery[types={}]: {}", deliveryTypes.toString(), statusResponse.toString()); + return statusResponse; + }); } // Returns a SingleSubject that returns when the bolus has finished. @@ -367,8 +304,6 @@ public class OmnipodManager { public synchronized BolusCommandResult bolus(Double units, boolean acknowledgementBeep, boolean completionBeep, BiConsumer progressIndicationConsumer) { assertReadyForDelivery(); - logStartingCommandExecution("bolus [units=" + units + ", acknowledgementBeep=" + acknowledgementBeep + ", completionBeep=" + completionBeep + "]"); - bolusCommandExecutionSubject = SingleSubject.create(); CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS; @@ -437,7 +372,7 @@ public class OmnipodManager { break; } catch (PodFaultException ex) { // Subtract units not delivered in case of a Pod failure - bolusNotDelivered = ex.getFaultEvent().getBolusNotDelivered(); + bolusNotDelivered = ex.getDetailedStatus().getBolusNotDelivered(); aapsLogger.debug(LTag.PUMPCOMM, "Caught PodFaultException in bolus completion verification", ex); break; @@ -454,8 +389,6 @@ public class OmnipodManager { }) .subscribe()); - logCommandExecutionFinished("bolus"); - return new BolusCommandResult(commandDeliveryStatus, bolusCompletionSubject); } @@ -467,16 +400,12 @@ public class OmnipodManager { throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podStateManager.getLastDeliveryStatus()); } - logStartingCommandExecution("cancelBolus [acknowledgementBeep=" + acknowledgementBeep + "]"); - try { StatusResponse statusResponse = cancelDelivery(EnumSet.of(DeliveryType.BOLUS), acknowledgementBeep); discardActiveBolusData(statusResponse.getBolusNotDelivered()); } catch (PodFaultException ex) { - discardActiveBolusData(ex.getFaultEvent().getBolusNotDelivered()); + discardActiveBolusData(ex.getDetailedStatus().getBolusNotDelivered()); throw ex; - } finally { - logCommandExecutionFinished("cancelBolus"); } } } @@ -494,7 +423,6 @@ public class OmnipodManager { public synchronized void suspendDelivery(boolean acknowledgementBeep) { assertReadyForDelivery(); - logStartingCommandExecution("suspendDelivery"); try { cancelDelivery(EnumSet.allOf(DeliveryType.class), acknowledgementBeep); @@ -508,8 +436,6 @@ public class OmnipodManager { ex.setCertainFailure(true); throw ex; } - } finally { - logCommandExecutionFinished("suspendDelivery"); } } @@ -518,26 +444,20 @@ public class OmnipodManager { public synchronized void setTime(boolean acknowledgementBeeps) { assertReadyForDelivery(); - logStartingCommandExecution("setTime [acknowledgementBeeps=" + acknowledgementBeeps + "]"); + DateTimeZone oldTimeZone = podStateManager.getTimeZone(); try { - DateTimeZone oldTimeZone = podStateManager.getTimeZone(); + // Joda seems to cache the default time zone, so we use the JVM's + DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault())); + podStateManager.setTimeZone(DateTimeZone.getDefault()); - try { - // Joda seems to cache the default time zone, so we use the JVM's - DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault())); - podStateManager.setTimeZone(DateTimeZone.getDefault()); - - setBasalSchedule(podStateManager.getBasalSchedule(), acknowledgementBeeps); - } catch (OmnipodException ex) { - podStateManager.setTimeZone(oldTimeZone); - throw ex; - } - - podStateManager.updateActivatedAt(); - } finally { - logCommandExecutionFinished("setTime"); + setBasalSchedule(podStateManager.getBasalSchedule(), acknowledgementBeeps); + } catch (OmnipodException ex) { + podStateManager.setTimeZone(oldTimeZone); + throw ex; } + + podStateManager.updateActivatedAt(); } public synchronized void deactivatePod() { @@ -545,8 +465,6 @@ public class OmnipodManager { throw new IllegalPodProgressException(PodProgressStatus.REMINDER_INITIALIZED, null); } - logStartingCommandExecution("deactivatePod"); - // Try to get pulse log for diagnostics try { PodInfoResponse podInfoResponse = communicationService.executeAction(new GetPodInfoAction(podStateManager, PodInfoType.RECENT_PULSE_LOG)); @@ -561,8 +479,6 @@ public class OmnipodManager { communicationService.executeAction(new DeactivatePodAction(podStateManager, true)); } catch (PodFaultException ex) { aapsLogger.info(LTag.PUMPCOMM, "Ignoring PodFaultException in deactivatePod", ex); - } finally { - logCommandExecutionFinished("deactivatePod"); } podStateManager.discardState(); @@ -592,7 +508,6 @@ public class OmnipodManager { // Only works for commands with nonce resyncable message blocks private StatusResponse executeAndVerify(Supplier supplier) { - logStartingCommandExecution("verifyCommand"); try { return supplier.get(); } catch (OmnipodException originalException) { @@ -616,8 +531,6 @@ public class OmnipodManager { throw originalException; } } - } finally { - logCommandExecutionFinished("verifyCommand"); } } @@ -632,7 +545,7 @@ public class OmnipodManager { * @return true if the Pod's progress status matches the expected status, otherwise false * @throws PodProgressStatusVerificationFailedException in case reading the Pod status fails */ - private boolean verifyPodProgressStatus(PodProgressStatus expectedPodProgressStatus) { + private boolean verifyPodProgressStatus(PodProgressStatus expectedPodProgressStatus, ActivationProgress activationProgress) { Boolean result = null; Throwable lastException = null; @@ -641,6 +554,7 @@ public class OmnipodManager { StatusResponse statusResponse = getPodStatus(); if (statusResponse.getPodProgressStatus().equals(expectedPodProgressStatus)) { + podStateManager.setActivationProgress(activationProgress); return true; } else { result = false; @@ -681,14 +595,6 @@ public class OmnipodManager { throw new DeliveryStatusVerificationFailedException(expectedStatus, verificationCause); } - private void logStartingCommandExecution(String action) { - aapsLogger.debug(LTag.PUMPCOMM, "Starting command execution for action: " + action); - } - - private void logCommandExecutionFinished(String action) { - aapsLogger.debug(LTag.PUMPCOMM, "Command execution finished for action: " + action); - } - private Duration calculateEstimatedBolusDuration(DateTime startTime, double units, double deliveryRateInUnitsPerSecond) { if (!podStateManager.isPodActivationCompleted()) { // No basal or temp basal is active yet diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java index f7fa1ee694..764467e15e 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/manager/PodStateManager.java @@ -16,16 +16,19 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.function.Supplier; import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSet; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertSlot; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.AlertType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FirmwareVersion; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodCrc; @@ -79,7 +82,7 @@ public abstract class PodStateManager { * @return true if we have a Pod state and the Pod activation has been completed. The pod could also be dead at this point */ public final boolean isPodActivationCompleted() { - return isPodInitialized() && podState.getPodProgressStatus().isAtLeast(PodProgressStatus.ABOVE_FIFTY_UNITS) && podState.getPodProgressStatus() != PodProgressStatus.ACTIVATION_TIME_EXCEEDED; + return getActivationProgress().isCompleted(); } /** @@ -97,6 +100,13 @@ public abstract class PodStateManager { return isPodInitialized() && podState.getPodProgressStatus().equals(PodProgressStatus.FAULT_EVENT_OCCURRED); } + /** + * @return true if the Pod's activation time has been exceeded + */ + public boolean isPodActivationTimeExceeded() { + return isPodInitialized() && getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED; + } + /** * @return true if we have a Pod state and the Pod is dead, meaning it is either in a fault state or activation time has been exceeded or it is deactivated */ @@ -232,16 +242,12 @@ public abstract class PodStateManager { * a fault event, this does NOT necessarily mean that the Pod is not faulted. For a reliable * indication on whether or not the pod is faulted, see {@link #isPodFaulted() isPodFaulted()} */ - public final boolean hasFaultEvent() { - return podState != null && podState.getFaultEvent() != null; + public final boolean isFaulted() { + return podState != null && podState.getFaultEventCode() != null; } - public final PodInfoFaultEvent getFaultEvent() { - return getSafe(() -> podState.getFaultEvent()); - } - - public final void setFaultEvent(PodInfoFaultEvent faultEvent) { - setAndStore(() -> podState.setFaultEvent(faultEvent)); + public final FaultEventCode getFaultEventCode() { + return getSafe(() -> podState.getFaultEventCode()); } public final AlertType getConfiguredAlertType(AlertSlot alertSlot) { @@ -331,6 +337,17 @@ public abstract class PodStateManager { return activatedAt == null ? null : activatedAt.withZone(getSafe(() -> podState.getTimeZone())).plus(OmnipodConstants.NOMINAL_POD_LIFE); } + public final ActivationProgress getActivationProgress() { + if (hasPodState()) { + return Optional.ofNullable(podState.getActivationProgress()).orElse(ActivationProgress.NONE); + } + return ActivationProgress.NONE; + } + + public final void setActivationProgress(ActivationProgress activationProgress) { + setAndStore(() -> podState.setActivationProgress(activationProgress)); + } + public final PodProgressStatus getPodProgressStatus() { return getSafe(() -> podState.getPodProgressStatus()); } @@ -513,20 +530,20 @@ public abstract class PodStateManager { /** * Does not automatically store pod state in order to decrease I/O load */ - public final void updateFromResponse(StatusUpdatableResponse statusResponse) { + public final void updateFromResponse(StatusUpdatableResponse status) { setSafe(() -> { if (podState.getActivatedAt() == null) { - DateTime activatedAtCalculated = DateTime.now().withZone(podState.getTimeZone()).minus(statusResponse.getTimeActive()); + DateTime activatedAtCalculated = DateTime.now().withZone(podState.getTimeZone()).minus(status.getTimeActive()); podState.setActivatedAt(activatedAtCalculated); } - podState.setSuspended(statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED); - podState.setActiveAlerts(statusResponse.getUnacknowledgedAlerts()); - podState.setLastDeliveryStatus(statusResponse.getDeliveryStatus()); - podState.setReservoirLevel(statusResponse.getReservoirLevel()); - podState.setTotalTicksDelivered(statusResponse.getTicksDelivered()); - podState.setPodProgressStatus(statusResponse.getPodProgressStatus()); - podState.setTimeActive(statusResponse.getTimeActive()); - if (statusResponse.getDeliveryStatus().isTbrRunning()) { + podState.setSuspended(status.getDeliveryStatus() == DeliveryStatus.SUSPENDED); + podState.setActiveAlerts(status.getUnacknowledgedAlerts()); + podState.setLastDeliveryStatus(status.getDeliveryStatus()); + podState.setReservoirLevel(status.getReservoirLevel()); + podState.setTotalTicksDelivered(status.getTicksDelivered()); + podState.setPodProgressStatus(status.getPodProgressStatus()); + podState.setTimeActive(status.getTimeActive()); + if (status.getDeliveryStatus().isTbrRunning()) { if (!isTempBasalCertain() && isTempBasalRunning()) { podState.setTempBasalCertain(true); } @@ -535,6 +552,13 @@ public abstract class PodStateManager { setTempBasal(null, null, null, true, false); } podState.setLastUpdatedFromResponse(DateTime.now()); + + if (status instanceof PodInfoDetailedStatus) { + PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) status; + if (detailedStatus.isFaulted()) { + podState.setFaultEventCode(detailedStatus.getFaultEventCode()); + } + } }); } @@ -626,11 +650,12 @@ public abstract class PodStateManager { private DateTimeZone timeZone; private DateTime activatedAt; private Duration timeActive; - private PodInfoFaultEvent faultEvent; + private FaultEventCode faultEventCode; private Double reservoirLevel; private Integer totalTicksDelivered; private boolean suspended; private NonceState nonceState; + private ActivationProgress activationProgress = ActivationProgress.NONE; private PodProgressStatus podProgressStatus; private DeliveryStatus lastDeliveryStatus; private AlertSet activeAlerts; @@ -751,12 +776,12 @@ public abstract class PodStateManager { this.timeActive = timeActive; } - PodInfoFaultEvent getFaultEvent() { - return faultEvent; + FaultEventCode getFaultEventCode() { + return faultEventCode; } - void setFaultEvent(PodInfoFaultEvent faultEvent) { - this.faultEvent = faultEvent; + void setFaultEventCode(FaultEventCode faultEventCode) { + this.faultEventCode = faultEventCode; } Double getReservoirLevel() { @@ -799,6 +824,14 @@ public abstract class PodStateManager { this.nonceState = nonceState; } + ActivationProgress getActivationProgress() { + return activationProgress; + } + + void setActivationProgress(ActivationProgress activationProgress) { + this.activationProgress = activationProgress; + } + PodProgressStatus getPodProgressStatus() { return podProgressStatus; } @@ -930,11 +963,12 @@ public abstract class PodStateManager { ", timeZone=" + timeZone + ", activatedAt=" + activatedAt + ", timeActive=" + timeActive + - ", faultEvent=" + faultEvent + + ", faultEventCode=" + faultEventCode + ", reservoirLevel=" + reservoirLevel + ", totalTicksDelivered=" + totalTicksDelivered + ", suspended=" + suspended + ", nonceState=" + nonceState + + ", activationProgress=" + activationProgress + ", podProgressStatus=" + podProgressStatus + ", lastDeliveryStatus=" + lastDeliveryStatus + ", activeAlerts=" + activeAlerts + diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java index cddf3b2692..9a2956792d 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/manager/AapsOmnipodManager.java @@ -50,9 +50,9 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.Deliver import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalSchedule; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.schedule.BasalScheduleEntry; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActivationTimeExceededException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CommandFailedAfterChangingDeliveryStatusException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.CrcMismatchException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.DeliveryStatusVerificationFailedException; @@ -62,6 +62,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalM import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPodProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalResponseException; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalActivationProgressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalVersionResponseTypeException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.MessageDecodingException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.NonceOutOfSyncException; @@ -481,7 +482,10 @@ public class AapsOmnipodManager { addTempBasalTreatment(System.currentTimeMillis(), pumpId, tempBasalPair); - return new PumpEnactResult(injector).success(true).enacted(true); + return new PumpEnactResult(injector) + .duration(tempBasalPair.getDurationMinutes()) + .absolute(PumpType.Insulet_Omnipod.determineCorrectBasalSize(tempBasalPair.getInsulinRate())) + .success(true).enacted(true); } public PumpEnactResult cancelTemporaryBasal() { @@ -755,10 +759,8 @@ public class AapsOmnipodManager { if (ex instanceof OmnipodException) { aapsLogger.error(LTag.PUMP, String.format("Caught OmnipodException[certainFailure=%s] from OmnipodManager", ((OmnipodException) ex).isCertainFailure()), ex); if (ex instanceof PodFaultException) { - FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode(); - if (!(faultEventCode == FaultEventCode.NO_FAULTS && podStateManager.isPodInitialized() && podStateManager.getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED)) { - showPodFaultNotification(faultEventCode); - } + FaultEventCode faultEventCode = ((PodFaultException) ex).getDetailedStatus().getFaultEventCode(); + showPodFaultNotification(faultEventCode); } } else { aapsLogger.error(LTag.PUMP, "Caught an unexpected non-OmnipodException from OmnipodManager", ex); @@ -772,7 +774,8 @@ public class AapsOmnipodManager { comment = getStringResource(R.string.omnipod_error_crc_mismatch); } else if (ex instanceof IllegalPacketTypeException) { comment = getStringResource(R.string.omnipod_error_invalid_packet_type); - } else if (ex instanceof IllegalPodProgressException || ex instanceof IllegalDeliveryStatusException) { + } else if (ex instanceof IllegalPodProgressException || ex instanceof IllegalActivationProgressException || + ex instanceof IllegalDeliveryStatusException) { comment = getStringResource(R.string.omnipod_error_invalid_progress_state); } else if (ex instanceof IllegalVersionResponseTypeException) { comment = getStringResource(R.string.omnipod_error_invalid_response); @@ -791,8 +794,10 @@ public class AapsOmnipodManager { } else if (ex instanceof NotEnoughDataException) { comment = getStringResource(R.string.omnipod_error_not_enough_data); } else if (ex instanceof PodFaultException) { - FaultEventCode faultEventCode = ((PodFaultException) ex).getFaultEvent().getFaultEventCode(); + FaultEventCode faultEventCode = ((PodFaultException) ex).getDetailedStatus().getFaultEventCode(); comment = createPodFaultErrorMessage(faultEventCode); + } else if (ex instanceof ActivationTimeExceededException) { + comment = getStringResource(R.string.omnipod_error_pod_fault_activation_time_exceeded); } else if (ex instanceof PodReturnedErrorResponseException) { comment = getStringResource(R.string.omnipod_error_pod_returned_error_response); } else if (ex instanceof RileyLinkUnreachableException) { @@ -813,9 +818,6 @@ public class AapsOmnipodManager { } private String createPodFaultErrorMessage(FaultEventCode faultEventCode) { - if (faultEventCode == FaultEventCode.NO_FAULTS && podStateManager.getPodProgressStatus() == PodProgressStatus.ACTIVATION_TIME_EXCEEDED) { - return getStringResource(R.string.omnipod_error_pod_fault_activation_time_exceeded); - } return getStringResource(R.string.omnipod_error_pod_fault, ByteUtil.convertUnsignedByteToInt(faultEventCode.getValue()), faultEventCode.name()); } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/rileylink/manager/OmnipodRileyLinkCommunicationManager.java b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/rileylink/manager/OmnipodRileyLinkCommunicationManager.java index adb9e97e69..822228d949 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/rileylink/manager/OmnipodRileyLinkCommunicationManager.java +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/rileylink/manager/OmnipodRileyLinkCommunicationManager.java @@ -23,12 +23,13 @@ import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.mess import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.ErrorResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.StatusUpdatableResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfo; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoFaultEvent; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoDetailedStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo.PodInfoResponse; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.MessageBlockType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.ActivationTimeExceededException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageAddressException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalMessageSequenceNumberException; import info.nightscout.androidaps.plugins.pump.omnipod.driver.exception.IllegalPacketTypeException; @@ -156,12 +157,21 @@ public class OmnipodRileyLinkCommunicationManager extends RileyLinkCommunication podStateManager.setLastFailedCommunication(DateTime.now()); throw new PodReturnedErrorResponseException(error); } - } else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) { - PodInfoFaultEvent faultEvent = (PodInfoFaultEvent) ((PodInfoResponse) responseMessageBlock).getPodInfo(); - podStateManager.setFaultEvent(faultEvent); - // Treat as successful communication as the user will get notified and can work with this response - podStateManager.setLastSuccessfulCommunication(DateTime.now()); - throw new PodFaultException(faultEvent); + } else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.DETAILED_STATUS) { + PodInfoDetailedStatus detailedStatus = (PodInfoDetailedStatus) ((PodInfoResponse) responseMessageBlock).getPodInfo(); + if (detailedStatus.isFaulted()) { + // Treat as successful communication in order to prevent false positive pump unreachable alarms + podStateManager.setLastSuccessfulCommunication(DateTime.now()); + throw new PodFaultException(detailedStatus); + } else if (detailedStatus.isActivationTimeExceeded()) { + // Treat as successful communication in order to prevent false positive pump unreachable alarms + podStateManager.setLastSuccessfulCommunication(DateTime.now()); + throw new ActivationTimeExceededException(); + } else { + // Shouldn't happen + podStateManager.setLastFailedCommunication(DateTime.now()); + throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType()); + } } else { podStateManager.setLastFailedCommunication(DateTime.now()); throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType()); @@ -174,6 +184,7 @@ public class OmnipodRileyLinkCommunicationManager extends RileyLinkCommunication } finally { podStateManager.storePodState(); } + } private MessageBlock transportMessages(PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt index 055e7550d2..de8f029bff 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/OmnipodOverviewFragment.kt @@ -23,6 +23,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyL 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.R +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.OmnipodConstants import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager @@ -272,8 +273,8 @@ class OmnipodOverviewFragment : DaggerFragment() { }) } - if (podStateManager.hasFaultEvent()) { - val faultEventCode = podStateManager.faultEvent.faultEventCode + if (podStateManager.isFaulted) { + val faultEventCode = podStateManager.faultEventCode errors.add(resourceHelper.gs(R.string.omnipod_pod_status_pod_fault_description, faultEventCode.value, faultEventCode.name)) } @@ -345,9 +346,7 @@ class OmnipodOverviewFragment : DaggerFragment() { if (!podStateManager.isPodInitialized) { resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation) } else { - if (PodProgressStatus.ACTIVATION_TIME_EXCEEDED == podStateManager.podProgressStatus) { - resourceHelper.gs(R.string.omnipod_pod_status_activation_time_exceeded) - } else if (podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) { + if (podStateManager.activationProgress.isBefore(ActivationProgress.PRIMING_COMPLETED)) { resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_activation) } else { resourceHelper.gs(R.string.omnipod_pod_status_waiting_for_cannula_insertion) @@ -454,7 +453,7 @@ class OmnipodOverviewFragment : DaggerFragment() { } private fun updateRefreshStatusButton() { - omnipod_overview_button_refresh_status.isEnabled = podStateManager.isPodInitialized && podStateManager.podProgressStatus.isAtLeast(PodProgressStatus.PAIRING_COMPLETED) + omnipod_overview_button_refresh_status.isEnabled = podStateManager.isPodInitialized && podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED) && rileyLinkServiceData.rileyLinkServiceState.isReady && isQueueEmpty() } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt index 03ee8035ae..fa1de1ef5c 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/PodManagementActivity.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.pump.common.events.EventRileyLinkDeviceStatusChange import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData import info.nightscout.androidaps.plugins.pump.omnipod.R +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.event.EventOmnipodPumpValuesChanged import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManager @@ -94,7 +95,7 @@ class PodManagementActivity : NoSplashAppCompatActivity() { if (rileyLinkServiceData.rileyLinkServiceState.isReady) { omnipod_pod_management_button_activate_pod.isEnabled = !podStateManager.isPodActivationCompleted - omnipod_pod_management_button_deactivate_pod.isEnabled = podStateManager.isPodInitialized + omnipod_pod_management_button_deactivate_pod.isEnabled = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED) if (discardButtonEnabled) { omnipod_pod_management_button_discard_pod.isEnabled = true } diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt index 183c3c239c..eccc00eb94 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/PodActivationWizardActivity.kt @@ -3,7 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.activation import android.os.Bundle import androidx.annotation.IdRes import info.nightscout.androidaps.plugins.pump.omnipod.R -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.common.activity.OmnipodWizardActivityBase import javax.inject.Inject @@ -25,7 +25,7 @@ class PodActivationWizardActivity : OmnipodWizardActivityBase() { setContentView(R.layout.omnipod_pod_activation_wizard_activity) startDestination = savedInstanceState?.getInt(KEY_START_DESTINATION, R.id.fillPodInfoFragment) - ?: if (!podStateManager.isPodInitialized || podStateManager.podProgressStatus.isBefore(PodProgressStatus.PRIMING_COMPLETED)) { + ?: if (podStateManager.activationProgress.isBefore(ActivationProgress.PRIMING_COMPLETED)) { R.id.fillPodInfoFragment } else { R.id.attachPodInfoFragment diff --git a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt index 2055d895e0..54df2de98e 100644 --- a/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt +++ b/omnipod/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/ui/wizard/activation/fragment/PodActivationActionFragmentBase.kt @@ -3,8 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.activation.fra import android.content.Intent import android.os.Bundle import android.view.View -import info.nightscout.androidaps.plugins.pump.omnipod.R -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ActivationProgress import info.nightscout.androidaps.plugins.pump.omnipod.driver.manager.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.common.fragment.ActionFragmentBase import info.nightscout.androidaps.plugins.pump.omnipod.ui.wizard.deactivation.PodDeactivationWizardActivity @@ -27,8 +26,7 @@ abstract class PodActivationActionFragmentBase : ActionFragmentBase() { } override fun onActionFailure() { - if (podStateManager.isPodInitialized && podStateManager.podProgressStatus == PodProgressStatus.ACTIVATION_TIME_EXCEEDED) { - omnipod_wizard_action_error.setText(R.string.omnipod_error_pod_fault_activation_time_exceeded) + if (podStateManager.isPodActivationTimeExceeded && podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED)) { omnipod_wizard_button_retry.visibility = View.GONE omnipod_wizard_button_deactivate_pod.visibility = View.VISIBLE } diff --git a/omnipod/src/main/res/values/strings.xml b/omnipod/src/main/res/values/strings.xml index 62ab50b16c..7be906aae4 100644 --- a/omnipod/src/main/res/values/strings.xml +++ b/omnipod/src/main/res/values/strings.xml @@ -93,7 +93,7 @@ Communication failed: nonce resync failed Communication failed: nonce out of sync Communication failed: not enough data received from the Pod - A Pod fault (%1$03d %2$s) has been detected. Please deactivate your Pod and start a new one + A Pod fault (%1$03d %2$s) has been detected. Please deactivate your Pod and activate a new one Communication failed: the Pod returned an error response No response from RileyLink RileyLink interrupted diff --git a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPluginTest.java b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPluginTest.java new file mode 100644 index 0000000000..64f7f48728 --- /dev/null +++ b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPluginTest.java @@ -0,0 +1,142 @@ +package info.nightscout.androidaps.plugins.pump.omnipod; + +import android.os.Looper; + +import org.joda.time.DateTimeZone; +import org.joda.time.tz.UTCProvider; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Answers; +import org.mockito.Mock; +import org.powermock.api.mockito.PowerMockito; +import org.powermock.core.classloader.annotations.PrepareForTest; +import org.powermock.modules.junit4.PowerMockRunner; + +import java.util.ArrayList; + +import dagger.android.AndroidInjector; +import dagger.android.HasAndroidInjector; +import info.nightscout.androidaps.data.Profile; +import info.nightscout.androidaps.data.PumpEnactResult; +import info.nightscout.androidaps.interfaces.ActivePluginProvider; +import info.nightscout.androidaps.interfaces.CommandQueueProvider; +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.AAPSLoggerTest; +import info.nightscout.androidaps.plugins.bus.RxBusWrapper; +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.RileyLinkUtil; +import info.nightscout.androidaps.plugins.pump.omnipod.manager.AapsOmnipodManager; +import info.nightscout.androidaps.utils.resources.ResourceHelper; + +import static org.junit.Assert.assertEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + + +@RunWith(PowerMockRunner.class) +public class OmnipodPumpPluginTest { + + @Mock HasAndroidInjector injector; + AAPSLogger aapsLogger = new AAPSLoggerTest(); + RxBusWrapper rxBusWrapper = new RxBusWrapper(); + @Mock ResourceHelper resourceHelper; + @Mock(answer = Answers.RETURNS_DEEP_STUBS) ActivePluginProvider activePluginProvider; + @Mock AapsOmnipodManager aapsOmnipodManager; + @Mock CommandQueueProvider commandQueueProvider; + @Mock RileyLinkUtil rileyLinkUtil; + + + @Test + @PrepareForTest(Looper.class) + public void testSetTempBasalPercent() { + + DateTimeZone.setProvider(new UTCProvider()); + + // mock all the things + PowerMockito.mockStatic(Looper.class); + OmnipodPumpPlugin plugin = new OmnipodPumpPlugin(injector, aapsLogger, rxBusWrapper, null, + resourceHelper, activePluginProvider, null, null, aapsOmnipodManager, commandQueueProvider, + null, null, null, null, null, + rileyLinkUtil, null, null + ); + when(activePluginProvider.getActiveTreatments().getTempBasalFromHistory(anyLong())).thenReturn(null); + when(rileyLinkUtil.getRileyLinkHistory()).thenReturn(new ArrayList<>()); + when(injector.androidInjector()).thenReturn(new AndroidInjector() { + @Override public void inject(Object instance) { + } + }); + Profile profile = mock(Profile.class); + + + // always return a PumpEnactResult containing same rate and duration as input + when(aapsOmnipodManager.setTemporaryBasal(any(TempBasalPair.class))).thenAnswer( + invocation -> { + TempBasalPair pair = invocation.getArgument(0); + PumpEnactResult result = new PumpEnactResult(injector); + result.absolute(pair.getInsulinRate()); + result.duration(pair.getDurationMinutes()); + return result; + }); + + + // Given standard basal + when(profile.getBasal()).thenReturn(0.5d); + // When + PumpEnactResult result1 = plugin.setTempBasalPercent(80, 30, profile, false); + PumpEnactResult result2 = plugin.setTempBasalPercent(5000, 30000, profile, false); + PumpEnactResult result3 = plugin.setTempBasalPercent(0, 30, profile, false); + PumpEnactResult result4 = plugin.setTempBasalPercent(0, 0, profile, false); + PumpEnactResult result5 = plugin.setTempBasalPercent(-50, -1, profile, false); + // Then return correct values + assertEquals(result1.absolute, 0.4d, 0.01d); + assertEquals(result1.duration, 30); + assertEquals(result2.absolute, 25d, 0.01d); + assertEquals(result2.duration, 30000); + assertEquals(result3.absolute, 0d, 0.01d); + assertEquals(result3.duration, 30); + assertEquals(result4.absolute, 0d, 0.01d); + assertEquals(result4.duration, 0); + // this is validated downstream, see TempBasalExtraCommand + assertEquals(result5.absolute, -0.25d, 0.01d); + assertEquals(result5.duration, -1); + + // Given zero basal + when(profile.getBasal()).thenReturn(0d); + // When + result1 = plugin.setTempBasalPercent(8000, 10, profile, false); + result2 = plugin.setTempBasalPercent(0, 00, profile, false); + // Then return zero values + assertEquals(result1.absolute, 0d, 0.01d); + assertEquals(result1.duration, 10); + assertEquals(result2.absolute, 0d, 0.01d); + assertEquals(result2.duration, 0); + + // Given unhealthy basal + when(profile.getBasal()).thenReturn(500d); + // When treatment + result1 = plugin.setTempBasalPercent(80, 30, profile, false); + // Then return sane values + assertEquals(result1.absolute, PumpType.Insulet_Omnipod.determineCorrectBasalSize(500d * 0.8), 0.01d); + assertEquals(result1.duration, 30); + + // Given weird basal + when(profile.getBasal()).thenReturn(1.234567d); + // When treatment + result1 = plugin.setTempBasalPercent(280, 500, profile, false); + // Then return sane values + assertEquals(result1.absolute, 3.4567876, 0.01d); + assertEquals(result1.duration, 500); + + // Given negative basal + when(profile.getBasal()).thenReturn(-1.234567d); + // When treatment + result1 = plugin.setTempBasalPercent(280, 500, profile, false); + // Then return negative value (this is validated further downstream, see TempBasalExtraCommand) + assertEquals(result1.absolute, -3.4567876, 0.01d); + assertEquals(result1.duration, 500); + } + +} diff --git a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/GetStatusCommandTest.java b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/GetStatusCommandTest.java index aa7d168a7c..65d8e9d7c2 100644 --- a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/GetStatusCommandTest.java +++ b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/command/GetStatusCommandTest.java @@ -24,7 +24,7 @@ public class GetStatusCommandTest { @Test public void testPodInfoTypeFaultEvents() { - GetStatusCommand getStatusCommand = new GetStatusCommand(PodInfoType.FAULT_EVENT); + GetStatusCommand getStatusCommand = new GetStatusCommand(PodInfoType.DETAILED_STATUS); assertArrayEquals(ByteUtil.fromHexString("0e0102"), getStatusCommand.getRawData()); } diff --git a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoDetailedStatusTest.java b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoDetailedStatusTest.java new file mode 100644 index 0000000000..1b3d5ed816 --- /dev/null +++ b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoDetailedStatusTest.java @@ -0,0 +1,162 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo; + +import org.joda.time.Duration; +import org.junit.Test; + +import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.ErrorEventInfo; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +// From https://github.com/ps2/rileylink_ios/blob/omnipod-testing/OmniKitTests/PodInfoTests.swift +public class PodInfoDetailedStatusTest { + @Test + public void testPodInfoFaultEventNoFaultAlerts() { + PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("02080100000a003800000003ff008700000095ff0000")); + + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPodProgressStatus()); + assertEquals(DeliveryStatus.NORMAL, podInfoDetailedStatus.getDeliveryStatus()); + assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); + assertEquals(0x0a, podInfoDetailedStatus.getPodMessageCounter()); + assertNull(podInfoDetailedStatus.getFaultEventCode()); + assertTrue(Duration.ZERO.isEqual(podInfoDetailedStatus.getFaultEventTime())); + assertNull(podInfoDetailedStatus.getReservoirLevel()); + assertTrue(Duration.standardSeconds(8100).isEqual(podInfoDetailedStatus.getTimeActive())); + assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue()); + assertFalse(podInfoDetailedStatus.isFaultAccessingTables()); + ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo(); + assertNull(errorEventInfo); + assertNull(podInfoDetailedStatus.getPreviousPodProgressStatus()); + assertEquals(2, podInfoDetailedStatus.getReceiverLowGain()); + assertEquals(21, podInfoDetailedStatus.getRadioRSSI()); + } + + @Test + public void testPodInfoFaultEventDeliveryErrorDuringPriming() { + PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020f0000000900345c000103ff0001000005ae056029")); + + assertEquals(PodProgressStatus.INACTIVE, podInfoDetailedStatus.getPodProgressStatus()); + assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus()); + assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); + assertEquals(0x09, podInfoDetailedStatus.getPodMessageCounter()); + assertEquals(FaultEventCode.PRIME_OPEN_COUNT_TOO_LOW, podInfoDetailedStatus.getFaultEventCode()); + assertTrue(Duration.standardSeconds(60).isEqual(podInfoDetailedStatus.getFaultEventTime())); + assertNull(podInfoDetailedStatus.getReservoirLevel()); + assertTrue(Duration.standardSeconds(60).isEqual(podInfoDetailedStatus.getTimeActive())); + assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue()); + assertFalse(podInfoDetailedStatus.isFaultAccessingTables()); + ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo(); + assertFalse(errorEventInfo.isInsulinStateTableCorruption()); + assertEquals(0x00, errorEventInfo.getInternalVariable()); + assertFalse(errorEventInfo.isImmediateBolusInProgress()); + assertEquals(PodProgressStatus.PRIMING_COMPLETED, errorEventInfo.getPodProgressStatus()); + assertEquals(PodProgressStatus.PRIMING_COMPLETED, podInfoDetailedStatus.getPreviousPodProgressStatus()); + assertEquals(2, podInfoDetailedStatus.getReceiverLowGain()); + assertEquals(46, podInfoDetailedStatus.getRadioRSSI()); + } + + @Test + public void testPodInfoFaultEventErrorShuttingDown() { + PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020d0000000407f28609ff03ff0a0200000823080000")); + + assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoDetailedStatus.getPodProgressStatus()); + assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus()); + assertEquals(2034, podInfoDetailedStatus.getTicksDelivered()); + assertEquals(101.7, podInfoDetailedStatus.getInsulinDelivered(), 0.000001); + assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); + assertEquals(0x04, podInfoDetailedStatus.getPodMessageCounter()); + assertEquals(FaultEventCode.BASAL_OVER_INFUSION_PULSE, podInfoDetailedStatus.getFaultEventCode()); + assertTrue(Duration.standardMinutes(2559).isEqual(podInfoDetailedStatus.getFaultEventTime())); + assertNull(podInfoDetailedStatus.getReservoirLevel()); + assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue()); + assertFalse(podInfoDetailedStatus.isFaultAccessingTables()); + ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo(); + assertFalse(errorEventInfo.isInsulinStateTableCorruption()); + assertEquals(0x00, errorEventInfo.getInternalVariable()); + assertFalse(errorEventInfo.isImmediateBolusInProgress()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorEventInfo.getPodProgressStatus()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPreviousPodProgressStatus()); + assertEquals(0, podInfoDetailedStatus.getReceiverLowGain()); + assertEquals(35, podInfoDetailedStatus.getRadioRSSI()); + } + + @Test + public void testPodInfoFaultEventInsulinNotDelivered() { + PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020f0000010200ec6a026803ff026b000028a7082023")); + + assertEquals(PodProgressStatus.INACTIVE, podInfoDetailedStatus.getPodProgressStatus()); + assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus()); + assertEquals(236, podInfoDetailedStatus.getTicksDelivered()); + assertEquals(11.8, podInfoDetailedStatus.getInsulinDelivered(), 0.000001); + assertEquals(0.05, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); + assertEquals(0x02, podInfoDetailedStatus.getPodMessageCounter()); + assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoDetailedStatus.getFaultEventCode()); + assertTrue(Duration.standardMinutes(616).isEqual(podInfoDetailedStatus.getFaultEventTime())); + assertNull(podInfoDetailedStatus.getReservoirLevel()); + assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue()); + assertFalse(podInfoDetailedStatus.isFaultAccessingTables()); + ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo(); + assertFalse(errorEventInfo.isInsulinStateTableCorruption()); + assertEquals(0x01, errorEventInfo.getInternalVariable()); + assertFalse(errorEventInfo.isImmediateBolusInProgress()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorEventInfo.getPodProgressStatus()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPreviousPodProgressStatus()); + assertEquals(2, podInfoDetailedStatus.getReceiverLowGain()); + assertEquals(39, podInfoDetailedStatus.getRadioRSSI()); + } + + @Test + public void testPodInfoFaultEventMaxBolusNotDelivered() { + PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020f00ffff0200ec6a026803ff026b000028a7082023")); + + assertEquals(PodProgressStatus.INACTIVE, podInfoDetailedStatus.getPodProgressStatus()); + assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus()); + assertEquals(236, podInfoDetailedStatus.getTicksDelivered()); + assertEquals(11.8, podInfoDetailedStatus.getInsulinDelivered(), 0.000001); + assertEquals(3276.75, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); // Insane and will not happen, but this verifies that we convert it to an unsigned int + assertEquals(0x02, podInfoDetailedStatus.getPodMessageCounter()); + assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoDetailedStatus.getFaultEventCode()); + assertTrue(Duration.standardMinutes(616).isEqual(podInfoDetailedStatus.getFaultEventTime())); + assertNull(podInfoDetailedStatus.getReservoirLevel()); + assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue()); + assertFalse(podInfoDetailedStatus.isFaultAccessingTables()); + ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo(); + assertFalse(errorEventInfo.isInsulinStateTableCorruption()); + assertEquals(0x01, errorEventInfo.getInternalVariable()); + assertFalse(errorEventInfo.isImmediateBolusInProgress()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, errorEventInfo.getPodProgressStatus()); + assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoDetailedStatus.getPreviousPodProgressStatus()); + assertEquals(2, podInfoDetailedStatus.getReceiverLowGain()); + assertEquals(39, podInfoDetailedStatus.getRadioRSSI()); + } + + @Test + public void testPodInfoFaultEventInsulinStateTableCorruptionFoundDuringErrorLogging() { + PodInfoDetailedStatus podInfoDetailedStatus = new PodInfoDetailedStatus(ByteUtil.fromHexString("020D00000000000012FFFF03FF00160000879A070000")); + + assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoDetailedStatus.getPodProgressStatus()); + assertEquals(DeliveryStatus.SUSPENDED, podInfoDetailedStatus.getDeliveryStatus()); + assertEquals(0, podInfoDetailedStatus.getBolusNotDelivered(), 0.000001); + assertEquals(0x00, podInfoDetailedStatus.getPodMessageCounter()); + assertEquals(FaultEventCode.RESET_DUE_TO_LVD, podInfoDetailedStatus.getFaultEventCode()); + assertTrue(Duration.ZERO.isEqual(podInfoDetailedStatus.getFaultEventTime())); + assertNull(podInfoDetailedStatus.getReservoirLevel()); + assertTrue(Duration.standardSeconds(1320).isEqual(podInfoDetailedStatus.getTimeActive())); + assertEquals(0, podInfoDetailedStatus.getUnacknowledgedAlerts().getRawValue()); + assertFalse(podInfoDetailedStatus.isFaultAccessingTables()); + ErrorEventInfo errorEventInfo = podInfoDetailedStatus.getErrorEventInfo(); + assertTrue(errorEventInfo.isInsulinStateTableCorruption()); + assertEquals(0x00, errorEventInfo.getInternalVariable()); + assertFalse(errorEventInfo.isImmediateBolusInProgress()); + assertEquals(PodProgressStatus.INSERTING_CANNULA, errorEventInfo.getPodProgressStatus()); + assertEquals(PodProgressStatus.INSERTING_CANNULA, podInfoDetailedStatus.getPreviousPodProgressStatus()); + assertEquals(2, podInfoDetailedStatus.getReceiverLowGain()); + assertEquals(26, podInfoDetailedStatus.getRadioRSSI()); + } +} diff --git a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoFaultEventTest.java b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoFaultEventTest.java deleted file mode 100644 index 5731123724..0000000000 --- a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoFaultEventTest.java +++ /dev/null @@ -1,121 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.driver.communication.message.response.podinfo; - -import org.joda.time.Duration; -import org.junit.Test; - -import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.DeliveryStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.FaultEventCode; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.LogEventErrorCode; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodProgressStatus; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; - -// From https://github.com/ps2/rileylink_ios/blob/omnipod-testing/OmniKitTests/PodInfoTests.swift -public class PodInfoFaultEventTest { - @Test - public void testPodInfoFaultEventNoFaultAlerts() { - PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("02080100000a003800000003ff008700000095ff0000")); - - assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatus()); - assertEquals(DeliveryStatus.NORMAL, podInfoFaultEvent.getDeliveryStatus()); - assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001); - assertEquals(0x0a, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventCode.NO_FAULTS, podInfoFaultEvent.getFaultEventCode()); - assertTrue(Duration.ZERO.isEqual(podInfoFaultEvent.getFaultEventTime())); - assertNull(podInfoFaultEvent.getReservoirLevel()); - assertTrue(Duration.standardSeconds(8100).isEqual(podInfoFaultEvent.getTimeActive())); - assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); - assertFalse(podInfoFaultEvent.isFaultAccessingTables()); - assertEquals(LogEventErrorCode.NONE, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); - assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); - assertEquals(21, podInfoFaultEvent.getRadioRSSI()); - } - - @Test - public void testPodInfoFaultEventDeliveryErrorDuringPriming() { - PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020f0000000900345c000103ff0001000005ae056029")); - - assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatus()); - assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus()); - assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001); - assertEquals(0x09, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventCode.PRIME_OPEN_COUNT_TOO_LOW, podInfoFaultEvent.getFaultEventCode()); - assertTrue(Duration.standardSeconds(60).isEqual(podInfoFaultEvent.getFaultEventTime())); - assertNull(podInfoFaultEvent.getReservoirLevel()); - assertTrue(Duration.standardSeconds(60).isEqual(podInfoFaultEvent.getTimeActive())); - assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); - assertFalse(podInfoFaultEvent.isFaultAccessingTables()); - assertEquals(LogEventErrorCode.NONE, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.PRIMING_COMPLETED, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); - assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); - assertEquals(46, podInfoFaultEvent.getRadioRSSI()); - } - - @Test - public void testPodInfoFaultEventErrorShuttingDown() { - PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020d0000000407f28609ff03ff0a0200000823080000")); - - assertEquals(PodProgressStatus.FAULT_EVENT_OCCURRED, podInfoFaultEvent.getPodProgressStatus()); - assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus()); - assertEquals(2034, podInfoFaultEvent.getTicksDelivered()); - assertEquals(101.7, podInfoFaultEvent.getInsulinDelivered(), 0.000001); - assertEquals(0, podInfoFaultEvent.getBolusNotDelivered(), 0.000001); - assertEquals(0x04, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventCode.BASAL_OVER_INFUSION_PULSE, podInfoFaultEvent.getFaultEventCode()); - assertTrue(Duration.standardMinutes(2559).isEqual(podInfoFaultEvent.getFaultEventTime())); - assertNull(podInfoFaultEvent.getReservoirLevel()); - assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); - assertFalse(podInfoFaultEvent.isFaultAccessingTables()); - assertEquals(LogEventErrorCode.NONE, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); - assertEquals(0, podInfoFaultEvent.getReceiverLowGain()); - assertEquals(35, podInfoFaultEvent.getRadioRSSI()); - } - - @Test - public void testPodInfoFaultEventInsulinNotDelivered() { - PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020f0000010200ec6a026803ff026b000028a7082023")); - - assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatus()); - assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus()); - assertEquals(236, podInfoFaultEvent.getTicksDelivered()); - assertEquals(11.8, podInfoFaultEvent.getInsulinDelivered(), 0.000001); - assertEquals(0.05, podInfoFaultEvent.getBolusNotDelivered(), 0.000001); - assertEquals(0x02, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventCode()); - assertTrue(Duration.standardMinutes(616).isEqual(podInfoFaultEvent.getFaultEventTime())); - assertNull(podInfoFaultEvent.getReservoirLevel()); - assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); - assertFalse(podInfoFaultEvent.isFaultAccessingTables()); - assertEquals(LogEventErrorCode.INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_2, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); - assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); - assertEquals(39, podInfoFaultEvent.getRadioRSSI()); - } - - @Test - public void testPodInfoFaultEventMaxBolusNotDelivered() { - PodInfoFaultEvent podInfoFaultEvent = new PodInfoFaultEvent(ByteUtil.fromHexString("020f00ffff0200ec6a026803ff026b000028a7082023")); - - assertEquals(PodProgressStatus.INACTIVE, podInfoFaultEvent.getPodProgressStatus()); - assertEquals(DeliveryStatus.SUSPENDED, podInfoFaultEvent.getDeliveryStatus()); - assertEquals(236, podInfoFaultEvent.getTicksDelivered()); - assertEquals(11.8, podInfoFaultEvent.getInsulinDelivered(), 0.000001); - assertEquals(3276.75, podInfoFaultEvent.getBolusNotDelivered(), 0.000001); // Insane and will not happen, but this verifies that we convert it to an unsigned int - assertEquals(0x02, podInfoFaultEvent.getPodMessageCounter()); - assertEquals(FaultEventCode.OCCLUSION_CHECK_ABOVE_THRESHOLD, podInfoFaultEvent.getFaultEventCode()); - assertTrue(Duration.standardMinutes(616).isEqual(podInfoFaultEvent.getFaultEventTime())); - assertNull(podInfoFaultEvent.getReservoirLevel()); - assertEquals(0, podInfoFaultEvent.getUnacknowledgedAlerts().getRawValue()); - assertFalse(podInfoFaultEvent.isFaultAccessingTables()); - assertEquals(LogEventErrorCode.INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_2, podInfoFaultEvent.getLogEventErrorType()); - assertEquals(PodProgressStatus.ABOVE_FIFTY_UNITS, podInfoFaultEvent.getPodProgressStatusAtTimeOfFirstLoggedFaultEvent()); - assertEquals(2, podInfoFaultEvent.getReceiverLowGain()); - assertEquals(39, podInfoFaultEvent.getRadioRSSI()); - } -} diff --git a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoResponseTest.java b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoResponseTest.java index 821143ecd4..99d05b7d03 100644 --- a/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoResponseTest.java +++ b/omnipod/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/communication/message/response/podinfo/PodInfoResponseTest.java @@ -5,7 +5,6 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; -import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.LogEventErrorCode; import info.nightscout.androidaps.plugins.pump.omnipod.driver.definition.PodInfoType; import static org.junit.Assert.assertArrayEquals; @@ -39,18 +38,18 @@ public class PodInfoResponseTest { public void testMessageDecoding() { PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d")); - assertEquals(PodInfoType.FAULT_EVENT, podInfoResponse.getSubType()); + assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType()); - PodInfoFaultEvent podInfo = (PodInfoFaultEvent) podInfoResponse.getPodInfo(); + PodInfoDetailedStatus podInfo = (PodInfoDetailedStatus) podInfoResponse.getPodInfo(); assertFalse(podInfo.isFaultAccessingTables()); - assertEquals(LogEventErrorCode.INTERNAL_2_BIT_VARIABLE_SET_AND_MANIPULATED_IN_MAIN_LOOP_ROUTINES_2, podInfo.getLogEventErrorType()); + assertEquals(0x01, podInfo.getErrorEventInfo().getInternalVariable()); } @Test public void testInvalidPodInfoTypeMessageDecoding() { PodInfoResponse podInfoResponse = new PodInfoResponse(ByteUtil.fromHexString("0216020d0000000000ab6a038403ff03860000285708030d")); - assertEquals(PodInfoType.FAULT_EVENT, podInfoResponse.getSubType()); + assertEquals(PodInfoType.DETAILED_STATUS, podInfoResponse.getSubType()); thrown.expect(ClassCastException.class); PodInfoActiveAlerts podInfo = (PodInfoActiveAlerts) podInfoResponse.getPodInfo(); diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/events/EventRileyLinkDeviceStatusChange.kt b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/events/EventRileyLinkDeviceStatusChange.kt index b3425d14a5..b2ece2d419 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/events/EventRileyLinkDeviceStatusChange.kt +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/events/EventRileyLinkDeviceStatusChange.kt @@ -1,12 +1,15 @@ package info.nightscout.androidaps.plugins.pump.common.events -import info.nightscout.androidaps.events.Event +import info.nightscout.androidaps.events.EventStatus import info.nightscout.androidaps.plugins.pump.common.defs.PumpDeviceState 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.utils.resources.ResourceHelper -open class EventRileyLinkDeviceStatusChange : Event { +open class EventRileyLinkDeviceStatusChange : EventStatus { + var rileyLinkTargetDevice: RileyLinkTargetDevice? = null var rileyLinkServiceState: RileyLinkServiceState? = null var rileyLinkError: RileyLinkError? = null @@ -14,11 +17,10 @@ open class EventRileyLinkDeviceStatusChange : Event { var errorDescription: String? = null constructor() { - } - - constructor(rileyLinkServiceState: RileyLinkServiceState?, rileyLinkError: RileyLinkError?) { + constructor(rileyLinkTargetDevice: RileyLinkTargetDevice, rileyLinkServiceState: RileyLinkServiceState?, rileyLinkError: RileyLinkError?) { + this.rileyLinkTargetDevice = rileyLinkTargetDevice this.rileyLinkServiceState = rileyLinkServiceState this.rileyLinkError = rileyLinkError } @@ -31,4 +33,17 @@ open class EventRileyLinkDeviceStatusChange : Event { this.pumpDeviceState = pumpDeviceState this.errorDescription = errorDescription } + + override fun getStatus(resourceHelper: ResourceHelper): String { + val rileyLinkServiceState = this.rileyLinkServiceState ?: return "" + val resourceId = rileyLinkServiceState.resourceId + val rileyLinkError = this.rileyLinkError + + if (rileyLinkServiceState.isError && rileyLinkError != null) { + val rileyLinkTargetDevice = this.rileyLinkTargetDevice ?: return "" + return resourceHelper.gs(rileyLinkError.getResourceId(rileyLinkTargetDevice)) + } + + return resourceHelper.gs(resourceId) + } } diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java index b4fb23d65f..b039e49c59 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkService.java @@ -24,8 +24,6 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.Rile 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.service.data.ServiceResult; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.data.ServiceTransport; import info.nightscout.androidaps.utils.resources.ResourceHelper; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -114,6 +112,10 @@ public abstract class RileyLinkService extends DaggerService { public abstract RileyLinkCommunicationManager getDeviceCommunicationManager(); + public RileyLinkServiceState getRileyLinkServiceState() { + return rileyLinkServiceData == null ? null : rileyLinkServiceData.rileyLinkServiceState; + } + // Here is where the wake-lock begins: // We've received a service startCommand, we grab the lock. @Override diff --git a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java index 13bebc22b8..02b27846bc 100644 --- a/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java +++ b/rileylink/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java @@ -33,8 +33,7 @@ public class RileyLinkServiceData { public RileyLinkServiceState rileyLinkServiceState = RileyLinkServiceState.NotStarted; private long lastServiceStateChange = 0L; public RileyLinkFirmwareVersion firmwareVersion; - public RileyLinkTargetFrequency rileyLinkTargetFrequency; // TODO this might not be correct place - + public RileyLinkTargetFrequency rileyLinkTargetFrequency; public String rileylinkAddress; long lastTuneUpTime = 0L; public Double lastGoodFrequency; @@ -44,7 +43,7 @@ public class RileyLinkServiceData { // radio version public RileyLinkFirmwareVersion versionCC110; - public RileyLinkTargetDevice targetDevice; // TODO this might not be correct place + public RileyLinkTargetDevice targetDevice; // Medtronic Pump public String pumpID; @@ -86,7 +85,7 @@ public class RileyLinkServiceData { aapsLogger.info(LTag.PUMP, "RileyLink State Changed: {} {}", newState, errorCode == null ? "" : " - Error State: " + errorCode.name()); rileyLinkUtil.getRileyLinkHistory().add(new RLHistoryItem(rileyLinkServiceState, errorCode, targetDevice)); - rxBus.send(new EventRileyLinkDeviceStatusChange(newState, errorCode)); + rxBus.send(new EventRileyLinkDeviceStatusChange(targetDevice, newState, errorCode)); return null; } else {