diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt index 9fa0ae8da4..a47a316fd2 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/OmnipodModule.kt @@ -1,9 +1,13 @@ package info.nightscout.androidaps.dependencyInjection import dagger.Module +import dagger.Provides import dagger.android.ContributesAndroidInjector +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.plugins.bus.RxBusWrapper +import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodHistoryActivity import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.initpod.InitActionFragment @@ -11,30 +15,45 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.initpod.In import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.pages.InitPodRefreshAction import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.pages.PodInfoFragment import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.removepod.RemoveActionFragment +import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus import info.nightscout.androidaps.plugins.pump.omnipod.driver.comm.AapsOmnipodManager +import info.nightscout.androidaps.plugins.pump.omnipod.driver.comm.AapsPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUITask +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import javax.inject.Singleton @Module @Suppress("unused") abstract class OmnipodModule { // Activities - @ContributesAndroidInjector abstract fun contributesPodManagementActivity(): PodManagementActivity + @ContributesAndroidInjector + abstract fun contributesPodManagementActivity(): PodManagementActivity @ContributesAndroidInjector abstract fun contributesPodHistoryActivity(): PodHistoryActivity // Fragments - @ContributesAndroidInjector abstract fun initActionFragment() : InitActionFragment - @ContributesAndroidInjector abstract fun removeActionFragment() : RemoveActionFragment - @ContributesAndroidInjector abstract fun podInfoFragment() : PodInfoFragment + @ContributesAndroidInjector abstract fun initActionFragment(): InitActionFragment + @ContributesAndroidInjector abstract fun removeActionFragment(): RemoveActionFragment + @ContributesAndroidInjector abstract fun podInfoFragment(): PodInfoFragment // Service - @ContributesAndroidInjector abstract fun omnipodCommunicationManagerProvider(): OmnipodCommunicationManager + @ContributesAndroidInjector + abstract fun omnipodCommunicationManagerProvider(): OmnipodCommunicationManager @ContributesAndroidInjector abstract fun aapsOmnipodManagerProvider(): AapsOmnipodManager // Data @ContributesAndroidInjector abstract fun omnipodUITaskProvider(): OmnipodUITask @ContributesAndroidInjector abstract fun initPodRefreshAction(): InitPodRefreshAction - @ContributesAndroidInjector abstract fun podSessionState(): PodSessionState - @ContributesAndroidInjector abstract fun initPodTask() : InitPodTask + @ContributesAndroidInjector abstract fun podStateManager(): PodStateManager + @ContributesAndroidInjector abstract fun initPodTask(): InitPodTask + @ContributesAndroidInjector abstract fun omnipodPumpPlugin(): OmnipodPumpPlugin + companion object { + @Provides + @Singleton + fun podStateManagerProvider(aapsLogger: AAPSLogger, sp: SP, omnipodPumpStatus: OmnipodPumpStatus, + rxBus: RxBusWrapper, resourceHelper: ResourceHelper): PodStateManager = + AapsPodStateManager(aapsLogger, sp, omnipodPumpStatus, rxBus, resourceHelper) + } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java index ff524b2ed2..18e07f1e72 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/RileyLinkUtil.java @@ -38,9 +38,6 @@ public class RileyLinkUtil { private RileyLinkEncodingType encoding; private Encoding4b6b encoding4b6b; - // TODO maybe not needed - private RileyLinkTargetFrequency rileyLinkTargetFrequency; - @Inject public RileyLinkUtil() { } @@ -158,8 +155,4 @@ public class RileyLinkUtil { public Encoding4b6b getEncoding4b6b() { return encoding4b6b; } - - public void setRileyLinkTargetFrequency(RileyLinkTargetFrequency rileyLinkTargetFrequency_) { - this.rileyLinkTargetFrequency = rileyLinkTargetFrequency_; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java index 702354a82e..71fc405748 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/RFSpy.java @@ -387,7 +387,7 @@ public class RFSpy { try { resp = writeToData(new SetPreamble(injector, preamble), EXPECTED_MAX_BLUETOOTH_LATENCY_MS); } catch (Exception e) { - e.toString(); + aapsLogger.error("Failed to set preamble", e); } return resp; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java index d58525deb0..3e99a8e412 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/ble/command/SetPreamble.java @@ -18,10 +18,11 @@ public class SetPreamble extends RileyLinkCommand { private int preamble; - public SetPreamble(HasAndroidInjector injector, int preamble) throws Exception { super(); + injector.androidInjector().inject(this); + // this command was not supported before 2.0 if (!rileyLinkServiceData.firmwareVersion.isSameVersion(RileyLinkFirmwareVersion.Version2AndHigher)) { throw new NotImplementedException("Old firmware does not support SetPreamble command"); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java index 4beea20154..5cec5ccccf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkBroadcastReceiver.java @@ -150,7 +150,7 @@ public class RileyLinkBroadcastReceiver extends DaggerBroadcastReceiver { return true; } else if (action.equals(RileyLinkConst.Intents.RileyLinkReady)) { - aapsLogger.warn(LTag.PUMPCOMM, "MedtronicConst.Intents.RileyLinkReady"); + aapsLogger.warn(LTag.PUMPCOMM, "RileyLinkConst.Intents.RileyLinkReady"); // sendIPCNotification(RT2Const.IPC.MSG_note_WakingPump); rileyLinkService.rileyLinkBLE.enableNotifications(); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java index cac30e6de1..b2439546a7 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/common/hw/rileylink/service/RileyLinkServiceData.java @@ -67,12 +67,10 @@ public class RileyLinkServiceData { return workWithServiceState(null, null, false); } - public void setServiceState(RileyLinkServiceState newState, RileyLinkError errorCode) { workWithServiceState(newState, errorCode, true); } - private synchronized RileyLinkServiceState workWithServiceState(RileyLinkServiceState newState, RileyLinkError errorCode, boolean set) { if (set) { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.kt index 667961be61..e1c22dc78e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodFragment.kt @@ -22,10 +22,8 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLin import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.dialog.RileyLinkStatusActivity import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodStatusRequest -import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodDeviceState -import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity -import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodDriverState import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodAcknowledgeAlertsChanged import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange @@ -61,6 +59,7 @@ class OmnipodFragment : DaggerFragment() { @Inject lateinit var omnipodPumpPlugin: OmnipodPumpPlugin @Inject lateinit var warnColors: WarnColors @Inject lateinit var omnipodPumpStatus: OmnipodPumpStatus + @Inject lateinit var podStateManager: PodStateManager @Inject lateinit var sp: SP @Inject lateinit var omnipodUtil: OmnipodUtil @Inject lateinit var rileyLinkServiceData: RileyLinkServiceData @@ -207,16 +206,10 @@ class OmnipodFragment : DaggerFragment() { } @Synchronized - private fun setDeviceStatus(event : EventOmnipodDeviceStatusChange) { - - + private fun setDeviceStatus(event: EventOmnipodDeviceStatusChange) { } - - - - @Synchronized private fun setDeviceStatus() { //val omnipodPumpStatus: OmnipodPumpStatus = OmnipodUtil.getPumpStatus() @@ -250,81 +243,48 @@ class OmnipodFragment : DaggerFragment() { aapsLogger.info(LTag.PUMP, "getDriverState: [driverState={}]", driverState) - if (driverState == OmnipodDriverState.NotInitalized) { - omnipod_pod_address.text = resourceHelper.gs(R.string.omnipod_pod_name_no_info) + if (!podStateManager.hasState() || !podStateManager.isPaired) { + if (podStateManager.hasState()) { + omnipod_pod_address.text = podStateManager.address.toString() + } else { + omnipod_pod_address.text = "-" + } + omnipod_pod_lot.text = "-" + omnipod_pod_tid.text = "-" + omnipod_pod_fw_version.text = "-" omnipod_pod_expiry.text = "-" - omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_not_initalized) + if (podStateManager.hasState()) { + omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_status_not_initalized) + } else { + omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_status_no_pod_connected) + } omnipodPumpStatus.podAvailable = false omnipodPumpStatus.podNumber == null - } else if (driverState == OmnipodDriverState.Initalized_NoPod) { - omnipod_pod_address.text = resourceHelper.gs(R.string.omnipod_pod_name_no_info) - omnipod_pod_expiry.text = "-" - omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_no_pod_connected) - omnipodPumpStatus.podAvailable = false - omnipodPumpStatus.podNumber == null - } else if (driverState == OmnipodDriverState.Initalized_PodInitializing) { - omnipod_pod_address.text = omnipodPumpStatus.podSessionState.address.toString() - omnipod_pod_expiry.text = "-" - omnipod_pod_status.text = resourceHelper.gs(R.string.omnipod_pod_status_initalizing) + " (" + omnipodPumpStatus.podSessionState.getSetupProgress().name + ")" - omnipodPumpStatus.podAvailable = false - omnipodPumpStatus.podNumber == omnipodPumpStatus.podSessionState.address.toString() } else { - omnipodPumpStatus.podLotNumber = "" + omnipodPumpStatus.podSessionState.lot - omnipodPumpStatus.podAvailable = true - omnipod_pod_address.text = omnipodPumpStatus.podSessionState.address.toString() - omnipod_pod_expiry.text = omnipodPumpStatus.podSessionState.expiryDateAsString - omnipodPumpStatus.podNumber = omnipodPumpStatus.podSessionState.address.toString() - - //pumpStatus.podSessionState = checkStatusSet(pumpStatus.podSessionState, - // OmnipodUtil.getPodSessionState()) as PodSessionState? + omnipodPumpStatus.podLotNumber = "" + podStateManager.lot + omnipodPumpStatus.podAvailable = podStateManager.isSetupCompleted + omnipod_pod_address.text = podStateManager.address.toString() + omnipod_pod_lot.text = podStateManager.lot.toString() + omnipod_pod_tid.text = podStateManager.tid.toString() + omnipod_pod_fw_version.text = podStateManager.pmVersion.toString() + " / " + podStateManager.piVersion.toString() + omnipod_pod_expiry.text = podStateManager.expiryDateAsString + omnipodPumpStatus.podNumber = podStateManager.address.toString() var podDeviceState = omnipodPumpStatus.podDeviceState - var stateText : String? + var stateText: String? - when (podDeviceState) { - null, - PodDeviceState.Sleeping -> stateText = "{fa-bed} " // + pumpStatus.pumpDeviceState.name()); - PodDeviceState.NeverContacted, - PodDeviceState.WakingUp, - PodDeviceState.PumpUnreachable, - PodDeviceState.ErrorWhenCommunicating, - PodDeviceState.TimeoutWhenCommunicating, - PodDeviceState.InvalidConfiguration -> stateText = " " + resourceHelper.gs(podDeviceState.resourceId) - - PodDeviceState.Active -> { - stateText = resourceHelper.gs(R.string.omnipod_pod_status_active) -// val cmd = OmnipodUtil.getCurrentCommand() -// if (cmd == null) -// omnipod_pod_status.text = " " + resourceHelper.gs(pumpStatus.pumpDeviceState.resourceId) -// else { -// aapsLogger.debug(LTag.PUMP,"Command: " + cmd) -// val cmdResourceId = cmd.resourceId -// if (cmd == MedtronicCommandType.GetHistoryData) { -// omnipod_pod_status.text = OmnipodUtil.frameNumber?.let { -// resourceHelper.gs(cmdResourceId, OmnipodUtil.pageNumber, OmnipodUtil.frameNumber) -// } -// ?: resourceHelper.gs(R.string.medtronic_cmd_desc_get_history_request, OmnipodUtil.pageNumber) -// } else { -// omnipod_pod_status.text = " " + (cmdResourceId?.let { resourceHelper.gs(it) } -// ?: cmd.getCommandDescription()) -// } -// } - } - else -> { - aapsLogger.warn(LTag.PUMP, "Unknown pump state: " + omnipodPumpStatus.podDeviceState) - stateText = resourceHelper.gs(R.string.omnipod_pod_status_unknown) - } - } - - if (SetupProgress.COMPLETED.equals(omnipodPumpStatus.podSessionState.getSetupProgress())) { - if(omnipodPumpStatus.podSessionState.lastDeliveryStatus != null) { - stateText += " (last delivery status: " + omnipodPumpStatus.podSessionState.lastDeliveryStatus.name + ")" + if(podStateManager.hasFaultEvent()) { + val faultEventCode = podStateManager.faultEvent.faultEventCode + stateText = resourceHelper.gs(R.string.omnipod_pod_status_pod_fault) + " ("+ faultEventCode.value +" "+ faultEventCode.name +")" + } else if (podStateManager.isSetupCompleted) { + stateText = resourceHelper.gs(R.string.omnipod_pod_status_pod_running) + if (podStateManager.lastDeliveryStatus != null) { + stateText += " (last delivery status: " + podStateManager.lastDeliveryStatus.name + ")" } } else { - if(omnipodPumpStatus.podSessionState.setupProgress != null) { - stateText += " (setup progress: " + omnipodPumpStatus.podSessionState.setupProgress.name + ")" - } + stateText = resourceHelper.gs(R.string.omnipod_pod_setup_in_progress) + stateText += " (setup progress: " + podStateManager.setupProgress.name + ")" } omnipod_pod_status.text = stateText diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java index 521db02a60..49b7faa7fe 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/OmnipodPumpPlugin.java @@ -49,7 +49,6 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific import info.nightscout.androidaps.plugins.pump.common.PumpPluginAbstract; import info.nightscout.androidaps.plugins.pump.common.data.PumpStatus; import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair; -import info.nightscout.androidaps.plugins.pump.common.defs.DeviceCommandExecutor; import info.nightscout.androidaps.plugins.pump.common.defs.PumpDriverState; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.RileyLinkConst; @@ -64,7 +63,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunication import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCustomActionType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodPumpPluginInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodStatusRequest; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodDriverState; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUIComm; @@ -91,6 +90,7 @@ import io.reactivex.schedulers.Schedulers; public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPumpPluginInterface, RileyLinkPumpDevice { // TODO Dagger (maybe done) + @Inject protected PodStateManager podStateManager; private static OmnipodPumpPlugin plugin = null; private RileyLinkServiceData rileyLinkServiceData; private ServiceTaskExecutor serviceTaskExecutor; @@ -150,6 +150,7 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump PumpType.Insulet_Omnipod, injector, resourceHelper, aapsLogger, commandQueue, rxBus, activePlugin, sp, context, fabricPrivacy ); + injector.androidInjector().inject(this); this.rileyLinkServiceData = rileyLinkServiceData; this.serviceTaskExecutor = serviceTaskExecutor; @@ -198,6 +199,10 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump if (isOmnipodEros) { + // We can't do this in PodStateManager itself, because JodaTimeAndroid.init() hasn't been called yet + // When PodStateManager is created, which causes an IllegalArgumentException for DateTimeZones not being recognized + podStateManager.loadPodState(); + serviceConnection = new ServiceConnection() { @Override @@ -487,18 +492,18 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump @Override public boolean isSuspended() { - return (omnipodUtil.getDriverState() == OmnipodDriverState.Initalized_NoPod) || - (omnipodUtil.getPodSessionState() != null && omnipodUtil.getPodSessionState().isSuspended()); + return omnipodUtil.getDriverState() == OmnipodDriverState.Initalized_NoPod || + !podStateManager.isSetupCompleted() || podStateManager.isSuspended(); // return (pumpStatusLocal != null && !pumpStatusLocal.podAvailable) || -// (OmnipodUtil.getPodSessionState() != null && OmnipodUtil.getPodSessionState().isSuspended()); +// (omnipodUtil.getPodStateManager().hasState() && OmnipodUtil.getPodStateManager().isSuspended()); // // TODO ddd // return (OmnipodUtil.getDriverState() == OmnipodDriverState.Initalized_NoPod) || -// (OmnipodUtil.getPodSessionState() != null && OmnipodUtil.getPodSessionState().isSuspended()); +// (omnipodUtil.getPodStateManager().hasState() && OmnipodUtil.getPodStateManager().isSuspended()); // // return (pumpStatusLocal != null && !pumpStatusLocal.podAvailable) || -// (OmnipodUtil.getPodSessionState() != null && OmnipodUtil.getPodSessionState().isSuspended()); +// (omnipodUtil.getPodStateManager().hasState() && OmnipodUtil.getPodStateManager().isSuspended()); } @Override @@ -580,6 +585,7 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump //getPodPumpStatusObject().driverState = OmnipodDriverState.Initalized_PodAvailable; //driverState = OmnipodDriverState.Initalized_PodAvailable; + // FIXME this does not seem to make sense omnipodUtil.setDriverState(OmnipodDriverState.Initalized_PodAttached); // we would probably need to read Basal Profile here too } @@ -613,8 +619,6 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump private void initializePump(boolean realInit) { - - aapsLogger.info(LTag.PUMP, getLogPrefix() + "initializePump - start"); // TODO ccc @@ -622,17 +626,8 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump setRefreshButtonEnabled(false); - PodSessionState podSessionState = null; - - if (omnipodUtil.getPodSessionState() != null) { - podSessionState = omnipodUtil.getPodSessionState(); - } else { - podSessionState = omnipodUtil.loadSessionState(); - } - - - if (podSessionState != null) { - aapsLogger.debug(LTag.PUMP, "PodSessionState (saved): " + podSessionState); + if (podStateManager.isPaired()) { + aapsLogger.debug(LTag.PUMP, "PodStateManager (saved): " + podStateManager); if (!isRefresh) { pumpState = PumpDriverState.Initialized; @@ -640,9 +635,8 @@ public class OmnipodPumpPlugin extends PumpPluginAbstract implements OmnipodPump // TODO handle if session state too old getPodPumpStatus(); - } else { - aapsLogger.debug(LTag.PUMP, "No PodSessionState found. Pod probably not running."); + aapsLogger.debug(LTag.PUMP, "No Pod running"); omnipodUtil.setDriverState(OmnipodDriverState.Initalized_NoPod); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java index e77befd258..7c9a96c0b4 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodCommunicationManager.java @@ -1,5 +1,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm; +import org.joda.time.DateTime; + import java.util.Collections; import java.util.List; @@ -16,11 +18,8 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.RileyLink import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.data.RLMessage; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RLMessageType; import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.ble.defs.RileyLinkBLEError; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.RileyLinkServiceData; -import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; -import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin; import info.nightscout.androidaps.plugins.pump.omnipod.comm.action.OmnipodAction; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.CommunicationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; @@ -43,7 +42,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.pod import info.nightscout.androidaps.plugins.pump.omnipod.defs.MessageBlockType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; @@ -103,13 +102,13 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { this.omnipodPumpStatus.setPumpDeviceState(pumpDeviceState); } - public T sendCommand(Class responseClass, PodState podState, MessageBlock command) { - return sendCommand(responseClass, podState, command, true); + public T sendCommand(Class responseClass, PodStateManager podStateManager, MessageBlock command) { + return sendCommand(responseClass, podStateManager, command, true); } - public T sendCommand(Class responseClass, PodState podState, MessageBlock command, boolean automaticallyResyncNone) { - OmnipodMessage message = new OmnipodMessage(podState.getAddress(), Collections.singletonList(command), podState.getMessageNumber()); - return exchangeMessages(responseClass, podState, message, automaticallyResyncNone); + public T sendCommand(Class responseClass, PodStateManager podStateManager, MessageBlock command, boolean automaticallyResyncNone) { + OmnipodMessage message = new OmnipodMessage(podStateManager.getAddress(), Collections.singletonList(command), podStateManager.getMessageNumber()); + return exchangeMessages(responseClass, podStateManager, message, automaticallyResyncNone); } // Convenience method @@ -117,70 +116,76 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { return action.execute(this); } - public T exchangeMessages(Class responseClass, PodState podState, OmnipodMessage message) { - return exchangeMessages(responseClass, podState, message, true); + public T exchangeMessages(Class responseClass, PodStateManager podStateManager, OmnipodMessage message) { + return exchangeMessages(responseClass, podStateManager, message, true); } - public T exchangeMessages(Class responseClass, PodState podState, OmnipodMessage message, boolean automaticallyResyncNonce) { - return exchangeMessages(responseClass, podState, message, null, null, automaticallyResyncNonce); + public T exchangeMessages(Class responseClass, PodStateManager podStateManager, OmnipodMessage message, boolean automaticallyResyncNonce) { + return exchangeMessages(responseClass, podStateManager, message, null, null, automaticallyResyncNonce); } - public synchronized T exchangeMessages(Class responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { - return exchangeMessages(responseClass, podState, message, addressOverride, ackAddressOverride, true); + public synchronized T exchangeMessages(Class responseClass, PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { + return exchangeMessages(responseClass, podStateManager, message, addressOverride, ackAddressOverride, true); } - public synchronized T exchangeMessages(Class responseClass, PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride, boolean automaticallyResyncNonce) { + public synchronized T exchangeMessages(Class responseClass, PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride, boolean automaticallyResyncNonce) { - aapsLogger.debug(LTag.PUMPCOMM, "Exchanging OmnipodMessage [responseClass={}, podState={}, message={}, addressOverride={}, ackAddressOverride={}, automaticallyResyncNonce={}]: {}", // - responseClass.getSimpleName(), podState, message, addressOverride, ackAddressOverride, automaticallyResyncNonce, message); + aapsLogger.debug(LTag.PUMPCOMM, "Exchanging OmnipodMessage [responseClass={}, podStateManager={}, message={}, addressOverride={}, ackAddressOverride={}, automaticallyResyncNonce={}]: {}", // + responseClass.getSimpleName(), podStateManager, message, addressOverride, ackAddressOverride, automaticallyResyncNonce, message); for (int i = 0; 2 > i; i++) { - if (podState.hasNonceState() && message.isNonceResyncable()) { - podState.advanceToNextNonce(); + if (podStateManager.isPaired() && message.isNonceResyncable()) { + podStateManager.advanceToNextNonce(); } - MessageBlock responseMessageBlock = transportMessages(podState, message, addressOverride, ackAddressOverride); + MessageBlock responseMessageBlock = transportMessages(podStateManager, message, addressOverride, ackAddressOverride); if (responseMessageBlock instanceof StatusResponse) { - podState.updateFromStatusResponse((StatusResponse) responseMessageBlock); + podStateManager.updateFromStatusResponse((StatusResponse) responseMessageBlock); } if (responseClass.isInstance(responseMessageBlock)) { + podStateManager.setLastSuccessfulCommunication(DateTime.now()); return (T) responseMessageBlock; } else { if (responseMessageBlock.getType() == MessageBlockType.ERROR_RESPONSE) { ErrorResponse error = (ErrorResponse) responseMessageBlock; if (error.getErrorResponseCode() == ErrorResponse.ERROR_RESPONSE_CODE_BAD_NONCE) { - podState.resyncNonce(error.getNonceSearchKey(), message.getSentNonce(), message.getSequenceNumber()); + podStateManager.resyncNonce(error.getNonceSearchKey(), message.getSentNonce(), message.getSequenceNumber()); if (automaticallyResyncNonce) { - message.resyncNonce(podState.getCurrentNonce()); + message.resyncNonce(podStateManager.getCurrentNonce()); } else { + podStateManager.setLastFailedCommunication(DateTime.now()); throw new NonceOutOfSyncException(); } } else { + podStateManager.setLastFailedCommunication(DateTime.now()); throw new PodReturnedErrorResponseException(error); } } else if (responseMessageBlock.getType() == MessageBlockType.POD_INFO_RESPONSE && ((PodInfoResponse) responseMessageBlock).getSubType() == PodInfoType.FAULT_EVENT) { PodInfoFaultEvent faultEvent = ((PodInfoResponse) responseMessageBlock).getPodInfo(); - podState.setFaultEvent(faultEvent); + podStateManager.setFaultEvent(faultEvent); + podStateManager.setLastFailedCommunication(DateTime.now()); throw new PodFaultException(faultEvent); } else { + podStateManager.setLastFailedCommunication(DateTime.now()); throw new IllegalResponseException(responseClass.getSimpleName(), responseMessageBlock.getType()); } } } + podStateManager.setLastFailedCommunication(DateTime.now()); throw new NonceResyncException(); } - private MessageBlock transportMessages(PodState podState, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { - int packetAddress = podState.getAddress(); + private MessageBlock transportMessages(PodStateManager podStateManager, OmnipodMessage message, Integer addressOverride, Integer ackAddressOverride) { + int packetAddress = podStateManager.getAddress(); if (addressOverride != null) { packetAddress = addressOverride; } - podState.increaseMessageNumber(); + podStateManager.increaseMessageNumber(); boolean firstPacket = true; byte[] encodedMessage; @@ -203,7 +208,7 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { OmnipodPacket response = null; while (encodedMessage.length > 0) { PacketType packetType = firstPacket ? PacketType.PDM : PacketType.CON; - OmnipodPacket packet = new OmnipodPacket(packetAddress, packetType, podState.getPacketNumber(), encodedMessage); + OmnipodPacket packet = new OmnipodPacket(packetAddress, packetType, podStateManager.getPacketNumber(), encodedMessage); byte[] encodedMessageInPacket = packet.getEncodedMessage(); // getting the data remaining to be sent @@ -212,7 +217,7 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { try { // We actually ignore previous (ack) responses if it was not last packet to send - response = exchangePackets(podState, packet); + response = exchangePackets(podStateManager, packet); } catch (Exception ex) { OmnipodException newException; if (ex instanceof OmnipodException) { @@ -245,15 +250,15 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { if (receivedMessage.getAddress() != message.getAddress()) { throw new IllegalMessageAddressException(message.getAddress(), receivedMessage.getAddress()); } - if (receivedMessage.getSequenceNumber() != podState.getMessageNumber()) { - throw new IllegalMessageSequenceNumberException(podState.getMessageNumber(), receivedMessage.getSequenceNumber()); + if (receivedMessage.getSequenceNumber() != podStateManager.getMessageNumber()) { + throw new IllegalMessageSequenceNumberException(podStateManager.getMessageNumber(), receivedMessage.getSequenceNumber()); } } catch (NotEnoughDataException ex) { // Message is (probably) not complete yet - OmnipodPacket ackForCon = createAckPacket(podState, packetAddress, ackAddressOverride); + OmnipodPacket ackForCon = createAckPacket(podStateManager, packetAddress, ackAddressOverride); try { - OmnipodPacket conPacket = exchangePackets(podState, ackForCon, 3, 40); + OmnipodPacket conPacket = exchangePackets(podStateManager, ackForCon, 3, 40); if (conPacket.getPacketType() != PacketType.CON) { throw new IllegalPacketTypeException(PacketType.CON, conPacket.getPacketType()); } @@ -267,7 +272,7 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { } } - ackUntilQuiet(podState, packetAddress, ackAddressOverride); + ackUntilQuiet(podStateManager, packetAddress, ackAddressOverride); List messageBlocks = receivedMessage.getMessageBlocks(); @@ -281,24 +286,24 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { MessageBlock messageBlock = messageBlocks.get(0); if (messageBlock.getType() != MessageBlockType.ERROR_RESPONSE) { - podState.increaseMessageNumber(); + podStateManager.increaseMessageNumber(); } return messageBlock; } - private OmnipodPacket createAckPacket(PodState podState, Integer packetAddress, Integer messageAddress) { + private OmnipodPacket createAckPacket(PodStateManager podStateManager, Integer packetAddress, Integer messageAddress) { if (packetAddress == null) { - packetAddress = podState.getAddress(); + packetAddress = podStateManager.getAddress(); } if (messageAddress == null) { - messageAddress = podState.getAddress(); + messageAddress = podStateManager.getAddress(); } - return new OmnipodPacket(packetAddress, PacketType.ACK, podState.getPacketNumber(), ByteUtil.getBytesFromInt(messageAddress)); + return new OmnipodPacket(packetAddress, PacketType.ACK, podStateManager.getPacketNumber(), ByteUtil.getBytesFromInt(messageAddress)); } - private void ackUntilQuiet(PodState podState, Integer packetAddress, Integer messageAddress) { - OmnipodPacket ack = createAckPacket(podState, packetAddress, messageAddress); + private void ackUntilQuiet(PodStateManager podStateManager, Integer packetAddress, Integer messageAddress) { + OmnipodPacket ack = createAckPacket(podStateManager, packetAddress, messageAddress); boolean quiet = false; while (!quiet) try { sendAndListen(ack, 300, 1, 0, 40, OmnipodPacket.class); @@ -314,21 +319,21 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { throw new CommunicationException(CommunicationException.Type.UNEXPECTED_EXCEPTION, ex); } - podState.increasePacketNumber(); + podStateManager.increasePacketNumber(); } - private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet) { - return exchangePackets(podState, packet, 0, 333, 9000, 127); + private OmnipodPacket exchangePackets(PodStateManager podStateManager, OmnipodPacket packet) { + return exchangePackets(podStateManager, packet, 0, 333, 9000, 127); } - private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet, int repeatCount, int preambleExtensionMilliseconds) { - return exchangePackets(podState, packet, repeatCount, 333, 9000, preambleExtensionMilliseconds); + private OmnipodPacket exchangePackets(PodStateManager podStateManager, OmnipodPacket packet, int repeatCount, int preambleExtensionMilliseconds) { + return exchangePackets(podStateManager, packet, repeatCount, 333, 9000, preambleExtensionMilliseconds); } - private OmnipodPacket exchangePackets(PodState podState, OmnipodPacket packet, int repeatCount, int responseTimeoutMilliseconds, int exchangeTimeoutMilliseconds, int preambleExtensionMilliseconds) { + private OmnipodPacket exchangePackets(PodStateManager podStateManager, OmnipodPacket packet, int repeatCount, int responseTimeoutMilliseconds, int exchangeTimeoutMilliseconds, int preambleExtensionMilliseconds) { long timeoutTime = System.currentTimeMillis() + exchangeTimeoutMilliseconds; - podState.increasePacketNumber(); + podStateManager.increasePacketNumber(); while (System.currentTimeMillis() < timeoutTime) { OmnipodPacket response = null; @@ -353,13 +358,13 @@ public class OmnipodCommunicationManager extends RileyLinkCommunicationManager { continue; } - if (response.getSequenceNumber() != podState.getPacketNumber()) { - aapsLogger.debug(LTag.PUMPBTCOMM, "Packet sequence number " + response.getSequenceNumber() + " does not match " + podState.getPacketNumber()); + if (response.getSequenceNumber() != podStateManager.getPacketNumber()) { + aapsLogger.debug(LTag.PUMPBTCOMM, "Packet sequence number " + response.getSequenceNumber() + " does not match " + podStateManager.getPacketNumber()); continue; } // Once we have verification that the POD heard us, we can increment our counters - podState.increasePacketNumber(); + podStateManager.increasePacketNumber(); return response; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java index c1a4cd57c5..3de30a1845 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/OmnipodManager.java @@ -5,7 +5,6 @@ import org.joda.time.DateTimeZone; import org.joda.time.Duration; import java.util.EnumSet; -import java.util.Random; import java.util.TimeZone; import java.util.concurrent.TimeUnit; @@ -40,8 +39,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateChangedHandler; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; import info.nightscout.androidaps.utils.sharedPreferences.SP; @@ -55,49 +53,45 @@ import io.reactivex.subjects.SingleSubject; public class OmnipodManager { private static final int ACTION_VERIFICATION_TRIES = 3; - protected final OmnipodCommunicationManager communicationService; - private final PodStateChangedHandler podStateChangedHandler; - protected PodSessionState podState; + private final OmnipodCommunicationManager communicationService; + private PodStateManager podStateManager; private ActiveBolusData activeBolusData; private final Object bolusDataMutex = new Object(); private AAPSLogger aapsLogger; - private SP sp; public OmnipodManager(AAPSLogger aapsLogger, SP sp, OmnipodCommunicationManager communicationService, - PodSessionState podState, - PodStateChangedHandler podStateChangedHandler) { + PodStateManager podStateManager) { if (communicationService == null) { throw new IllegalArgumentException("Communication service cannot be null"); } - this.aapsLogger = aapsLogger; - this.sp = sp; - this.communicationService = communicationService; - if (podState != null) { - podState.setStateChangedHandler(podStateChangedHandler); + if (podStateManager == null) { + throw new IllegalArgumentException("Pod State Manager can not be null"); } - this.podState = podState; - this.podStateChangedHandler = podStateChangedHandler; + this.aapsLogger = aapsLogger; + this.communicationService = communicationService; + + this.podStateManager = podStateManager; } - public synchronized Single pairAndPrime(int address) { + public synchronized Single pairAndPrime() { logStartingCommandExecution("pairAndPrime"); try { - if (podState == null || podState.getSetupProgress().isBefore(SetupProgress.POD_CONFIGURED)) { + if (!podStateManager.hasState() || !podStateManager.isPaired() || podStateManager.getSetupProgress().isBefore(SetupProgress.POD_CONFIGURED)) { // Always send both 0x07 and 0x03 on retries - podState = communicationService.executeAction( - new AssignAddressAction(podStateChangedHandler, address)); + communicationService.executeAction( + new AssignAddressAction(podStateManager)); - communicationService.executeAction(new SetupPodAction(podState)); - } else if (SetupProgress.PRIMING.isBefore(podState.getSetupProgress())) { - throw new IllegalSetupProgressException(SetupProgress.POD_CONFIGURED, podState.getSetupProgress()); + communicationService.executeAction(new SetupPodAction(podStateManager)); + } else if (SetupProgress.PRIMING.isBefore(podStateManager.getSetupProgress())) { + throw new IllegalSetupProgressException(SetupProgress.POD_CONFIGURED, podStateManager.getSetupProgress()); } - communicationService.executeAction(new PrimeAction(new PrimeService(), podState)); + communicationService.executeAction(new PrimeAction(new PrimeService(), podStateManager)); } finally { logCommandExecutionFinished("pairAndPrime"); } @@ -106,21 +100,21 @@ public class OmnipodManager { return Single.timer(delayInSeconds, TimeUnit.SECONDS) // .map(o -> verifySetupAction(statusResponse -> - PrimeAction.updatePrimingStatus(podState, statusResponse, aapsLogger), SetupProgress.PRIMING_FINISHED)) // + PrimeAction.updatePrimingStatus(podStateManager, statusResponse, aapsLogger), SetupProgress.PRIMING_FINISHED)) // .observeOn(Schedulers.io()); } public synchronized Single insertCannula(BasalSchedule basalSchedule) { - if (podState == null || podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { - throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, podState == null ? null : podState.getSetupProgress()); - } else if (podState.getSetupProgress().isAfter(SetupProgress.CANNULA_INSERTING)) { - throw new IllegalSetupProgressException(SetupProgress.CANNULA_INSERTING, podState.getSetupProgress()); + if (!podStateManager.hasState() || !podStateManager.isPaired() || podStateManager.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { + throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, !podStateManager.hasState() ? null : podStateManager.getSetupProgress()); + } else if (podStateManager.getSetupProgress().isAfter(SetupProgress.CANNULA_INSERTING)) { + throw new IllegalSetupProgressException(SetupProgress.CANNULA_INSERTING, podStateManager.getSetupProgress()); } logStartingCommandExecution("insertCannula [basalSchedule=" + basalSchedule + "]"); try { - communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podState, basalSchedule)); + communicationService.executeAction(new InsertCannulaAction(new InsertCannulaService(), podStateManager, basalSchedule)); } finally { logCommandExecutionFinished("insertCannula"); } @@ -129,19 +123,19 @@ public class OmnipodManager { return Single.timer(delayInSeconds, TimeUnit.SECONDS) // .map(o -> verifySetupAction(statusResponse -> - InsertCannulaAction.updateCannulaInsertionStatus(podState, statusResponse, aapsLogger), SetupProgress.COMPLETED)) // + InsertCannulaAction.updateCannulaInsertionStatus(podStateManager, statusResponse, aapsLogger), SetupProgress.COMPLETED)) // .observeOn(Schedulers.io()); } public synchronized StatusResponse getPodStatus() { - if (podState == null) { + if (!podStateManager.hasState()) { throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, null); } logStartingCommandExecution("getPodStatus"); try { - return communicationService.executeAction(new GetStatusAction(podState)); + return communicationService.executeAction(new GetStatusAction(podStateManager)); } finally { logCommandExecutionFinished("getPodStatus"); } @@ -153,7 +147,7 @@ public class OmnipodManager { logStartingCommandExecution("getPodInfo"); try { - return communicationService.executeAction(new GetPodInfoAction(podState, podInfoType)); + return communicationService.executeAction(new GetPodInfoAction(podStateManager, podInfoType)); } finally { logCommandExecutionFinished("getPodInfo"); } @@ -165,7 +159,7 @@ public class OmnipodManager { logStartingCommandExecution("acknowledgeAlerts"); try { - return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podState, podState.getActiveAlerts()))); + return executeAndVerify(() -> communicationService.executeAction(new AcknowledgeAlertsAction(podStateManager, podStateManager.getActiveAlerts()))); } finally { logCommandExecutionFinished("acknowledgeAlerts"); } @@ -187,8 +181,8 @@ public class OmnipodManager { try { try { - return executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, schedule, - false, podState.getScheduleOffset(), acknowledgementBeep))); + return executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, schedule, + false, podStateManager.getScheduleOffset(), acknowledgementBeep))); } catch (OmnipodException ex) { // Treat all exceptions as uncertain failures, because all delivery has been suspended here. // Setting this to an uncertain failure will enable for the user to get an appropriate warning @@ -214,9 +208,10 @@ public class OmnipodManager { } try { - return executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction( - podState, rate, duration, + StatusResponse statusResponse = executeAndVerify(() -> communicationService.executeAction(new SetTempBasalAction( + podStateManager, rate, duration, acknowledgementBeep, completionBeep))); + return statusResponse; } catch (OmnipodException ex) { // Treat all exceptions as uncertain failures, because all delivery has been suspended here. // Setting this to an uncertain failure will enable for the user to get an appropriate warning @@ -238,7 +233,7 @@ public class OmnipodManager { try { return executeAndVerify(() -> { - StatusResponse statusResponse = communicationService.executeAction(new CancelDeliveryAction(podState, deliveryTypes, acknowledgementBeep)); + StatusResponse statusResponse = communicationService.executeAction(new CancelDeliveryAction(podStateManager, deliveryTypes, acknowledgementBeep)); aapsLogger.info(LTag.PUMPBTCOMM, "Status response after cancel delivery[types={}]: {}", deliveryTypes.toString(), statusResponse.toString()); return statusResponse; }); @@ -258,7 +253,7 @@ public class OmnipodManager { CommandDeliveryStatus commandDeliveryStatus = CommandDeliveryStatus.SUCCESS; try { - executeAndVerify(() -> communicationService.executeAction(new BolusAction(podState, units, acknowledgementBeep, completionBeep))); + executeAndVerify(() -> communicationService.executeAction(new BolusAction(podStateManager, units, acknowledgementBeep, completionBeep))); } catch (OmnipodException ex) { if (ex.isCertainFailure()) { throw ex; @@ -272,6 +267,7 @@ public class OmnipodManager { } DateTime startDate = DateTime.now().minus(OmnipodConst.AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION); + podStateManager.setLastBolus(startDate, units); CompositeDisposable disposables = new CompositeDisposable(); Duration bolusDuration = calculateBolusDuration(units, OmnipodConst.POD_BOLUS_DELIVERY_RATE); @@ -339,7 +335,7 @@ public class OmnipodManager { synchronized (bolusDataMutex) { if (activeBolusData == null) { - throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podState.getLastDeliveryStatus()); + throw new IllegalDeliveryStatusException(DeliveryStatus.BOLUS_IN_PROGRESS, podStateManager.getLastDeliveryStatus()); } logStartingCommandExecution("cancelBolus [acknowledgementBeep=" + acknowledgementBeep + "]"); @@ -358,8 +354,10 @@ public class OmnipodManager { private void discardActiveBolusData(double unitsNotDelivered) { synchronized (bolusDataMutex) { + double unitsDelivered = activeBolusData.getUnits() - unitsNotDelivered; + podStateManager.setLastBolus(activeBolusData.getStartDate(), unitsDelivered); activeBolusData.getDisposables().dispose(); - activeBolusData.getBolusCompletionSubject().onSuccess(new BolusDeliveryResult(activeBolusData.getUnits() - unitsNotDelivered)); + activeBolusData.getBolusCompletionSubject().onSuccess(new BolusDeliveryResult(unitsDelivered)); activeBolusData = null; } } @@ -374,8 +372,8 @@ public class OmnipodManager { logStartingCommandExecution("resumeDelivery"); try { - return executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podState, podState.getBasalSchedule(), - false, podState.getScheduleOffset(), acknowledgementBeep))); + return executeAndVerify(() -> communicationService.executeAction(new SetBasalScheduleAction(podStateManager, podStateManager.getBasalSchedule(), + false, podStateManager.getScheduleOffset(), acknowledgementBeep))); } finally { logCommandExecutionFinished("resumeDelivery"); } @@ -395,18 +393,18 @@ public class OmnipodManager { throw ex; } - DateTimeZone oldTimeZone = podState.getTimeZone(); + DateTimeZone oldTimeZone = podStateManager.getTimeZone(); try { // Joda seems to cache the default time zone, so we use the JVM's DateTimeZone.setDefault(DateTimeZone.forTimeZone(TimeZone.getDefault())); - podState.setTimeZone(DateTimeZone.getDefault()); + podStateManager.setTimeZone(DateTimeZone.getDefault()); - setBasalSchedule(podState.getBasalSchedule(), acknowledgementBeeps); + setBasalSchedule(podStateManager.getBasalSchedule(), acknowledgementBeeps); } catch (OmnipodException ex) { // Treat all exceptions as uncertain failures, because all delivery has been suspended here. // Setting this to an uncertain failure will enable for the user to get an appropriate warning - podState.setTimeZone(oldTimeZone); + podStateManager.setTimeZone(oldTimeZone); ex.setCertainFailure(false); throw ex; } finally { @@ -415,7 +413,7 @@ public class OmnipodManager { } public synchronized void deactivatePod() { - if (podState == null) { + if (!podStateManager.isPaired()) { throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, null); } @@ -424,7 +422,7 @@ public class OmnipodManager { // Try to get pulse log for diagnostics // FIXME replace by storing to file try { - PodInfoResponse podInfoResponse = communicationService.executeAction(new GetPodInfoAction(podState, PodInfoType.RECENT_PULSE_LOG)); + PodInfoResponse podInfoResponse = communicationService.executeAction(new GetPodInfoAction(podStateManager, PodInfoType.RECENT_PULSE_LOG)); PodInfoRecentPulseLog pulseLogInfo = podInfoResponse.getPodInfo(); aapsLogger.info(LTag.PUMPBTCOMM, "Retrieved pulse log from the pod: {}", pulseLogInfo.toString()); } catch (Exception ex) { @@ -433,20 +431,14 @@ public class OmnipodManager { try { // Always send acknowledgement beeps here. Matches the PDM's behavior - communicationService.executeAction(new DeactivatePodAction(podState, true)); + communicationService.executeAction(new DeactivatePodAction(podStateManager, true)); } catch (PodFaultException ex) { aapsLogger.info(LTag.PUMPBTCOMM, "Ignoring PodFaultException in deactivatePod", ex); } finally { logCommandExecutionFinished("deactivatePod"); } - resetPodState(false); - } - - public void resetPodState(boolean forcedByUser) { - aapsLogger.warn(LTag.PUMPBTCOMM, "resetPodState has been called. forcedByUser={}", forcedByUser); - podState = null; - sp.remove(OmnipodConst.Prefs.PodState); + podStateManager.removeState(); } public OmnipodCommunicationManager getCommunicationService() { @@ -454,11 +446,11 @@ public class OmnipodManager { } public DateTime getTime() { - return podState.getTime(); + return podStateManager.getTime(); } public boolean isReadyForDelivery() { - return podState != null && podState.getSetupProgress() == SetupProgress.COMPLETED; + return podStateManager.isSetupCompleted(); } public boolean hasActiveBolus() { @@ -467,15 +459,6 @@ public class OmnipodManager { } } - // FIXME this is dirty, we should not expose the original pod state - public PodSessionState getPodState() { - return this.podState; - } - - public String getPodStateAsString() { - return podState == null ? "null" : podState.toString(); - } - // Only works for commands with nonce resyncable message blocks // FIXME method is too big, needs refactoring private StatusResponse executeAndVerify(VerifiableAction runnable) { @@ -489,8 +472,8 @@ public class OmnipodManager { try { logStartingCommandExecution("verifyCommand"); - StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podState, - new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.NO_BEEP, DeliveryType.NONE), false); + StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podStateManager, + new CancelDeliveryCommand(podStateManager.getCurrentNonce(), BeepType.NO_BEEP, DeliveryType.NONE), false); aapsLogger.info(LTag.PUMPBTCOMM, "Command status resolved to SUCCESS. Status response after cancelDelivery[types=DeliveryType.NONE]: {}", statusResponse); return statusResponse; @@ -517,7 +500,7 @@ public class OmnipodManager { private void assertReadyForDelivery() { if (!isReadyForDelivery()) { - throw new IllegalSetupProgressException(SetupProgress.COMPLETED, podState == null ? null : podState.getSetupProgress()); + throw new IllegalSetupProgressException(SetupProgress.COMPLETED, !podStateManager.hasState() ? null : podStateManager.getSetupProgress()); } } @@ -525,15 +508,15 @@ public class OmnipodManager { SetupActionResult result = null; for (int i = 0; ACTION_VERIFICATION_TRIES > i; i++) { try { - StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podState)); + StatusResponse delayedStatusResponse = communicationService.executeAction(new GetStatusAction(podStateManager)); setupActionResponseHandler.accept(delayedStatusResponse); - if (podState.getSetupProgress().equals(expectedSetupProgress)) { + if (podStateManager.getSetupProgress().equals(expectedSetupProgress)) { result = new SetupActionResult(SetupActionResult.ResultType.SUCCESS); break; } else { result = new SetupActionResult(SetupActionResult.ResultType.FAILURE) // - .setupProgress(podState.getSetupProgress()); + .setupProgress(podStateManager.getSetupProgress()); break; } } catch (Exception ex) { @@ -564,15 +547,6 @@ public class OmnipodManager { return ex instanceof OmnipodException && ((OmnipodException) ex).isCertainFailure(); } - public static int generateRandomAddress() { - // Create random address with 20 bits to match PDM, could easily use 24 bits instead - return 0x1f000000 | (new Random().nextInt() & 0x000fffff); - } - - public static boolean isValidAddress(int address) { - return (0x1f000000 | (address & 0x000fffff)) == address; - } - public static class BolusCommandResult { private final CommandDeliveryStatus commandDeliveryStatus; private final SingleSubject deliveryResultSubject; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AcknowledgeAlertsAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AcknowledgeAlertsAction.java index facdb4b2d5..3ffbc5942f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AcknowledgeAlertsAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AcknowledgeAlertsAction.java @@ -3,37 +3,37 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action; import java.util.Collections; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.AcknowledgeAlertsCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class AcknowledgeAlertsAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final AlertSet alerts; - public AcknowledgeAlertsAction(PodSessionState podState, AlertSet alerts) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + public AcknowledgeAlertsAction(PodStateManager podStateManager, AlertSet alerts) { + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (alerts == null) { throw new ActionInitializationException("Alert set can not be null"); } else if (alerts.size() == 0) { throw new ActionInitializationException("Alert set can not be empty"); } - this.podState = podState; + this.podStateManager = podStateManager; this.alerts = alerts; } - public AcknowledgeAlertsAction(PodSessionState podState, AlertSlot alertSlot) { - this(podState, new AlertSet(Collections.singletonList(alertSlot))); + public AcknowledgeAlertsAction(PodStateManager podStateManager, AlertSlot alertSlot) { + this(podStateManager, new AlertSet(Collections.singletonList(alertSlot))); } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - return communicationService.sendCommand(StatusResponse.class, podState, - new AcknowledgeAlertsCommand(podState.getCurrentNonce(), alerts)); + return communicationService.sendCommand(StatusResponse.class, podStateManager, + new AcknowledgeAlertsCommand(podStateManager.getCurrentNonce(), alerts)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java index b5e46e38b5..0637a75872 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/AssignAddressAction.java @@ -3,6 +3,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action; import org.joda.time.DateTimeZone; import java.util.Collections; +import java.util.Random; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalMessageAddressException; @@ -10,45 +11,51 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalVer import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.AssignAddressCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.VersionResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSetupState; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateChangedHandler; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; -public class AssignAddressAction implements OmnipodAction { - private final int address; - private final PodStateChangedHandler podStateChangedHandler; +public class AssignAddressAction implements OmnipodAction { + private final PodStateManager podStateManager; - public AssignAddressAction(PodStateChangedHandler podStateChangedHandler, int address) { - this.address = address; - this.podStateChangedHandler = podStateChangedHandler; + public AssignAddressAction(PodStateManager podStateManager) { + if (podStateManager == null) { + throw new IllegalArgumentException("podStateManager can not be null"); + } + this.podStateManager = podStateManager; } @Override - public PodSessionState execute(OmnipodCommunicationManager communicationService) { - PodSetupState setupState = new PodSetupState(address, 0x00, 0x00); + public VersionResponse execute(OmnipodCommunicationManager communicationService) { + if (!podStateManager.hasState()) { + podStateManager.initState(generateRandomAddress()); + } + if (podStateManager.isPaired()) { + throw new IllegalStateException("podStateManager already has a paired Pod"); + } - AssignAddressCommand assignAddress = new AssignAddressCommand(setupState.getAddress()); + AssignAddressCommand assignAddress = new AssignAddressCommand(podStateManager.getAddress()); OmnipodMessage assignAddressMessage = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS, - Collections.singletonList(assignAddress), setupState.getMessageNumber()); + Collections.singletonList(assignAddress), podStateManager.getMessageNumber()); - VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, setupState, assignAddressMessage, - OmnipodConst.DEFAULT_ADDRESS, setupState.getAddress()); + VersionResponse assignAddressResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, assignAddressMessage, + OmnipodConst.DEFAULT_ADDRESS, podStateManager.getAddress()); if (!assignAddressResponse.isAssignAddressVersionResponse()) { throw new IllegalVersionResponseTypeException("assignAddress", "setupPod"); } - if (assignAddressResponse.getAddress() != address) { - throw new IllegalMessageAddressException(address, assignAddressResponse.getAddress()); + if (assignAddressResponse.getAddress() != podStateManager.getAddress()) { + throw new IllegalMessageAddressException(podStateManager.getAddress(), assignAddressResponse.getAddress()); } - DateTimeZone timeZone = DateTimeZone.getDefault(); + podStateManager.setPairingParameters(assignAddressResponse.getLot(), assignAddressResponse.getTid(), // + assignAddressResponse.getPiVersion(), assignAddressResponse.getPmVersion(), DateTimeZone.getDefault()); - PodSessionState podState = new PodSessionState(timeZone, address, assignAddressResponse.getPiVersion(), - assignAddressResponse.getPmVersion(), assignAddressResponse.getLot(), assignAddressResponse.getTid(), - setupState.getPacketNumber(), 0x00, communicationService.injector); // At this point, for an unknown reason, the pod starts counting messages from 0 again + return assignAddressResponse; + } - podState.setStateChangedHandler(podStateChangedHandler); - return podState; + + private static int generateRandomAddress() { + // Create random address with 20 bits to match PDM, could easily use 24 bits instead + return 0x1f000000 | (new Random().nextInt() & 0x000fffff); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/BolusAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/BolusAction.java index 14cee38962..c57d2b3615 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/BolusAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/BolusAction.java @@ -5,49 +5,49 @@ import org.joda.time.Duration; import java.util.Arrays; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.BolusExtraCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BolusDeliverySchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class BolusAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final double units; private final Duration timeBetweenPulses; private final boolean acknowledgementBeep; private final boolean completionBeep; - public BolusAction(PodSessionState podState, double units, Duration timeBetweenPulses, + public BolusAction(PodStateManager podStateManager, double units, Duration timeBetweenPulses, boolean acknowledgementBeep, boolean completionBeep) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (timeBetweenPulses == null) { throw new ActionInitializationException("Time between pulses cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.units = units; this.timeBetweenPulses = timeBetweenPulses; this.acknowledgementBeep = acknowledgementBeep; this.completionBeep = completionBeep; } - public BolusAction(PodSessionState podState, double units, boolean acknowledgementBeep, boolean completionBeep) { - this(podState, units, Duration.standardSeconds(2), acknowledgementBeep, completionBeep); + public BolusAction(PodStateManager podStateManager, double units, boolean acknowledgementBeep, boolean completionBeep) { + this(podStateManager, units, Duration.standardSeconds(2), acknowledgementBeep, completionBeep); } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { BolusDeliverySchedule bolusDeliverySchedule = new BolusDeliverySchedule(units, timeBetweenPulses); SetInsulinScheduleCommand setInsulinScheduleCommand = new SetInsulinScheduleCommand( - podState.getCurrentNonce(), bolusDeliverySchedule); + podStateManager.getCurrentNonce(), bolusDeliverySchedule); BolusExtraCommand bolusExtraCommand = new BolusExtraCommand(units, timeBetweenPulses, acknowledgementBeep, completionBeep); - OmnipodMessage primeBolusMessage = new OmnipodMessage(podState.getAddress(), - Arrays.asList(setInsulinScheduleCommand, bolusExtraCommand), podState.getMessageNumber()); - return communicationService.exchangeMessages(StatusResponse.class, podState, primeBolusMessage); + OmnipodMessage primeBolusMessage = new OmnipodMessage(podStateManager.getAddress(), + Arrays.asList(setInsulinScheduleCommand, bolusExtraCommand), podStateManager.getMessageNumber()); + return communicationService.exchangeMessages(StatusResponse.class, podStateManager, primeBolusMessage); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/CancelDeliveryAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/CancelDeliveryAction.java index ca713bcab6..c29135a24f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/CancelDeliveryAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/CancelDeliveryAction.java @@ -5,29 +5,29 @@ import java.util.EnumSet; import java.util.List; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.CancelDeliveryCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.BeepType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class CancelDeliveryAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final EnumSet deliveryTypes; private final boolean acknowledgementBeep; - public CancelDeliveryAction(PodSessionState podState, EnumSet deliveryTypes, + public CancelDeliveryAction(PodStateManager podStateManager, EnumSet deliveryTypes, boolean acknowledgementBeep) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (deliveryTypes == null) { throw new ActionInitializationException("Delivery types cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.deliveryTypes = deliveryTypes; this.acknowledgementBeep = acknowledgementBeep; } @@ -43,14 +43,18 @@ public class CancelDeliveryAction implements OmnipodAction { EnumSet deliveryTypeWithBeep = EnumSet.of(deliveryTypeList.remove(deliveryTypeList.size() - 1)); EnumSet deliveryTypesWithoutBeep = EnumSet.copyOf(deliveryTypeList); - messageBlocks.add(new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.NO_BEEP, deliveryTypesWithoutBeep)); - messageBlocks.add(new CancelDeliveryCommand(podState.getCurrentNonce(), BeepType.BEEP, deliveryTypeWithBeep)); + messageBlocks.add(new CancelDeliveryCommand(podStateManager.getCurrentNonce(), BeepType.NO_BEEP, deliveryTypesWithoutBeep)); + messageBlocks.add(new CancelDeliveryCommand(podStateManager.getCurrentNonce(), BeepType.BEEP, deliveryTypeWithBeep)); } else { - messageBlocks.add(new CancelDeliveryCommand(podState.getCurrentNonce(), + messageBlocks.add(new CancelDeliveryCommand(podStateManager.getCurrentNonce(), acknowledgementBeep && deliveryTypes.size() == 1 ? BeepType.BEEP : BeepType.NO_BEEP, deliveryTypes)); } - return communicationService.exchangeMessages(StatusResponse.class, podState, - new OmnipodMessage(podState.getAddress(), messageBlocks, podState.getMessageNumber())); + StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podStateManager, + new OmnipodMessage(podStateManager.getAddress(), messageBlocks, podStateManager.getMessageNumber())); + if (deliveryTypes.contains(DeliveryType.TEMP_BASAL)) { + podStateManager.setLastTempBasal(null, null, null); + } + return statusResponse; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigureAlertsAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigureAlertsAction.java index b44fc092a8..e5f93e97f3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigureAlertsAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/ConfigureAlertsAction.java @@ -3,33 +3,33 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action; import java.util.List; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.ConfigureAlertsCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class ConfigureAlertsAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final List alertConfigurations; - public ConfigureAlertsAction(PodSessionState podState, List alertConfigurations) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + public ConfigureAlertsAction(PodStateManager podStateManager, List alertConfigurations) { + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (alertConfigurations == null) { throw new ActionInitializationException("Alert configurations cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.alertConfigurations = alertConfigurations; } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand(podState.getCurrentNonce(), alertConfigurations); - StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podState, configureAlertsCommand); + ConfigureAlertsCommand configureAlertsCommand = new ConfigureAlertsCommand(podStateManager.getCurrentNonce(), alertConfigurations); + StatusResponse statusResponse = communicationService.sendCommand(StatusResponse.class, podStateManager, configureAlertsCommand); for (AlertConfiguration alertConfiguration : alertConfigurations) { - podState.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType()); + podStateManager.putConfiguredAlert(alertConfiguration.getAlertSlot(), alertConfiguration.getAlertType()); } return statusResponse; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/DeactivatePodAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/DeactivatePodAction.java index 01162ef434..7d1645c473 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/DeactivatePodAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/DeactivatePodAction.java @@ -3,36 +3,36 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action; import java.util.EnumSet; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.DeactivatePodCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodFaultException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class DeactivatePodAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final boolean acknowledgementBeep; - public DeactivatePodAction(PodSessionState podState, boolean acknowledgementBeep) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + public DeactivatePodAction(PodStateManager podStateManager, boolean acknowledgementBeep) { + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.acknowledgementBeep = acknowledgementBeep; } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - if (!podState.isSuspended() && !podState.hasFaultEvent()) { + if (!podStateManager.isSuspended() && !podStateManager.hasFaultEvent()) { try { - communicationService.executeAction(new CancelDeliveryAction(podState, + communicationService.executeAction(new CancelDeliveryAction(podStateManager, EnumSet.allOf(DeliveryType.class), acknowledgementBeep)); - } catch(PodFaultException ex) { + } catch (PodFaultException ex) { // Ignore } } - return communicationService.sendCommand(StatusResponse.class, podState, new DeactivatePodCommand(podState.getCurrentNonce())); + return communicationService.sendCommand(StatusResponse.class, podStateManager, new DeactivatePodCommand(podStateManager.getCurrentNonce())); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetPodInfoAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetPodInfoAction.java index 0eef011607..a082ca47d8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetPodInfoAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetPodInfoAction.java @@ -1,29 +1,29 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.GetStatusCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class GetPodInfoAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final PodInfoType podInfoType; - public GetPodInfoAction(PodSessionState podState, PodInfoType podInfoType) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + public GetPodInfoAction(PodStateManager podStateManager, PodInfoType podInfoType) { + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (podInfoType == null) { throw new ActionInitializationException("Pod info type cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.podInfoType = podInfoType; } @Override public PodInfoResponse execute(OmnipodCommunicationManager communicationService) { - return communicationService.sendCommand(PodInfoResponse.class, podState, new GetStatusCommand(podInfoType)); + return communicationService.sendCommand(PodInfoResponse.class, podStateManager, new GetStatusCommand(podInfoType)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetStatusAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetStatusAction.java index dfcc1fe043..35431cea8b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetStatusAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/GetStatusAction.java @@ -4,21 +4,21 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunication import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.GetStatusCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class GetStatusAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; - public GetStatusAction(PodSessionState podState) { + public GetStatusAction(PodStateManager podState) { if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + throw new ActionInitializationException("Pod state manager cannot be null"); } - this.podState = podState; + this.podStateManager = podState; } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - return communicationService.sendCommand(StatusResponse.class, podState, new GetStatusCommand(PodInfoType.NORMAL)); + return communicationService.sendCommand(StatusResponse.class, podStateManager, new GetStatusCommand(PodInfoType.NORMAL)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/InsertCannulaAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/InsertCannulaAction.java index 9a433ab86a..c8da669fb8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/InsertCannulaAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/InsertCannulaAction.java @@ -9,63 +9,63 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSet import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class InsertCannulaAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final InsertCannulaService service; private final BasalSchedule initialBasalSchedule; - public InsertCannulaAction(InsertCannulaService insertCannulaService, PodSessionState podState, BasalSchedule initialBasalSchedule) { + public InsertCannulaAction(InsertCannulaService insertCannulaService, PodStateManager podStateManager, BasalSchedule initialBasalSchedule) { if (insertCannulaService == null) { throw new ActionInitializationException("Insert cannula service cannot be null"); } - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (initialBasalSchedule == null) { throw new ActionInitializationException("Initial basal schedule cannot be null"); } this.service = insertCannulaService; - this.podState = podState; + this.podStateManager = podStateManager; this.initialBasalSchedule = initialBasalSchedule; } - public static void updateCannulaInsertionStatus(PodSessionState podState, StatusResponse statusResponse, AAPSLogger aapsLogger) { - if (podState.getSetupProgress().equals(SetupProgress.CANNULA_INSERTING) && + public static void updateCannulaInsertionStatus(PodStateManager podStateManager, StatusResponse statusResponse, AAPSLogger aapsLogger) { + if (podStateManager.getSetupProgress().equals(SetupProgress.CANNULA_INSERTING) && statusResponse.getPodProgressStatus().isReadyForDelivery()) { aapsLogger.debug(LTag.PUMPBTCOMM, "Updating SetupProgress from CANNULA_INSERTING to COMPLETED"); - podState.setSetupProgress(SetupProgress.COMPLETED); + podStateManager.setSetupProgress(SetupProgress.COMPLETED); } } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - if (podState.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { - throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, podState.getSetupProgress()); + if (!podStateManager.isPaired() || podStateManager.getSetupProgress().isBefore(SetupProgress.PRIMING_FINISHED)) { + throw new IllegalSetupProgressException(SetupProgress.PRIMING_FINISHED, podStateManager.getSetupProgress()); } - if (podState.getSetupProgress().isBefore(SetupProgress.INITIAL_BASAL_SCHEDULE_SET)) { - service.programInitialBasalSchedule(communicationService, podState, initialBasalSchedule); - podState.setSetupProgress(SetupProgress.INITIAL_BASAL_SCHEDULE_SET); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.INITIAL_BASAL_SCHEDULE_SET)) { + service.programInitialBasalSchedule(communicationService, podStateManager, initialBasalSchedule); + podStateManager.setSetupProgress(SetupProgress.INITIAL_BASAL_SCHEDULE_SET); } - if (podState.getSetupProgress().isBefore(SetupProgress.STARTING_INSERT_CANNULA)) { - service.executeExpirationRemindersAlertCommand(communicationService, podState); - podState.setSetupProgress(SetupProgress.STARTING_INSERT_CANNULA); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.STARTING_INSERT_CANNULA)) { + service.executeExpirationRemindersAlertCommand(communicationService, podStateManager); + podStateManager.setSetupProgress(SetupProgress.STARTING_INSERT_CANNULA); } - if (podState.getSetupProgress().isBefore(SetupProgress.CANNULA_INSERTING)) { - StatusResponse statusResponse = service.executeInsertionBolusCommand(communicationService, podState); - podState.setSetupProgress(SetupProgress.CANNULA_INSERTING); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.CANNULA_INSERTING)) { + StatusResponse statusResponse = service.executeInsertionBolusCommand(communicationService, podStateManager); + podStateManager.setSetupProgress(SetupProgress.CANNULA_INSERTING); return statusResponse; - } else if (podState.getSetupProgress().equals(SetupProgress.CANNULA_INSERTING)) { + } else if (podStateManager.getSetupProgress().equals(SetupProgress.CANNULA_INSERTING)) { // Check status - StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podState)); - updateCannulaInsertionStatus(podState, statusResponse, communicationService.aapsLogger); + StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podStateManager)); + updateCannulaInsertionStatus(podStateManager, statusResponse, communicationService.aapsLogger); return statusResponse; } else { - throw new IllegalSetupProgressException(null, podState.getSetupProgress()); + throw new IllegalSetupProgressException(null, podStateManager.getSetupProgress()); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java index 380eb0ce3d..a3056ac8a3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/PrimeAction.java @@ -9,53 +9,53 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.IllegalSet import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class PrimeAction implements OmnipodAction { private final PrimeService service; - private final PodSessionState podState; + private final PodStateManager podStateManager; - public PrimeAction(PrimeService primeService, PodSessionState podState) { + public PrimeAction(PrimeService primeService, PodStateManager podStateManager) { if (primeService == null) { throw new ActionInitializationException("Prime service cannot be null"); } - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } this.service = primeService; - this.podState = podState; + this.podStateManager = podStateManager; } - public static void updatePrimingStatus(PodSessionState podState, StatusResponse statusResponse, AAPSLogger aapsLogger) { - if (podState.getSetupProgress().equals(SetupProgress.PRIMING) && statusResponse.getPodProgressStatus().equals(PodProgressStatus.PRIMING_COMPLETED)) { + public static void updatePrimingStatus(PodStateManager podStateManager, StatusResponse statusResponse, AAPSLogger aapsLogger) { + if (podStateManager.getSetupProgress().equals(SetupProgress.PRIMING) && statusResponse.getPodProgressStatus().equals(PodProgressStatus.PRIMING_COMPLETED)) { aapsLogger.debug(LTag.PUMPBTCOMM, "Updating SetupProgress from PRIMING to PRIMING_FINISHED"); - podState.setSetupProgress(SetupProgress.PRIMING_FINISHED); + podStateManager.setSetupProgress(SetupProgress.PRIMING_FINISHED); } } @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - if (podState.getSetupProgress().isBefore(SetupProgress.POD_CONFIGURED)) { - throw new IllegalSetupProgressException(SetupProgress.POD_CONFIGURED, podState.getSetupProgress()); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.POD_CONFIGURED)) { + throw new IllegalSetupProgressException(SetupProgress.POD_CONFIGURED, podStateManager.getSetupProgress()); } - if (podState.getSetupProgress().isBefore(SetupProgress.STARTING_PRIME)) { - service.executeDisableTab5Sub16FaultConfigCommand(communicationService, podState); - service.executeFinishSetupReminderAlertCommand(communicationService, podState); - podState.setSetupProgress(SetupProgress.STARTING_PRIME); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.STARTING_PRIME)) { + service.executeDisableTab5Sub16FaultConfigCommand(communicationService, podStateManager); + service.executeFinishSetupReminderAlertCommand(communicationService, podStateManager); + podStateManager.setSetupProgress(SetupProgress.STARTING_PRIME); } - if (podState.getSetupProgress().isBefore(SetupProgress.PRIMING)) { - StatusResponse statusResponse = service.executePrimeBolusCommand(communicationService, podState); - podState.setSetupProgress(SetupProgress.PRIMING); + if (podStateManager.getSetupProgress().isBefore(SetupProgress.PRIMING)) { + StatusResponse statusResponse = service.executePrimeBolusCommand(communicationService, podStateManager); + podStateManager.setSetupProgress(SetupProgress.PRIMING); return statusResponse; - } else if (podState.getSetupProgress().equals(SetupProgress.PRIMING)) { + } else if (podStateManager.getSetupProgress().equals(SetupProgress.PRIMING)) { // Check status - StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podState)); - updatePrimingStatus(podState, statusResponse, communicationService.aapsLogger); + StatusResponse statusResponse = communicationService.executeAction(new GetStatusAction(podStateManager)); + updatePrimingStatus(podStateManager, statusResponse, communicationService.aapsLogger); return statusResponse; } else { - throw new IllegalSetupProgressException(null, podState.getSetupProgress()); + throw new IllegalSetupProgressException(null, podStateManager.getSetupProgress()); } } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetBasalScheduleAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetBasalScheduleAction.java index 0c8ae7f8be..1a4fd91237 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetBasalScheduleAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetBasalScheduleAction.java @@ -5,25 +5,25 @@ import org.joda.time.Duration; import java.util.Arrays; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.BasalScheduleExtraCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; public class SetBasalScheduleAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final BasalSchedule basalSchedule; private final boolean confidenceReminder; private final Duration scheduleOffset; private final boolean acknowledgementBeep; - public SetBasalScheduleAction(PodSessionState podState, BasalSchedule basalSchedule, + public SetBasalScheduleAction(PodStateManager podStateManager, BasalSchedule basalSchedule, boolean confidenceReminder, Duration scheduleOffset, boolean acknowledgementBeep) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (basalSchedule == null) { throw new ActionInitializationException("Basal schedule cannot be null"); @@ -31,7 +31,7 @@ public class SetBasalScheduleAction implements OmnipodAction { if (scheduleOffset == null) { throw new ActionInitializationException("Schedule offset cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.basalSchedule = basalSchedule; this.confidenceReminder = confidenceReminder; this.scheduleOffset = scheduleOffset; @@ -40,14 +40,14 @@ public class SetBasalScheduleAction implements OmnipodAction { @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { - SetInsulinScheduleCommand setBasal = new SetInsulinScheduleCommand(podState.getCurrentNonce(), basalSchedule, scheduleOffset); + SetInsulinScheduleCommand setBasal = new SetInsulinScheduleCommand(podStateManager.getCurrentNonce(), basalSchedule, scheduleOffset); BasalScheduleExtraCommand extraCommand = new BasalScheduleExtraCommand(basalSchedule, scheduleOffset, acknowledgementBeep, confidenceReminder, Duration.ZERO); - OmnipodMessage basalMessage = new OmnipodMessage(podState.getAddress(), Arrays.asList(setBasal, extraCommand), - podState.getMessageNumber()); + OmnipodMessage basalMessage = new OmnipodMessage(podStateManager.getAddress(), Arrays.asList(setBasal, extraCommand), + podStateManager.getMessageNumber()); - StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podState, basalMessage); - podState.setBasalSchedule(basalSchedule); + StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podStateManager, basalMessage); + podStateManager.setBasalSchedule(basalSchedule); return statusResponse; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetTempBasalAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetTempBasalAction.java index d9406a3ed7..0610256d81 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetTempBasalAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetTempBasalAction.java @@ -1,35 +1,37 @@ package info.nightscout.androidaps.plugins.pump.omnipod.comm.action; +import org.joda.time.DateTime; import org.joda.time.Duration; import java.util.Arrays; import java.util.List; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.MessageBlock; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.OmnipodMessage; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.SetInsulinScheduleCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.TempBasalExtraCommand; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.ActionInitializationException; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; +import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; public class SetTempBasalAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; private final double rate; private final Duration duration; private final boolean acknowledgementBeep; private final boolean completionBeep; - public SetTempBasalAction(PodSessionState podState, double rate, Duration duration, + public SetTempBasalAction(PodStateManager podStateManager, double rate, Duration duration, boolean acknowledgementBeep, boolean completionBeep) { - if (podState == null) { - throw new ActionInitializationException("Pod state cannot be null"); + if (podStateManager == null) { + throw new ActionInitializationException("Pod state manager cannot be null"); } if (duration == null) { throw new ActionInitializationException("Duration cannot be null"); } - this.podState = podState; + this.podStateManager = podStateManager; this.rate = rate; this.duration = duration; this.acknowledgementBeep = acknowledgementBeep; @@ -39,10 +41,12 @@ public class SetTempBasalAction implements OmnipodAction { @Override public StatusResponse execute(OmnipodCommunicationManager communicationService) { List messageBlocks = Arrays.asList( // - new SetInsulinScheduleCommand(podState.getCurrentNonce(), rate, duration), + new SetInsulinScheduleCommand(podStateManager.getCurrentNonce(), rate, duration), new TempBasalExtraCommand(rate, duration, acknowledgementBeep, completionBeep, Duration.ZERO)); - OmnipodMessage message = new OmnipodMessage(podState.getAddress(), messageBlocks, podState.getMessageNumber()); - return communicationService.exchangeMessages(StatusResponse.class, podState, message); + OmnipodMessage message = new OmnipodMessage(podStateManager.getAddress(), messageBlocks, podStateManager.getMessageNumber()); + StatusResponse statusResponse = communicationService.exchangeMessages(StatusResponse.class, podStateManager, message); + podStateManager.setLastTempBasal(new DateTime().minus(OmnipodConst.AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION), rate, duration); + return statusResponse; } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java index 52979c91f3..a2ef13e488 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/SetupPodAction.java @@ -16,35 +16,38 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.Ver import info.nightscout.androidaps.plugins.pump.omnipod.defs.PacketType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodProgressStatus; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; public class SetupPodAction implements OmnipodAction { - private final PodSessionState podState; + private final PodStateManager podStateManager; - public SetupPodAction(PodSessionState podState) { - this.podState = podState; + public SetupPodAction(PodStateManager podStateManager) { + if(podStateManager == null) { + throw new IllegalArgumentException("Pod state manager can not be null"); + } + this.podStateManager = podStateManager; } @Override public VersionResponse execute(OmnipodCommunicationManager communicationService) { - if (!podState.getSetupProgress().equals(SetupProgress.ADDRESS_ASSIGNED)) { - throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, podState.getSetupProgress()); + if (!podStateManager.getSetupProgress().equals(SetupProgress.ADDRESS_ASSIGNED)) { + throw new IllegalSetupProgressException(SetupProgress.ADDRESS_ASSIGNED, podStateManager.getSetupProgress()); } - DateTime activationDate = DateTime.now(podState.getTimeZone()); + DateTime activationDate = DateTime.now(podStateManager.getTimeZone()); - SetupPodCommand setupPodCommand = new SetupPodCommand(podState.getAddress(), activationDate, - podState.getLot(), podState.getTid()); + SetupPodCommand setupPodCommand = new SetupPodCommand(podStateManager.getAddress(), activationDate, + podStateManager.getLot(), podStateManager.getTid()); OmnipodMessage message = new OmnipodMessage(OmnipodConst.DEFAULT_ADDRESS, - Collections.singletonList(setupPodCommand), podState.getMessageNumber()); + Collections.singletonList(setupPodCommand), podStateManager.getMessageNumber()); VersionResponse setupPodResponse; try { - setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podState, - message, OmnipodConst.DEFAULT_ADDRESS, podState.getAddress()); + setupPodResponse = communicationService.exchangeMessages(VersionResponse.class, podStateManager, + message, OmnipodConst.DEFAULT_ADDRESS, podStateManager.getAddress()); } catch (IllegalPacketTypeException ex) { if (PacketType.ACK.equals(ex.getActual())) { // Pod is already configured - podState.setSetupProgress(SetupProgress.POD_CONFIGURED); + podStateManager.setSetupProgress(SetupProgress.POD_CONFIGURED); return null; } throw ex; @@ -53,14 +56,14 @@ public class SetupPodAction implements OmnipodAction { if (!setupPodResponse.isSetupPodVersionResponse()) { throw new IllegalVersionResponseTypeException("setupPod", "assignAddress"); } - if (setupPodResponse.getAddress() != podState.getAddress()) { - throw new IllegalMessageAddressException(podState.getAddress(), setupPodResponse.getAddress()); + if (setupPodResponse.getAddress() != podStateManager.getAddress()) { + throw new IllegalMessageAddressException(podStateManager.getAddress(), setupPodResponse.getAddress()); } if (setupPodResponse.getPodProgressStatus() != PodProgressStatus.PAIRING_COMPLETED) { throw new IllegalPodProgressException(PodProgressStatus.PAIRING_COMPLETED, setupPodResponse.getPodProgressStatus()); } - podState.setSetupProgress(SetupProgress.POD_CONFIGURED); + podStateManager.setSetupProgress(SetupProgress.POD_CONFIGURED); return setupPodResponse; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/InsertCannulaService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/InsertCannulaService.java index b897e448c8..61c786eeca 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/InsertCannulaService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/InsertCannulaService.java @@ -14,21 +14,21 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.Sta import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfigurationFactory; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; public class InsertCannulaService { public StatusResponse programInitialBasalSchedule(OmnipodCommunicationManager communicationService, - PodSessionState podState, BasalSchedule basalSchedule) { - return communicationService.executeAction(new SetBasalScheduleAction(podState, basalSchedule, - true, podState.getScheduleOffset(), false)); + PodStateManager podStateManager, BasalSchedule basalSchedule) { + return communicationService.executeAction(new SetBasalScheduleAction(podStateManager, basalSchedule, + true, podStateManager.getScheduleOffset(), false)); } public StatusResponse executeExpirationRemindersAlertCommand(OmnipodCommunicationManager communicationService, - PodSessionState podState) { + PodStateManager podStateManager) { AlertConfiguration lowReservoirAlertConfiguration = AlertConfigurationFactory.createLowReservoirAlertConfiguration(OmnipodConst.LOW_RESERVOIR_ALERT); - DateTime endOfServiceTime = podState.getActivatedAt().plus(OmnipodConst.SERVICE_DURATION); + DateTime endOfServiceTime = podStateManager.getActivatedAt().plus(OmnipodConst.SERVICE_DURATION); Duration timeUntilExpirationAdvisoryAlarm = new Duration(DateTime.now(), endOfServiceTime.minus(OmnipodConst.EXPIRATION_ADVISORY_WINDOW)); @@ -49,11 +49,11 @@ public class InsertCannulaService { autoOffAlertConfiguration // ); - return new ConfigureAlertsAction(podState, alertConfigurations).execute(communicationService); + return new ConfigureAlertsAction(podStateManager, alertConfigurations).execute(communicationService); } - public StatusResponse executeInsertionBolusCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) { - return communicationService.executeAction(new BolusAction(podState, OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS, + public StatusResponse executeInsertionBolusCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) { + return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConst.POD_CANNULA_INSERTION_BOLUS_UNITS, Duration.standardSeconds(1), false, false)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/PrimeService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/PrimeService.java index 3fc7663398..d8726be029 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/PrimeService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/comm/action/service/PrimeService.java @@ -12,26 +12,26 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.command.Faul import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfiguration; import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertConfigurationFactory; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; public class PrimeService { - public StatusResponse executeDisableTab5Sub16FaultConfigCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) { - FaultConfigCommand faultConfigCommand = new FaultConfigCommand(podState.getCurrentNonce(), (byte) 0x00, (byte) 0x00); - OmnipodMessage faultConfigMessage = new OmnipodMessage(podState.getAddress(), - Collections.singletonList(faultConfigCommand), podState.getMessageNumber()); - return communicationService.exchangeMessages(StatusResponse.class, podState, faultConfigMessage); + public StatusResponse executeDisableTab5Sub16FaultConfigCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) { + FaultConfigCommand faultConfigCommand = new FaultConfigCommand(podStateManager.getCurrentNonce(), (byte) 0x00, (byte) 0x00); + OmnipodMessage faultConfigMessage = new OmnipodMessage(podStateManager.getAddress(), + Collections.singletonList(faultConfigCommand), podStateManager.getMessageNumber()); + return communicationService.exchangeMessages(StatusResponse.class, podStateManager, faultConfigMessage); } - public StatusResponse executeFinishSetupReminderAlertCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) { + public StatusResponse executeFinishSetupReminderAlertCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) { AlertConfiguration finishSetupReminderAlertConfiguration = AlertConfigurationFactory.createFinishSetupReminderAlertConfiguration(); - return communicationService.executeAction(new ConfigureAlertsAction(podState, + return communicationService.executeAction(new ConfigureAlertsAction(podStateManager, Collections.singletonList(finishSetupReminderAlertConfiguration))); } - public StatusResponse executePrimeBolusCommand(OmnipodCommunicationManager communicationService, PodSessionState podState) { - return communicationService.executeAction(new BolusAction(podState, OmnipodConst.POD_PRIME_BOLUS_UNITS, + public StatusResponse executePrimeBolusCommand(OmnipodCommunicationManager communicationService, PodStateManager podStateManager) { + return communicationService.executeAction(new BolusAction(podStateManager, OmnipodConst.POD_PRIME_BOLUS_UNITS, Duration.standardSeconds(1), false, false)); } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/AlertSet.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/AlertSet.java index 9d65d7d5aa..91590e2f12 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/AlertSet.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/AlertSet.java @@ -15,8 +15,12 @@ public class AlertSet { } } + public AlertSet(AlertSet alertSet) { + this(alertSet == null ? new ArrayList<>() : alertSet.getAlertSlots()); + } + public AlertSet(List alertSlots) { - this.alertSlots = alertSlots; + this.alertSlots = alertSlots == null ? new ArrayList<>() : new ArrayList<>(alertSlots); } public List getAlertSlots() { diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommunicationManagerInterface.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommunicationManagerInterface.java index 3999cd2923..d345a3c385 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommunicationManagerInterface.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/OmnipodCommunicationManagerInterface.java @@ -71,9 +71,5 @@ public interface OmnipodCommunicationManagerInterface { */ PumpEnactResult setTime(); - - void setPumpStatus(OmnipodPumpStatus pumpStatusLocal); - - PodInfoRecentPulseLog readPulseLog(); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSessionState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSessionState.java deleted file mode 100644 index 64cb92e84b..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSessionState.java +++ /dev/null @@ -1,299 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; - -import com.google.gson.Gson; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; -import org.joda.time.Duration; - -import java.util.HashMap; -import java.util.Map; - -import javax.inject.Inject; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FirmwareVersion; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.NonceState; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; -import info.nightscout.androidaps.plugins.pump.omnipod.util.OmniCRC; -import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; -import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil; -import info.nightscout.androidaps.utils.DateUtil; -import info.nightscout.androidaps.utils.sharedPreferences.SP; - - -public class PodSessionState extends PodState { - - @Inject transient AAPSLogger aapsLogger; - @Inject transient SP sp; - @Inject transient OmnipodUtil omnipodUtil; - - private transient PodStateChangedHandler stateChangedHandler; - - private final Map configuredAlerts; - private DateTimeZone timeZone; - private DateTime activatedAt; - private DateTime expiresAt; - private final FirmwareVersion piVersion; - private final FirmwareVersion pmVersion; - private final int lot; - private final int tid; - private Double reservoirLevel; - private boolean suspended; - private NonceState nonceState; - private SetupProgress setupProgress; - private AlertSet activeAlerts; - private BasalSchedule basalSchedule; - private DeliveryStatus lastDeliveryStatus; - - public PodSessionState(DateTimeZone timeZone, int address, FirmwareVersion piVersion, - FirmwareVersion pmVersion, int lot, int tid, int packetNumber, int messageNumber, HasAndroidInjector injector) { - super(address, messageNumber, packetNumber); - injectDaggerClass(injector); - if (timeZone == null) { - throw new IllegalArgumentException("Time zone can not be null"); - } - - suspended = false; - configuredAlerts = new HashMap<>(); - configuredAlerts.put(AlertSlot.SLOT7, AlertType.FINISH_SETUP_REMINDER); - - this.timeZone = timeZone; - this.setupProgress = SetupProgress.ADDRESS_ASSIGNED; - this.piVersion = piVersion; - this.pmVersion = pmVersion; - this.lot = lot; - this.tid = tid; - this.nonceState = new NonceState(lot, tid); - handleUpdates(); - } - - public void injectDaggerClass(HasAndroidInjector injector) { - injector.androidInjector().inject(this); - } - - public void setStateChangedHandler(PodStateChangedHandler handler) { - // FIXME this is an ugly workaround for not being able to serialize the PodStateChangedHandler - if (stateChangedHandler != null) { - throw new IllegalStateException("A PodStateChangedHandler has already been already registered"); - } - stateChangedHandler = handler; - } - - public AlertType getConfiguredAlertType(AlertSlot alertSlot) { - return configuredAlerts.get(alertSlot); - } - - public void putConfiguredAlert(AlertSlot alertSlot, AlertType alertType) { - configuredAlerts.put(alertSlot, alertType); - handleUpdates(); - } - - public void removeConfiguredAlert(AlertSlot alertSlot) { - configuredAlerts.remove(alertSlot); - handleUpdates(); - } - - public DateTime getActivatedAt() { - return activatedAt == null ? null : activatedAt.withZone(timeZone); - } - - public DateTime getExpiresAt() { - return expiresAt == null ? null : expiresAt.withZone(timeZone); - } - - public String getExpiryDateAsString() { - return expiresAt == null ? "???" : DateUtil.dateAndTimeString(expiresAt.toDate()); - } - - public FirmwareVersion getPiVersion() { - return piVersion; - } - - public FirmwareVersion getPmVersion() { - return pmVersion; - } - - public int getLot() { - return lot; - } - - public int getTid() { - return tid; - } - - public Double getReservoirLevel() { - return reservoirLevel; - } - - public synchronized void resyncNonce(int syncWord, int sentNonce, int sequenceNumber) { - int sum = (sentNonce & 0xFFFF) - + OmniCRC.crc16lookup[sequenceNumber] - + (this.lot & 0xFFFF) - + (this.tid & 0xFFFF); - int seed = ((sum & 0xFFFF) ^ syncWord); - - this.nonceState = new NonceState(lot, tid, (byte) (seed & 0xFF)); - handleUpdates(); - } - - public int getCurrentNonce() { - return nonceState.getCurrentNonce(); - } - - public synchronized void advanceToNextNonce() { - nonceState.advanceToNextNonce(); - handleUpdates(); - } - - public SetupProgress getSetupProgress() { - return setupProgress; - } - - public synchronized void setSetupProgress(SetupProgress setupProgress) { - if (setupProgress == null) { - throw new IllegalArgumentException("Setup state cannot be null"); - } - this.setupProgress = setupProgress; - handleUpdates(); - } - - public boolean isSuspended() { - return suspended; - } - - public boolean hasActiveAlerts() { - return activeAlerts != null && activeAlerts.size() > 0; - } - - public AlertSet getActiveAlerts() { - return activeAlerts; - } - - public DateTimeZone getTimeZone() { - return timeZone; - } - - public void setTimeZone(DateTimeZone timeZone) { - if (timeZone == null) { - throw new IllegalArgumentException("Time zone can not be null"); - } - this.timeZone = timeZone; - handleUpdates(); - } - - public DateTime getTime() { - DateTime now = DateTime.now(); - return now.withZone(timeZone); - } - - public Duration getScheduleOffset() { - DateTime now = getTime(); - DateTime startOfDay = new DateTime(now.getYear(), now.getMonthOfYear(), now.getDayOfMonth(), - 0, 0, 0, timeZone); - return new Duration(startOfDay, now); - } - - public boolean hasNonceState() { - return true; - } - - @Override - public void setPacketNumber(int packetNumber) { - super.setPacketNumber(packetNumber); - handleUpdates(); - } - - @Override - public void setMessageNumber(int messageNumber) { - super.setMessageNumber(messageNumber); - handleUpdates(); - } - - public BasalSchedule getBasalSchedule() { - return basalSchedule; - } - - public void setBasalSchedule(BasalSchedule basalSchedule) { - this.basalSchedule = basalSchedule; - handleUpdates(); - } - - public DeliveryStatus getLastDeliveryStatus() { - return lastDeliveryStatus; - } - - @Override - public void setFaultEvent(PodInfoFaultEvent faultEvent) { - super.setFaultEvent(faultEvent); - suspended = true; - handleUpdates(); - } - - @Override - public void updateFromStatusResponse(StatusResponse statusResponse) { - DateTime activatedAtCalculated = getTime().minus(statusResponse.getTimeActive()); - if (activatedAt == null) { - activatedAt = activatedAtCalculated; - } - DateTime expiresAtCalculated = activatedAtCalculated.plus(OmnipodConst.NOMINAL_POD_LIFE); - if (expiresAt == null || expiresAtCalculated.isBefore(expiresAt) || expiresAtCalculated.isAfter(expiresAt.plusMinutes(1))) { - expiresAt = expiresAtCalculated; - } - - boolean newSuspendedState = statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED; - if (suspended != newSuspendedState) { - aapsLogger.info(LTag.PUMPCOMM, "Updating pod suspended state in updateFromStatusResponse. newSuspendedState={}, statusResponse={}", newSuspendedState, statusResponse.toString()); - suspended = newSuspendedState; - } - activeAlerts = statusResponse.getAlerts(); - lastDeliveryStatus = statusResponse.getDeliveryStatus(); - reservoirLevel = statusResponse.getReservoirLevel(); - handleUpdates(); - } - - private void handleUpdates() { - Gson gson = omnipodUtil.getGsonInstance(); - String gsonValue = gson.toJson(this); - aapsLogger.info(LTag.PUMPCOMM, "PodSessionState-SP: Saved Session State to SharedPreferences: " + gsonValue); - sp.putString(OmnipodConst.Prefs.PodState, gsonValue); - if (stateChangedHandler != null) { - stateChangedHandler.handle(this); - } - } - - @Override - public String toString() { - return "PodSessionState{" + - "configuredAlerts=" + configuredAlerts + - ", stateChangedHandler=" + stateChangedHandler + - ", activatedAt=" + activatedAt + - ", expiresAt=" + expiresAt + - ", piVersion=" + piVersion + - ", pmVersion=" + pmVersion + - ", lot=" + lot + - ", tid=" + tid + - ", reservoirLevel=" + reservoirLevel + - ", suspended=" + suspended + - ", timeZone=" + timeZone + - ", nonceState=" + nonceState + - ", setupProgress=" + setupProgress + - ", activeAlerts=" + activeAlerts + - ", basalSchedule=" + basalSchedule + - ", lastDeliveryStatus=" + lastDeliveryStatus + - ", address=" + address + - ", packetNumber=" + packetNumber + - ", messageNumber=" + messageNumber + - ", faultEvent=" + faultEvent + - '}'; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSetupState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSetupState.java deleted file mode 100644 index 26b5802258..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSetupState.java +++ /dev/null @@ -1,43 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; - -import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; - -public class PodSetupState extends PodState { - public PodSetupState(int address, int packetNumber, int messageNumber) { - super(address, packetNumber, messageNumber); - } - - @Override - public boolean hasNonceState() { - return false; - } - - @Override - public int getCurrentNonce() { - throw new UnsupportedOperationException("PodSetupState does not have a nonce state"); - } - - @Override - public void advanceToNextNonce() { - throw new UnsupportedOperationException("PodSetupState does not have a nonce state"); - } - - @Override - public void resyncNonce(int syncWord, int sentNonce, int sequenceNumber) { - throw new UnsupportedOperationException("PodSetupState does not have a nonce state"); - } - - @Override - public void updateFromStatusResponse(StatusResponse statusResponse) { - } - - @Override - public String toString() { - return "PodSetupState{" + - "address=" + address + - ", packetNumber=" + packetNumber + - ", messageNumber=" + messageNumber + - ", faultEvent=" + faultEvent + - '}'; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java deleted file mode 100644 index c6987c879e..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodState.java +++ /dev/null @@ -1,68 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; - -import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent; - -public abstract class PodState { - protected final int address; - protected int packetNumber; - protected int messageNumber; - - protected PodInfoFaultEvent faultEvent; - - public PodState(int address, int packetNumber, int messageNumber) { - this.address = address; - this.packetNumber = packetNumber; - this.messageNumber = messageNumber; - } - - public abstract boolean hasNonceState(); - - public abstract int getCurrentNonce(); - - public abstract void advanceToNextNonce(); - - public abstract void resyncNonce(int syncWord, int sentNonce, int sequenceNumber); - - public abstract void updateFromStatusResponse(StatusResponse statusResponse); - - public int getAddress() { - return address; - } - - public int getMessageNumber() { - return messageNumber; - } - - public void setMessageNumber(int messageNumber) { - this.messageNumber = messageNumber; - } - - public int getPacketNumber() { - return packetNumber; - } - - public void setPacketNumber(int packetNumber) { - this.packetNumber = packetNumber; - } - - public void increaseMessageNumber() { - setMessageNumber((messageNumber + 1) & 0b1111); - } - - public void increasePacketNumber() { - setPacketNumber((packetNumber + 1) & 0b11111); - } - - public boolean hasFaultEvent() { - return faultEvent != null; - } - - public PodInfoFaultEvent getFaultEvent() { - return faultEvent; - } - - public void setFaultEvent(PodInfoFaultEvent faultEvent) { - this.faultEvent = faultEvent; - } -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodStateChangedHandler.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodStateChangedHandler.java deleted file mode 100644 index 6e706131a2..0000000000 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodStateChangedHandler.java +++ /dev/null @@ -1,6 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; - -@FunctionalInterface -public interface PodStateChangedHandler { - void handle(PodSessionState podState); -} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodStateManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodStateManager.java new file mode 100644 index 0000000000..4cbb965244 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodStateManager.java @@ -0,0 +1,754 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializer; + +import net.danlew.android.joda.JodaTimeAndroid; + +import org.apache.commons.lang3.StringUtils; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; +import org.joda.time.Duration; +import org.joda.time.format.ISODateTimeFormat; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.logging.LTag; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; +import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoFaultEvent; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.DeliveryStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FirmwareVersion; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; +import info.nightscout.androidaps.plugins.pump.omnipod.util.OmniCRC; +import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; +import info.nightscout.androidaps.utils.DateUtil; + +public abstract class PodStateManager { + + private final AAPSLogger aapsLogger; + private final Gson gsonInstance; + private PodState podState; + + public PodStateManager(AAPSLogger aapsLogger) { + this.aapsLogger = aapsLogger; + this.gsonInstance = createGson(); + } + + public final boolean hasState() { + return podState != null; + } + + public final void removeState() { + this.podState = null; + storePodState(); + notifyPodStateChanged(); + } + + public final void initState(int address) { + if (hasState()) { + throw new IllegalStateException("Can not init a new pod state: podState <> null"); + } + podState = new PodState(address); + storePodState(); + notifyPodStateChanged(); + } + + public final boolean isPaired() { + return hasState() // + && podState.getLot() != null && podState.getTid() != null // + && podState.getPiVersion() != null && podState.getPmVersion() != null // + && podState.getTimeZone() != null // + && podState.getSetupProgress() != null; + } + + public final boolean isSetupCompleted() { + return isPaired() && SetupProgress.COMPLETED.equals(podState.getSetupProgress()); + } + + public final void setPairingParameters(int lot, int tid, FirmwareVersion piVersion, FirmwareVersion pmVersion, DateTimeZone timeZone) { + if (!hasState()) { + throw new IllegalStateException("Cannot set pairing parameters: podState is null"); + } + if (isPaired()) { + throw new IllegalStateException("Cannot set pairing parameters: pairing parameters have already been set"); + } + if (piVersion == null) { + throw new IllegalArgumentException("Cannot set pairing parameters: piVersion can not be null"); + } + if (pmVersion == null) { + throw new IllegalArgumentException("Cannot set pairing parameters: pmVersion can not be null"); + } + if (timeZone == null) { + throw new IllegalArgumentException("Cannot set pairing parameters: timeZone can not be null"); + } + + setAndStore(() -> { + podState.setLot(lot); + podState.setTid(tid); + podState.setPiVersion(piVersion); + podState.setPmVersion(pmVersion); + podState.setTimeZone(timeZone); + podState.setNonceState(new NonceState(lot, tid)); + podState.setSetupProgress(SetupProgress.ADDRESS_ASSIGNED); + podState.getConfiguredAlerts().put(AlertSlot.SLOT7, AlertType.FINISH_SETUP_REMINDER); + }); + } + + public final int getAddress() { + return getSafe(() -> podState.getAddress()); + } + + public final int getMessageNumber() { + return getSafe(() -> podState.getMessageNumber()); + } + + public final void setMessageNumber(int messageNumber) { + setAndStore(() -> podState.setMessageNumber(messageNumber)); + } + + public final int getPacketNumber() { + return getSafe(() -> podState.getPacketNumber()); + } + + public final void setPacketNumber(int packetNumber) { + setAndStore(() -> podState.setPacketNumber(packetNumber)); + } + + public final void increaseMessageNumber() { + setAndStore(() -> podState.setMessageNumber((podState.getMessageNumber() + 1) & 0b1111)); + } + + public final void increasePacketNumber() { + setAndStore(() -> podState.setPacketNumber((podState.getPacketNumber() + 1) & 0b11111)); + } + + public final synchronized void resyncNonce(int syncWord, int sentNonce, int sequenceNumber) { + if (!isPaired()) { + throw new IllegalStateException("Cannot resync nonce: Pod is not paired yet"); + } + + int sum = (sentNonce & 0xFFFF) + + OmniCRC.crc16lookup[sequenceNumber] + + (podState.getLot() & 0xFFFF) + + (podState.getTid() & 0xFFFF); + int seed = ((sum & 0xFFFF) ^ syncWord); + NonceState nonceState = new NonceState(podState.getLot(), podState.getTid(), (byte) (seed & 0xFF)); + + setAndStore(() -> podState.setNonceState(nonceState)); + } + + public final synchronized int getCurrentNonce() { + if (!isPaired()) { + throw new IllegalStateException("Cannot get current nonce: Pod is not paired yet"); + } + return podState.getNonceState().getCurrentNonce(); + } + + public final synchronized void advanceToNextNonce() { + if (!isPaired()) { + throw new IllegalStateException("Cannot advance to next nonce: Pod is not paired yet"); + } + setAndStore(() -> podState.getNonceState().advanceToNextNonce()); + } + + public final DateTime getLastSuccessfulCommunication() { + return getSafe(() -> podState.getLastSuccessfulCommunication()); + } + + public final void setLastSuccessfulCommunication(DateTime dateTime) { + setAndStore(() -> podState.setLastSuccessfulCommunication(dateTime)); + } + + public final DateTime getLastFailedCommunication() { + return getSafe(() -> podState.getLastFailedCommunication()); + } + + public final void setLastFailedCommunication(DateTime dateTime) { + setAndStore(() -> podState.setLastFailedCommunication(dateTime)); + } + + public final boolean hasFaultEvent() { + return getSafe(() -> podState.getFaultEvent()) != null; + } + + public final PodInfoFaultEvent getFaultEvent() { + return getSafe(() -> podState.getFaultEvent()); + } + + public final void setFaultEvent(PodInfoFaultEvent faultEvent) { + setAndStore(() -> podState.setFaultEvent(faultEvent)); + } + + public final AlertType getConfiguredAlertType(AlertSlot alertSlot) { + return getSafe(() -> podState.getConfiguredAlerts().get(alertSlot)); + } + + public final void putConfiguredAlert(AlertSlot alertSlot, AlertType alertType) { + setAndStore(() -> podState.getConfiguredAlerts().put(alertSlot, alertType)); + } + + public final void removeConfiguredAlert(AlertSlot alertSlot) { + setAndStore(() -> podState.getConfiguredAlerts().remove(alertSlot)); + } + + public final boolean hasActiveAlerts() { + AlertSet activeAlerts = podState.getActiveAlerts(); + return activeAlerts != null && activeAlerts.size() > 0; + } + + public final AlertSet getActiveAlerts() { + return new AlertSet(getSafe(() -> podState.getActiveAlerts())); + } + + public final Integer getLot() { + return getSafe(() -> podState.getLot()); + } + + public final Integer getTid() { + return getSafe(() -> podState.getTid()); + } + + public final FirmwareVersion getPiVersion() { + return getSafe(() -> podState.getPiVersion()); + } + + public final FirmwareVersion getPmVersion() { + return getSafe(() -> podState.getPmVersion()); + } + + public final DateTimeZone getTimeZone() { + return getSafe(() -> podState.getTimeZone()); + } + + public final void setTimeZone(DateTimeZone timeZone) { + if (timeZone == null) { + throw new IllegalArgumentException("Time zone can not be null"); + } + setAndStore(() -> podState.setTimeZone(timeZone)); + } + + public final DateTime getTime() { + DateTime now = DateTime.now(); + return now.withZone(getSafe(() -> podState.getTimeZone())); + } + + public final DateTime getActivatedAt() { + DateTime activatedAt = getSafe(() -> podState.getActivatedAt()); + return activatedAt == null ? null : activatedAt.withZone(getSafe(() -> podState.getTimeZone())); + } + + public final DateTime getExpiresAt() { + DateTime expiresAt = getSafe(() -> podState.getExpiresAt()); + return expiresAt == null ? null : expiresAt.withZone(getSafe(() -> podState.getTimeZone())); + } + + // TODO doesn't belong here + public final String getExpiryDateAsString() { + DateTime expiresAt = getExpiresAt(); + return expiresAt == null ? "???" : DateUtil.dateAndTimeString(expiresAt.toDate()); + } + + public final SetupProgress getSetupProgress() { + return getSafe(() -> podState.getSetupProgress()); + } + + public final void setSetupProgress(SetupProgress setupProgress) { + if (setupProgress == null) { + throw new IllegalArgumentException("Setup progress can not be null"); + } + setAndStore(() -> podState.setSetupProgress(setupProgress)); + } + + public final boolean isSuspended() { + return getSafe(() -> podState.isSuspended()); + } + + public final Double getReservoirLevel() { + return getSafe(() -> podState.getReservoirLevel()); + } + + public final Duration getScheduleOffset() { + DateTime now = getTime(); + DateTime startOfDay = new DateTime(now.getYear(), now.getMonthOfYear(), now.getDayOfMonth(), + 0, 0, 0, getSafe(() -> podState.getTimeZone())); + return new Duration(startOfDay, now); + } + + public final BasalSchedule getBasalSchedule() { + return getSafe(() -> podState.getBasalSchedule()); + } + + public final void setBasalSchedule(BasalSchedule basalSchedule) { + setAndStore(() -> podState.setBasalSchedule(basalSchedule)); + } + + public final DateTime getLastBolusStartTime() { + return getSafe(() -> podState.getLastBolusStartTime()); + } + + public final Double getLastBolusAmount() { + return getSafe(() -> podState.getLastBolusAmount()); + } + + public final void setLastBolus(DateTime startTime, double amount) { + setAndStore(() -> { + podState.setLastBolusStartTime(startTime); + podState.setLastBolusAmount(amount); + }); + } + + public final DateTime getLastTempBasalStartTime() { + return getSafe(() -> podState.getLastTempBasalStartTime()); + } + + public final Double getLastTempBasalAmount() { + return getSafe(() -> podState.getLastTempBasalAmount()); + } + + public final Duration getLastTempBasalDuration() { + return getSafe(() -> podState.getLastTempBasalDuration()); + } + + public final void setLastTempBasal(DateTime startTime, Double amount, Duration duration) { + setAndStore(() -> { + podState.setLastTempBasalStartTime(startTime); + podState.setLastTempBasalAmount(amount); + podState.setLastTempBasalDuration(duration); + }); + } + + public final DeliveryStatus getLastDeliveryStatus() { + return getSafe(() -> podState.getLastDeliveryStatus()); + } + + public final void updateFromStatusResponse(StatusResponse statusResponse) { + if (!hasState()) { + throw new IllegalStateException("Cannot update from status response: podState is null"); + } + setAndStore(() -> { + if (podState.getActivatedAt() == null) { + DateTime activatedAtCalculated = getTime().minus(statusResponse.getTimeActive()); + podState.setActivatedAt(activatedAtCalculated); + } + DateTime expiresAt = podState.getExpiresAt(); + DateTime expiresAtCalculated = podState.getActivatedAt().plus(OmnipodConst.NOMINAL_POD_LIFE); + if (expiresAt == null || expiresAtCalculated.isBefore(expiresAt) || expiresAtCalculated.isAfter(expiresAt.plusMinutes(1))) { + podState.setExpiresAt(expiresAtCalculated); + } + + boolean newSuspendedState = statusResponse.getDeliveryStatus() == DeliveryStatus.SUSPENDED; + if (podState.isSuspended() != newSuspendedState) { + aapsLogger.info(LTag.PUMPCOMM, "Updating pod suspended state in updateFromStatusResponse. newSuspendedState={}, statusResponse={}", newSuspendedState, statusResponse.toString()); + podState.setSuspended(newSuspendedState); + } + podState.setActiveAlerts(statusResponse.getAlerts()); + podState.setLastDeliveryStatus(statusResponse.getDeliveryStatus()); + podState.setReservoirLevel(statusResponse.getReservoirLevel()); + }); + } + + private void setAndStore(Runnable runnable) { + if (!hasState()) { + throw new IllegalStateException("Cannot mutate PodState: podState is null"); + } + runnable.run(); + storePodState(); + notifyPodStateChanged(); + } + + private void storePodState() { + String podState = gsonInstance.toJson(this.podState); + aapsLogger.info(LTag.PUMP, "storePodState: storing podState: " + podState); + storePodState(podState); + } + + protected abstract void storePodState(String podState); + + protected abstract String readPodState(); + + // Should be called after initializing the object + public final void loadPodState() { + podState = null; + + String storedPodState = readPodState(); + + if (StringUtils.isEmpty(storedPodState)) { + aapsLogger.info(LTag.PUMP, "loadPodState: no Pod state was provided"); + } else { + aapsLogger.info(LTag.PUMP, "loadPodState: serialized Pod state was provided: " + storedPodState); + try { + podState = gsonInstance.fromJson(storedPodState, PodState.class); + } catch (Exception ex) { + aapsLogger.error(LTag.PUMP, "loadPodState: could not deserialize PodState: " + storedPodState, ex); + } + } + + notifyPodStateChanged(); + } + + protected abstract void notifyPodStateChanged(); + + // Not actually "safe" as it throws an Exception, but it prevents NPEs + private T getSafe(Supplier supplier) { + if (!hasState()) { + throw new IllegalStateException("Cannot read from PodState: podState is null"); + } + return supplier.get(); + } + + private static Gson createGson() { + GsonBuilder gsonBuilder = new GsonBuilder() + .registerTypeAdapter(DateTime.class, (JsonSerializer) (dateTime, typeOfSrc, context) -> + new JsonPrimitive(ISODateTimeFormat.dateTime().print(dateTime))) + .registerTypeAdapter(DateTime.class, (JsonDeserializer) (json, typeOfT, context) -> + ISODateTimeFormat.dateTime().parseDateTime(json.getAsString())) + .registerTypeAdapter(DateTimeZone.class, (JsonSerializer) (timeZone, typeOfSrc, context) -> + new JsonPrimitive(timeZone.getID())) + .registerTypeAdapter(DateTimeZone.class, (JsonDeserializer) (json, typeOfT, context) -> + DateTimeZone.forID(json.getAsString())); + + return gsonBuilder.create(); + } + + @Override public String toString() { + return "AapsPodStateManager{" + + "podState=" + podState + + '}'; + } + + private static final class PodState { + private final int address; + private Integer lot; + private Integer tid; + private FirmwareVersion piVersion; + private FirmwareVersion pmVersion; + private int packetNumber; + private int messageNumber; + private DateTime lastSuccessfulCommunication; + private DateTime lastFailedCommunication; + private DateTimeZone timeZone; + private DateTime activatedAt; + private DateTime expiresAt; + private PodInfoFaultEvent faultEvent; + private Double reservoirLevel; + private boolean suspended; + private NonceState nonceState; + private SetupProgress setupProgress; + private DeliveryStatus lastDeliveryStatus; + private AlertSet activeAlerts; + private BasalSchedule basalSchedule; + private DateTime lastBolusStartTime; + private Double lastBolusAmount; + private Double lastTempBasalAmount; + private DateTime lastTempBasalStartTime; + private Duration lastTempBasalDuration; + private final Map configuredAlerts = new HashMap<>(); + + private PodState(int address) { + this.address = address; + } + + int getAddress() { + return address; + } + + Integer getLot() { + return lot; + } + + void setLot(int lot) { + this.lot = lot; + } + + Integer getTid() { + return tid; + } + + void setTid(int tid) { + this.tid = tid; + } + + FirmwareVersion getPiVersion() { + return piVersion; + } + + void setPiVersion(FirmwareVersion piVersion) { + if (this.piVersion != null) { + throw new IllegalStateException("piVersion has already been set"); + } + if (piVersion == null) { + throw new IllegalArgumentException("piVersion can not be null"); + } + this.piVersion = piVersion; + } + + FirmwareVersion getPmVersion() { + return pmVersion; + } + + void setPmVersion(FirmwareVersion pmVersion) { + this.pmVersion = pmVersion; + } + + int getPacketNumber() { + return packetNumber; + } + + void setPacketNumber(int packetNumber) { + this.packetNumber = packetNumber; + } + + int getMessageNumber() { + return messageNumber; + } + + void setMessageNumber(int messageNumber) { + this.messageNumber = messageNumber; + } + + DateTime getLastSuccessfulCommunication() { + return lastSuccessfulCommunication; + } + + void setLastSuccessfulCommunication(DateTime lastSuccessfulCommunication) { + this.lastSuccessfulCommunication = lastSuccessfulCommunication; + } + + DateTime getLastFailedCommunication() { + return lastFailedCommunication; + } + + void setLastFailedCommunication(DateTime lastFailedCommunication) { + this.lastFailedCommunication = lastFailedCommunication; + } + + DateTimeZone getTimeZone() { + return timeZone; + } + + void setTimeZone(DateTimeZone timeZone) { + this.timeZone = timeZone; + } + + DateTime getActivatedAt() { + return activatedAt; + } + + void setActivatedAt(DateTime activatedAt) { + this.activatedAt = activatedAt; + } + + DateTime getExpiresAt() { + return expiresAt; + } + + void setExpiresAt(DateTime expiresAt) { + this.expiresAt = expiresAt; + } + + PodInfoFaultEvent getFaultEvent() { + return faultEvent; + } + + void setFaultEvent(PodInfoFaultEvent faultEvent) { + this.faultEvent = faultEvent; + } + + Double getReservoirLevel() { + return reservoirLevel; + } + + void setReservoirLevel(Double reservoirLevel) { + this.reservoirLevel = reservoirLevel; + } + + public boolean isSuspended() { + return suspended; + } + + void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + NonceState getNonceState() { + return nonceState; + } + + void setNonceState(NonceState nonceState) { + this.nonceState = nonceState; + } + + public SetupProgress getSetupProgress() { + return setupProgress; + } + + void setSetupProgress(SetupProgress setupProgress) { + this.setupProgress = setupProgress; + } + + DeliveryStatus getLastDeliveryStatus() { + return lastDeliveryStatus; + } + + void setLastDeliveryStatus(DeliveryStatus lastDeliveryStatus) { + this.lastDeliveryStatus = lastDeliveryStatus; + } + + AlertSet getActiveAlerts() { + return activeAlerts; + } + + void setActiveAlerts(AlertSet activeAlerts) { + this.activeAlerts = activeAlerts; + } + + BasalSchedule getBasalSchedule() { + return basalSchedule; + } + + void setBasalSchedule(BasalSchedule basalSchedule) { + this.basalSchedule = basalSchedule; + } + + public DateTime getLastBolusStartTime() { + return lastBolusStartTime; + } + + void setLastBolusStartTime(DateTime lastBolusStartTime) { + this.lastBolusStartTime = lastBolusStartTime; + } + + Double getLastBolusAmount() { + return lastBolusAmount; + } + + void setLastBolusAmount(Double lastBolusAmount) { + this.lastBolusAmount = lastBolusAmount; + } + + Double getLastTempBasalAmount() { + return lastTempBasalAmount; + } + + void setLastTempBasalAmount(Double lastTempBasalAmount) { + this.lastTempBasalAmount = lastTempBasalAmount; + } + + DateTime getLastTempBasalStartTime() { + return lastTempBasalStartTime; + } + + void setLastTempBasalStartTime(DateTime lastTempBasalStartTime) { + this.lastTempBasalStartTime = lastTempBasalStartTime; + } + + Duration getLastTempBasalDuration() { + return lastTempBasalDuration; + } + + void setLastTempBasalDuration(Duration lastTempBasalDuration) { + this.lastTempBasalDuration = lastTempBasalDuration; + } + + Map getConfiguredAlerts() { + return configuredAlerts; + } + + @Override public String toString() { + return "PodState{" + + "address=" + address + + ", lot=" + lot + + ", tid=" + tid + + ", piVersion=" + piVersion + + ", pmVersion=" + pmVersion + + ", packetNumber=" + packetNumber + + ", messageNumber=" + messageNumber + + ", lastSuccessfulCommunication=" + lastSuccessfulCommunication + + ", lastFailedCommunication=" + lastFailedCommunication + + ", timeZone=" + timeZone + + ", activatedAt=" + activatedAt + + ", expiresAt=" + expiresAt + + ", faultEvent=" + faultEvent + + ", reservoirLevel=" + reservoirLevel + + ", suspended=" + suspended + + ", nonceState=" + nonceState + + ", setupProgress=" + setupProgress + + ", lastDeliveryStatus=" + lastDeliveryStatus + + ", activeAlerts=" + activeAlerts + + ", basalSchedule=" + basalSchedule + + ", lastBolusStartTime=" + lastBolusStartTime + + ", lastBolusAmount=" + lastBolusAmount + + ", lastTempBasalAmount=" + lastTempBasalAmount + + ", lastTempBasalStartTime=" + lastTempBasalStartTime + + ", lastTempBasalDuration=" + lastTempBasalDuration + + ", configuredAlerts=" + configuredAlerts + + '}'; + } + } + + private static class NonceState { + private final long[] table = new long[21]; + private int index; + + private NonceState(int lot, int tid) { + initializeTable(lot, tid, (byte) 0x00); + } + + private NonceState(int lot, int tid, byte seed) { + initializeTable(lot, tid, seed); + } + + private void initializeTable(int lot, int tid, byte seed) { + table[0] = (long) (lot & 0xFFFF) + 0x55543DC3L + (((long) (lot) & 0xFFFFFFFFL) >> 16); + table[0] = table[0] & 0xFFFFFFFFL; + table[1] = (tid & 0xFFFF) + 0xAAAAE44EL + (((long) (tid) & 0xFFFFFFFFL) >> 16); + table[1] = table[1] & 0xFFFFFFFFL; + index = 0; + table[0] += seed; + for (int i = 0; i < 16; i++) { + table[2 + i] = generateEntry(); + } + index = (int) ((table[0] + table[1]) & 0X0F); + } + + private int generateEntry() { + table[0] = (((table[0] >> 16) + (table[0] & 0xFFFF) * 0x5D7FL) & 0xFFFFFFFFL); + table[1] = (((table[1] >> 16) + (table[1] & 0xFFFF) * 0x8CA0L) & 0xFFFFFFFFL); + return (int) ((table[1] + (table[0] << 16)) & 0xFFFFFFFFL); + } + + public int getCurrentNonce() { + return (int) table[(2 + index)]; + } + + void advanceToNextNonce() { + int nonce = getCurrentNonce(); + table[(2 + index)] = generateEntry(); + index = (nonce & 0x0F); + } + + @Override + public String toString() { + return "NonceState{" + + "table=" + Arrays.toString(table) + + ", index=" + index + + '}'; + } + } + + // TODO replace with java.util.function.Supplier when min API level >= 24 + @FunctionalInterface + private interface Supplier { + T get(); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt index 372304ab66..b03332828a 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/PodManagementActivity.kt @@ -15,6 +15,7 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.plugins.bus.RxBusWrapper import info.nightscout.androidaps.plugins.configBuilder.ProfileFunction import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.defs.PodActionType import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.model.FullInitPodWizardModel import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.model.RemovePodWizardModel @@ -42,10 +43,10 @@ class PodManagementActivity : NoSplashAppCompatActivity() { @Inject lateinit var fabricPrivacy: FabricPrivacy @Inject lateinit var commandQueue: CommandQueueProvider @Inject lateinit var omnipodUtil: OmnipodUtil + @Inject lateinit var podStateManager: PodStateManager @Inject lateinit var injector: HasAndroidInjector private var initPodChanged = false - private var podSessionFullyInitalized = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -99,8 +100,7 @@ class PodManagementActivity : NoSplashAppCompatActivity() { wizardPagerContext.clearContext() wizardPagerContext.pagerSettings = pagerSettings - val podSessionState = omnipodUtil.getPodSessionState() - val isFullInit = podSessionState == null || podSessionState.setupProgress.isBefore(SetupProgress.PRIMING_FINISHED) + val isFullInit = !podStateManager.isPaired || podStateManager.setupProgress.isBefore(SetupProgress.PRIMING_FINISHED) if (isFullInit) { wizardPagerContext.wizardModel = FullInitPodWizardModel(applicationContext) } else { @@ -151,13 +151,11 @@ class PodManagementActivity : NoSplashAppCompatActivity() { } fun refreshButtons() { - initpod_init_pod.isEnabled = (omnipodUtil.getPodSessionState() == null || - omnipodUtil.getPodSessionState().getSetupProgress().isBefore(SetupProgress.COMPLETED)) + initpod_init_pod.isEnabled = !podStateManager.isPaired() || + podStateManager.getSetupProgress().isBefore(SetupProgress.COMPLETED) - val isPodSessionActive = (omnipodUtil.getPodSessionState() != null) - - initpod_remove_pod.isEnabled = isPodSessionActive - initpod_reset_pod.isEnabled = isPodSessionActive || omnipodUtil.hasNextPodAddress() + initpod_remove_pod.isEnabled = podStateManager.hasState() && podStateManager.isPaired + initpod_reset_pod.isEnabled = podStateManager.hasState() if (omnipodUtil.getDriverState() == OmnipodDriverState.NotInitalized) { // if rileylink is not running we disable all operations diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/InitPodRefreshAction.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/InitPodRefreshAction.java index 37c6d420f7..3d3d5d02d5 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/InitPodRefreshAction.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/InitPodRefreshAction.java @@ -16,6 +16,7 @@ import info.nightscout.androidaps.logging.AAPSLogger; import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.general.nsclient.NSUpload; import info.nightscout.androidaps.plugins.pump.omnipod.defs.SetupProgress; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.PodManagementActivity; import info.nightscout.androidaps.plugins.pump.omnipod.dialogs.wizard.defs.PodActionType; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodDriverState; @@ -33,6 +34,7 @@ public class InitPodRefreshAction extends AbstractCancelAction implements Finish private PodActionType actionType; @Inject OmnipodUtil omnipodUtil; + @Inject PodStateManager podStateManager; @Inject AAPSLogger aapsLogger; @Inject SP sp; @@ -58,7 +60,7 @@ public class InitPodRefreshAction extends AbstractCancelAction implements Finish @Override public void execute() { if (actionType == PodActionType.InitPod) { - if (omnipodUtil.getPodSessionState().getSetupProgress().isBefore(SetupProgress.COMPLETED)) { + if (podStateManager.getSetupProgress().isBefore(SetupProgress.COMPLETED)) { omnipodUtil.setDriverState(OmnipodDriverState.Initalized_PodInitializing); } else { omnipodUtil.setDriverState(OmnipodDriverState.Initalized_PodAttached); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/PodInfoFragment.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/PodInfoFragment.java index 65d032739d..a0369832bd 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/PodInfoFragment.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dialogs/wizard/pages/PodInfoFragment.java @@ -19,7 +19,7 @@ import javax.inject.Inject; import dagger.android.support.DaggerFragment; import info.nightscout.androidaps.R; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil; @@ -30,6 +30,7 @@ public class PodInfoFragment extends DaggerFragment { private static final String ARG_KEY = "key"; @Inject OmnipodUtil omnipodUtil; + @Inject PodStateManager podStateManager; private PageFragmentCallbacks mCallbacks; private String mKey; @@ -84,28 +85,24 @@ public class PodInfoFragment extends DaggerFragment { } private boolean createDataOfPod() { - - PodSessionState podSessionState = omnipodUtil.getPodSessionState(); - -// PodSessionState podSessionState = new PodSessionState(DateTimeZone.UTC, -// 483748738, -// new DateTime(), -// new FirmwareVersion(1,0,0), -// new FirmwareVersion(1,0,0), -// 574875, -// 5487584, -// 1, -// 1 -// ); - - if (podSessionState == null) + if (podStateManager == null) return false; mCurrentReviewItems = new ArrayList<>(); - mCurrentReviewItems.add(new ReviewItem("Pod Address", "" + podSessionState.getAddress(), "33")); - mCurrentReviewItems.add(new ReviewItem("Activated At", podSessionState.getActivatedAt().toString("dd.MM.yyyy HH:mm:ss"), "34")); - mCurrentReviewItems.add(new ReviewItem("Firmware Version", podSessionState.getPiVersion().toString(), "35")); - mCurrentReviewItems.add(new ReviewItem("LOT", "" + podSessionState.getLot(), "36")); + mCurrentReviewItems.add(new ReviewItem("Pod Address", "" + podStateManager.getAddress(), "33")); + mCurrentReviewItems.add(new ReviewItem("Activated At", podStateManager.getActivatedAt() == null ? "Not activated yet" : podStateManager.getActivatedAt().toString("dd.MM.yyyy HH:mm:ss"), "34")); + if (podStateManager.getLot() != null) { + mCurrentReviewItems.add(new ReviewItem("LOT", "" + podStateManager.getLot(), "35")); + } + if (podStateManager.getTid() != null) { + mCurrentReviewItems.add(new ReviewItem("TID", "" + podStateManager.getLot(), "36")); + } + if (podStateManager.getPiVersion() != null) { + mCurrentReviewItems.add(new ReviewItem("Pi Version", podStateManager.getPiVersion().toString(), "37")); + } + if (podStateManager.getPmVersion() != null) { + mCurrentReviewItems.add(new ReviewItem("Pm Version", podStateManager.getPmVersion().toString(), "38")); + } return true; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/OmnipodPumpStatus.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/OmnipodPumpStatus.java index 05ca9d6ad5..e069875d27 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/OmnipodPumpStatus.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/OmnipodPumpStatus.java @@ -15,9 +15,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLin 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.medtronic.defs.PumpDeviceState; -import info.nightscout.androidaps.plugins.pump.medtronic.events.EventMedtronicDeviceStatusChange; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodDeviceState; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -47,13 +45,13 @@ public class OmnipodPumpStatus extends PumpStatus { public Double tempBasalAmount = 0.0d; public Integer tempBasalLength; public long tempBasalPumpId; - public PodSessionState podSessionState; public PumpType pumpType; public String regexMac = "([\\da-fA-F]{1,2}(?:\\:|$)){6}"; public String podNumber; public PodDeviceState podDeviceState = PodDeviceState.NeverContacted; + // FIXME replace with method calls on PodStateManager public boolean podAvailable = false; public boolean podAvailibityChecked = false; public boolean ackAlertsAvailable = false; @@ -142,7 +140,6 @@ public class OmnipodPumpStatus extends PumpStatus { ", tempBasalEnd=" + tempBasalEnd + ", tempBasalAmount=" + tempBasalAmount + ", tempBasalLength=" + tempBasalLength + - ", podSessionState=" + podSessionState + ", regexMac='" + regexMac + '\'' + ", podNumber='" + podNumber + '\'' + ", podDeviceState=" + podDeviceState + diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java index f8c67f5471..f814a1082f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsOmnipodManager.java @@ -1,16 +1,13 @@ package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm; import android.content.Intent; -import android.text.TextUtils; -import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.joda.time.Duration; import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.Objects; import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.MainApp; @@ -22,7 +19,6 @@ import info.nightscout.androidaps.data.PumpEnactResult; import info.nightscout.androidaps.db.Source; import info.nightscout.androidaps.db.TemporaryBasal; import info.nightscout.androidaps.events.Event; -import info.nightscout.androidaps.events.EventRefreshOverview; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.interfaces.TreatmentsInterface; import info.nightscout.androidaps.logging.AAPSLogger; @@ -32,7 +28,6 @@ import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotifi import info.nightscout.androidaps.plugins.general.overview.events.EventOverviewBolusProgress; import info.nightscout.androidaps.plugins.general.overview.notifications.Notification; import info.nightscout.androidaps.plugins.pump.common.data.TempBasalPair; -import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType; import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.plugins.pump.common.utils.ByteUtil; import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil; @@ -60,8 +55,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.exception.PodReturne import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.StatusResponse; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoRecentPulseLog; import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.podinfo.PodInfoResponse; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.FaultEventCode; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInfoType; @@ -69,12 +62,10 @@ import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitReceiver; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalSchedule; import info.nightscout.androidaps.plugins.pump.omnipod.defs.schedule.BasalScheduleEntry; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.db.PodHistory; import info.nightscout.androidaps.plugins.pump.omnipod.driver.db.PodHistoryEntryType; -import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodAcknowledgeAlertsChanged; -import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged; import info.nightscout.androidaps.plugins.pump.omnipod.exception.OmnipodException; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil; import info.nightscout.androidaps.utils.resources.ResourceHelper; @@ -83,6 +74,7 @@ import io.reactivex.disposables.Disposable; public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface { + private final PodStateManager podStateManager; private OmnipodUtil omnipodUtil; private AAPSLogger aapsLogger; private RxBusWrapper rxBus; @@ -95,15 +87,12 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface private static AapsOmnipodManager instance; - private Date lastBolusTime; - private Double lastBolusUnits; - public static AapsOmnipodManager getInstance() { return instance; } public AapsOmnipodManager(OmnipodCommunicationManager communicationService, - PodSessionState podState, + PodStateManager podStateManager, OmnipodPumpStatus _pumpStatus, OmnipodUtil omnipodUtil, AAPSLogger aapsLogger, @@ -112,6 +101,10 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface ResourceHelper resourceHelper, HasAndroidInjector injector, ActivePluginProvider activePlugin) { + if (podStateManager == null) { + throw new IllegalArgumentException("Pod state manager can not be null"); + } + this.podStateManager = podStateManager; this.omnipodUtil = omnipodUtil; this.aapsLogger = aapsLogger; this.rxBus = rxBus; @@ -120,76 +113,12 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface this.activePlugin = activePlugin; this.pumpStatus = _pumpStatus; - delegate = new OmnipodManager(aapsLogger, sp, communicationService, podState, podSessionState -> { - // Handle pod state changes - omnipodUtil.setPodSessionState(podSessionState); - updatePumpStatus(podSessionState); - }); + delegate = new OmnipodManager(aapsLogger, sp, communicationService, podStateManager); instance = this; } - private void updatePumpStatus(PodSessionState podSessionState) { - if (pumpStatus != null) { - if (podSessionState == null) { - pumpStatus.ackAlertsText = null; - pumpStatus.ackAlertsAvailable = false; - pumpStatus.lastBolusTime = null; - pumpStatus.lastBolusAmount = null; - pumpStatus.reservoirRemainingUnits = 0.0; - pumpStatus.pumpStatusType = PumpStatusType.Suspended; - sendEvent(new EventOmnipodAcknowledgeAlertsChanged()); - sendEvent(new EventOmnipodPumpValuesChanged()); - sendEvent(new EventRefreshOverview("Omnipod Pump", false)); - } else { - // Update active alerts - if (podSessionState.hasActiveAlerts()) { - List alerts = translateActiveAlerts(podSessionState); - String alertsText = TextUtils.join("\n", alerts); - - if (!pumpStatus.ackAlertsAvailable || !alertsText.equals(pumpStatus.ackAlertsText)) { - pumpStatus.ackAlertsAvailable = true; - pumpStatus.ackAlertsText = TextUtils.join("\n", alerts); - - sendEvent(new EventOmnipodAcknowledgeAlertsChanged()); - } - } else { - if (pumpStatus.ackAlertsAvailable || StringUtils.isNotEmpty(pumpStatus.ackAlertsText)) { - pumpStatus.ackAlertsText = null; - pumpStatus.ackAlertsAvailable = false; - sendEvent(new EventOmnipodAcknowledgeAlertsChanged()); - } - } - - // Update other info: last bolus, units remaining, suspended - if (!Objects.equals(lastBolusTime, pumpStatus.lastBolusTime) // - || !Objects.equals(lastBolusUnits, pumpStatus.lastBolusAmount) // - || !isReservoirStatusUpToDate(pumpStatus, podSessionState.getReservoirLevel()) - || podSessionState.isSuspended() != PumpStatusType.Suspended.equals(pumpStatus.pumpStatusType)) { - pumpStatus.lastBolusTime = lastBolusTime; - pumpStatus.lastBolusAmount = lastBolusUnits; - pumpStatus.reservoirRemainingUnits = podSessionState.getReservoirLevel() == null ? 75.0 : podSessionState.getReservoirLevel(); - pumpStatus.pumpStatusType = podSessionState.isSuspended() ? PumpStatusType.Suspended : PumpStatusType.Running; - sendEvent(new EventOmnipodPumpValuesChanged()); - - if (podSessionState.isSuspended() != PumpStatusType.Suspended.equals(pumpStatus.pumpStatusType)) { - sendEvent(new EventRefreshOverview("Omnipod Pump", false)); - } - } - } - } - } - - private static boolean isReservoirStatusUpToDate(OmnipodPumpStatus pumpStatus, Double unitsRemaining) { - double expectedUnitsRemaining = unitsRemaining == null ? 75.0 : unitsRemaining; - return Math.abs(expectedUnitsRemaining - pumpStatus.reservoirRemainingUnits) < 0.000001; - } - - private List translateActiveAlerts(PodSessionState podSessionState) { - List alerts = new ArrayList<>(); - for (AlertSlot alertSlot : podSessionState.getActiveAlerts().getAlertSlots()) { - alerts.add(translateAlertType(podSessionState.getConfiguredAlertType(alertSlot))); - } - return alerts; + public PodStateManager getPodStateManager() { + return podStateManager; } @Override @@ -197,13 +126,9 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface long time = System.currentTimeMillis(); if (PodInitActionType.PairAndPrimeWizardStep.equals(podInitActionType)) { try { - int address = obtainNextPodAddress(); - - Disposable disposable = delegate.pairAndPrime(address).subscribe(res -> // + Disposable disposable = delegate.pairAndPrime().subscribe(res -> // handleSetupActionResult(podInitActionType, podInitReceiver, res, time, null)); - removeNextPodAddress(); - return new PumpEnactResult(injector).success(true).enacted(true); } catch (Exception ex) { String comment = handleAndTranslateException(ex); @@ -265,8 +190,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface podInitReceiver.returnInitTaskStatus(PodInitActionType.DeactivatePodWizardStep, true, null); - this.omnipodUtil.setPodSessionState(null); - return new PumpEnactResult(injector).success(true).enacted(true); } @@ -296,19 +219,15 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return new PumpEnactResult(injector).success(false).enacted(false).comment(comment); } - return new PumpEnactResult(injector).success(true).enacted(true); } @Override public PumpEnactResult resetPodStatus() { - delegate.resetPodState(true); + getPodStateManager().removeState(); reportImplicitlyCanceledTbr(); - this.omnipodUtil.setPodSessionState(null); - this.omnipodUtil.removeNextPodAddress(); - addSuccessToHistory(System.currentTimeMillis(), PodHistoryEntryType.ResetPodState, null); return new PumpEnactResult(injector).success(true).enacted(true); @@ -349,11 +268,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface double unitsDelivered = bolusDeliveryResult.getUnitsDelivered(); - if (pumpStatus != null && !detailedBolusInfo.isSMB) { - lastBolusTime = pumpStatus.lastBolusTime = bolusStarted; - lastBolusUnits = pumpStatus.lastBolusAmount = unitsDelivered; - } - long pumpId = addSuccessToHistory(bolusStarted.getTime(), PodHistoryEntryType.SetBolus, unitsDelivered + ";" + detailedBolusInfo.carbs); detailedBolusInfo.date = bolusStarted.getTime(); @@ -363,8 +277,8 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface activePlugin.getActiveTreatments().addToHistoryTreatment(detailedBolusInfo, false); - if (delegate.getPodState().hasFaultEvent()) { - showPodFaultErrorDialog(delegate.getPodState().getFaultEvent().getFaultEventCode(), R.raw.urgentalarm); + if (podStateManager.hasFaultEvent()) { + showPodFaultErrorDialog(podStateManager.getFaultEvent().getFaultEventCode(), R.raw.urgentalarm); } return new PumpEnactResult(injector).success(true).enacted(true).bolusDelivered(unitsDelivered); @@ -460,12 +374,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return new PumpEnactResult(injector).success(true).enacted(true); } - @Override - public void setPumpStatus(OmnipodPumpStatus pumpStatus) { - this.pumpStatus = pumpStatus; - updatePumpStatus(delegate.getPodState()); - } - // TODO should we add this to the OmnipodCommunicationManager interface? public PumpEnactResult getPodInfo(PodInfoType podInfoType) { long time = System.currentTimeMillis(); @@ -547,10 +455,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return delegate.isReadyForDelivery(); } - public String getPodStateAsString() { - return delegate.getPodStateAsString(); - } - private void reportImplicitlyCanceledTbr() { //TreatmentsPlugin plugin = TreatmentsPlugin.getPlugin(); TreatmentsInterface plugin = activePlugin.getActiveTreatments(); @@ -598,20 +502,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface return podHistory.getPumpId(); } - private int obtainNextPodAddress() { - Integer nextPodAddress = this.omnipodUtil.getNextPodAddress(); - if (nextPodAddress == null) { - nextPodAddress = OmnipodManager.generateRandomAddress(); - this.omnipodUtil.setNextPodAddress(nextPodAddress); - } - - return nextPodAddress; - } - - private void removeNextPodAddress() { - this.omnipodUtil.removeNextPodAddress(); - } - private void handleSetupActionResult(PodInitActionType podInitActionType, PodInitReceiver podInitReceiver, SetupActionResult res, long time, Profile profile) { String comment = null; switch (res.getResultType()) { @@ -725,28 +615,6 @@ public class AapsOmnipodManager implements OmnipodCommunicationManagerInterface sendEvent(new EventNewNotification(notification)); } - private String translateAlertType(AlertType alertType) { - if (alertType == null) { - return getStringResource(R.string.omnipod_alert_unknown_alert); - } - switch (alertType) { - case FINISH_PAIRING_REMINDER: - return getStringResource(R.string.omnipod_alert_finish_pairing_reminder); - case FINISH_SETUP_REMINDER: - return getStringResource(R.string.omnipod_alert_finish_setup_reminder_reminder); - case EXPIRATION_ALERT: - return getStringResource(R.string.omnipod_alert_expiration); - case EXPIRATION_ADVISORY_ALERT: - return getStringResource(R.string.omnipod_alert_expiration_advisory); - case SHUTDOWN_IMMINENT_ALARM: - return getStringResource(R.string.omnipod_alert_shutdown_imminent); - case LOW_RESERVOIR_ALERT: - return getStringResource(R.string.omnipod_alert_low_reservoir); - default: - return alertType.name(); - } - } - private boolean isBolusBeepsEnabled() { return this.pumpStatus.beepBolusEnabled; } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsPodStateManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsPodStateManager.java new file mode 100644 index 0000000000..d5f8c95d72 --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/driver/comm/AapsPodStateManager.java @@ -0,0 +1,178 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.driver.comm; + +import android.text.TextUtils; + +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Objects; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import info.nightscout.androidaps.R; +import info.nightscout.androidaps.events.Event; +import info.nightscout.androidaps.events.EventRefreshOverview; +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.plugins.bus.RxBusWrapper; +import info.nightscout.androidaps.plugins.pump.common.defs.PumpStatusType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSet; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertSlot; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.AlertType; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodAcknowledgeAlertsChanged; +import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange; +import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodPumpValuesChanged; +import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; +import info.nightscout.androidaps.utils.resources.ResourceHelper; +import info.nightscout.androidaps.utils.sharedPreferences.SP; + +@Singleton +public class AapsPodStateManager extends PodStateManager { + private final AAPSLogger aapsLogger; + private final SP sp; + private final OmnipodPumpStatus omnipodPumpStatus; + private final RxBusWrapper rxBus; + private final ResourceHelper resourceHelper; + + @Inject + public AapsPodStateManager(AAPSLogger aapsLogger, SP sp, OmnipodPumpStatus omnipodPumpStatus, + RxBusWrapper rxBus, ResourceHelper resourceHelper) { + super(aapsLogger); + + if (aapsLogger == null) { + throw new IllegalArgumentException("aapsLogger can not be null"); + } + if (sp == null) { + throw new IllegalArgumentException("sp can not be null"); + } + if (omnipodPumpStatus == null) { + throw new IllegalArgumentException("omnipodPumpStatus can not be null"); + } + if (rxBus == null) { + throw new IllegalArgumentException("rxBus can not be null"); + } + if (resourceHelper == null) { + throw new IllegalArgumentException("resourceHelper can not be null"); + } + + this.aapsLogger = aapsLogger; + this.sp = sp; + this.omnipodPumpStatus = omnipodPumpStatus; + this.rxBus = rxBus; + this.resourceHelper = resourceHelper; + } + + @Override + protected String readPodState() { + return sp.getString(OmnipodConst.Prefs.PodState, ""); + } + + @Override + protected void storePodState(String podState) { + sp.putString(OmnipodConst.Prefs.PodState, podState); + } + + @Override + protected void notifyPodStateChanged() { + if (!hasState()) { + omnipodPumpStatus.ackAlertsText = null; + omnipodPumpStatus.ackAlertsAvailable = false; + omnipodPumpStatus.lastBolusTime = null; + omnipodPumpStatus.lastBolusAmount = null; + omnipodPumpStatus.reservoirRemainingUnits = 0.0; + omnipodPumpStatus.pumpStatusType = PumpStatusType.Suspended; + sendEvent(new EventOmnipodAcknowledgeAlertsChanged()); + sendEvent(new EventOmnipodPumpValuesChanged()); + sendEvent(new EventRefreshOverview("Omnipod Pump", false)); + } else { + // Update active alerts + if (hasActiveAlerts()) { + List alerts = getTranslatedActiveAlerts(); + String alertsText = TextUtils.join("\n", alerts); + + if (!omnipodPumpStatus.ackAlertsAvailable || !alertsText.equals(omnipodPumpStatus.ackAlertsText)) { + omnipodPumpStatus.ackAlertsAvailable = true; + omnipodPumpStatus.ackAlertsText = TextUtils.join("\n", alerts); + + sendEvent(new EventOmnipodAcknowledgeAlertsChanged()); + } + } else { + if (omnipodPumpStatus.ackAlertsAvailable || StringUtils.isNotEmpty(omnipodPumpStatus.ackAlertsText)) { + omnipodPumpStatus.ackAlertsText = null; + omnipodPumpStatus.ackAlertsAvailable = false; + sendEvent(new EventOmnipodAcknowledgeAlertsChanged()); + } + } + + Date lastBolusStartTime = getLastBolusStartTime() == null ? null : getLastBolusStartTime().toDate(); + Double lastBolusAmount = getLastBolusAmount(); + + // Update other info: last bolus, units remaining, suspended + if (Objects.equals(lastBolusStartTime, omnipodPumpStatus.lastBolusTime) // + || !Objects.equals(lastBolusAmount, omnipodPumpStatus.lastBolusAmount) // + || !isReservoirStatusUpToDate(omnipodPumpStatus, getReservoirLevel()) + || isSuspended() != PumpStatusType.Suspended.equals(omnipodPumpStatus.pumpStatusType)) { + omnipodPumpStatus.lastBolusTime = lastBolusStartTime; + omnipodPumpStatus.lastBolusAmount = lastBolusAmount; + omnipodPumpStatus.reservoirRemainingUnits = getReservoirLevel() == null ? 75.0 : getReservoirLevel(); + omnipodPumpStatus.pumpStatusType = isSuspended() ? PumpStatusType.Suspended : PumpStatusType.Running; + sendEvent(new EventOmnipodPumpValuesChanged()); + + if (isSuspended() != PumpStatusType.Suspended.equals(omnipodPumpStatus.pumpStatusType)) { + sendEvent(new EventRefreshOverview("Omnipod Pump", false)); + } + } + } + rxBus.send(new EventOmnipodDeviceStatusChange(this)); + } + + private List getTranslatedActiveAlerts() { + List translatedAlerts = new ArrayList<>(); + AlertSet activeAlerts = getActiveAlerts(); + + for (AlertSlot alertSlot : activeAlerts.getAlertSlots()) { + translatedAlerts.add(translateAlertType(getConfiguredAlertType(alertSlot))); + } + return translatedAlerts; + } + + + private String translateAlertType(AlertType alertType) { + if (alertType == null) { + return getStringResource(R.string.omnipod_alert_unknown_alert); + } + switch (alertType) { + case FINISH_PAIRING_REMINDER: + return getStringResource(R.string.omnipod_alert_finish_pairing_reminder); + case FINISH_SETUP_REMINDER: + return getStringResource(R.string.omnipod_alert_finish_setup_reminder_reminder); + case EXPIRATION_ALERT: + return getStringResource(R.string.omnipod_alert_expiration); + case EXPIRATION_ADVISORY_ALERT: + return getStringResource(R.string.omnipod_alert_expiration_advisory); + case SHUTDOWN_IMMINENT_ALARM: + return getStringResource(R.string.omnipod_alert_shutdown_imminent); + case LOW_RESERVOIR_ALERT: + return getStringResource(R.string.omnipod_alert_low_reservoir); + default: + return alertType.name(); + } + } + + private String getStringResource(int id, Object... args) { + return resourceHelper.gs(id, args); + } + + private static boolean isReservoirStatusUpToDate(OmnipodPumpStatus pumpStatus, Double unitsRemaining) { + double expectedUnitsRemaining = unitsRemaining == null ? 75.0 : unitsRemaining; + return Math.abs(expectedUnitsRemaining - pumpStatus.reservoirRemainingUnits) < 0.000001; + } + + private void sendEvent(Event event) { + rxBus.send(event); + } +} diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.kt index 7e7cc87279..41f4cfca9b 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/events/EventOmnipodDeviceStatusChange.kt @@ -6,7 +6,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.defs.RileyLin import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodDeviceState -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager /** * Created by andy on 4.8.2019 @@ -15,7 +15,7 @@ class EventOmnipodDeviceStatusChange : Event { var rileyLinkServiceState: RileyLinkServiceState? = null var rileyLinkError: RileyLinkError? = null - var podSessionState: PodSessionState? = null + var podStateManager: PodStateManager? = null var errorDescription: String? = null var podDeviceState: PodDeviceState? = null var pumpDeviceState: PumpDeviceState? = null @@ -32,8 +32,8 @@ class EventOmnipodDeviceStatusChange : Event { } - constructor(podSessionState: PodSessionState?) { - this.podSessionState = podSessionState + constructor(podStateManager: PodStateManager?) { + this.podStateManager = podStateManager } constructor(errorDescription: String?) { @@ -58,7 +58,7 @@ class EventOmnipodDeviceStatusChange : Event { return ("EventOmnipodDeviceStatusChange [" // + "rileyLinkServiceState=" + rileyLinkServiceState + ", rileyLinkError=" + rileyLinkError // - + ", podSessionState=" + podSessionState // + + ", podStateManager=" + podStateManager // + ", podDeviceState=" + podDeviceState + "]") } } \ No newline at end of file diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java index f401e4ddd1..2503beb2b3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/service/RileyLinkOmnipodService.java @@ -7,6 +7,8 @@ import android.os.IBinder; import org.apache.commons.lang3.StringUtils; +import java.time.LocalDateTime; + import javax.inject.Inject; import info.nightscout.androidaps.R; @@ -23,11 +25,12 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.medtronic.defs.PumpDeviceState; import info.nightscout.androidaps.plugins.pump.omnipod.OmnipodPumpPlugin; import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodCommunicationManager; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.driver.comm.AapsOmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUIComm; import info.nightscout.androidaps.plugins.pump.omnipod.driver.ui.OmnipodUIPostprocessor; +import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodConst; import info.nightscout.androidaps.plugins.pump.omnipod.util.OmnipodUtil; @@ -42,6 +45,7 @@ public class RileyLinkOmnipodService extends RileyLinkService { @Inject OmnipodPumpStatus omnipodPumpStatus; @Inject OmnipodUtil omnipodUtil; @Inject OmnipodUIPostprocessor omnipodUIPostprocessor; + @Inject PodStateManager podStateManager; private static RileyLinkOmnipodService instance; @@ -59,12 +63,10 @@ public class RileyLinkOmnipodService extends RileyLinkService { instance = this; } - public static RileyLinkOmnipodService getInstance() { return instance; } - @Override public void onConfigurationChanged(Configuration newConfig) { aapsLogger.warn(LTag.PUMPCOMM, "onConfigurationChanged"); @@ -106,20 +108,20 @@ public class RileyLinkOmnipodService extends RileyLinkService { } private void initializeErosOmnipodManager() { - if (AapsOmnipodManager.getInstance() == null) { - PodSessionState podState = omnipodUtil.loadSessionState(); + AapsOmnipodManager instance = AapsOmnipodManager.getInstance(); + if (instance == null) { OmnipodCommunicationManager omnipodCommunicationService = new OmnipodCommunicationManager(injector, rfspy); - //omnipodCommunicationService.setPumpStatus(omnipodPumpStatus); this.omnipodCommunicationManager = omnipodCommunicationService; - this.aapsOmnipodManager = new AapsOmnipodManager(omnipodCommunicationService, podState, omnipodPumpStatus, + aapsOmnipodManager = new AapsOmnipodManager(omnipodCommunicationService, podStateManager, omnipodPumpStatus, omnipodUtil, aapsLogger, rxBus, sp, resourceHelper, injector, activePlugin); omnipodUIComm = new OmnipodUIComm(injector, aapsLogger, omnipodUtil, omnipodUIPostprocessor, aapsOmnipodManager); } else { - aapsOmnipodManager = AapsOmnipodManager.getInstance(); + aapsOmnipodManager = instance; } + rxBus.send(new EventOmnipodDeviceStatusChange(podStateManager)); } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java index d12fbd31df..35889383c2 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodConst.java @@ -14,7 +14,6 @@ public class OmnipodConst { public class Prefs { public static final String PodState = Prefix + "pod_state"; - public static final String NextPodAddress = Prefix + "next_pod_address"; public static final int BeepBasalEnabled = R.string.key_omnipod_beep_basal_enabled; public static final int BeepBolusEnabled = R.string.key_omnipod_beep_bolus_enabled; public static final int BeepSMBEnabled = R.string.key_omnipod_beep_smb_enabled; @@ -45,6 +44,7 @@ public class OmnipodConst { public static final int DEFAULT_ADDRESS = 0xffffffff; public static final Duration AVERAGE_BOLUS_COMMAND_COMMUNICATION_DURATION = Duration.millis(1500); + public static final Duration AVERAGE_TEMP_BASAL_COMMAND_COMMUNICATION_DURATION = Duration.millis(1500); public static final Duration SERVICE_DURATION = Duration.standardHours(80); public static final Duration EXPIRATION_ADVISORY_WINDOW = Duration.standardHours(9); diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java index 9c4f6cabe5..7fde7c640f 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/util/OmnipodUtil.java @@ -8,7 +8,6 @@ import com.google.gson.JsonDeserializer; import com.google.gson.JsonPrimitive; import com.google.gson.JsonSerializer; -import org.apache.commons.lang3.StringUtils; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.format.ISODateTimeFormat; @@ -16,21 +15,18 @@ import org.joda.time.format.ISODateTimeFormat; import javax.inject.Inject; import javax.inject.Singleton; -import dagger.android.HasAndroidInjector; import info.nightscout.androidaps.MainApp; import info.nightscout.androidaps.R; import info.nightscout.androidaps.interfaces.ActivePluginProvider; import info.nightscout.androidaps.logging.AAPSLogger; -import info.nightscout.androidaps.logging.LTag; import info.nightscout.androidaps.plugins.bus.RxBusWrapper; 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.common.hw.rileylink.data.RLHistoryItem; -import info.nightscout.androidaps.plugins.pump.omnipod.comm.OmnipodManager; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommandType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodPodType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodDeviceState; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodDriverState; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; import info.nightscout.androidaps.plugins.pump.omnipod.events.EventOmnipodDeviceStatusChange; @@ -49,26 +45,22 @@ public class OmnipodUtil { private final OmnipodPumpStatus omnipodPumpStatus; private final ActivePluginProvider activePlugins; private final SP sp; - private final HasAndroidInjector injector; private boolean lowLevelDebug = true; private OmnipodCommandType currentCommand; private Gson gsonInstance = createGson(); - //private static PodSessionState podSessionState; - //private static PodDeviceState podDeviceState; private OmnipodPodType omnipodPodType; private OmnipodDriverState driverState = OmnipodDriverState.NotInitalized; - @Inject public OmnipodUtil( AAPSLogger aapsLogger, RxBusWrapper rxBus, RileyLinkUtil rileyLinkUtil, OmnipodPumpStatus omnipodPumpStatus, + PodStateManager podStateManager, SP sp, - ActivePluginProvider activePlugins, - HasAndroidInjector injector + ActivePluginProvider activePlugins ) { this.aapsLogger = aapsLogger; this.rxBus = rxBus; @@ -76,25 +68,20 @@ public class OmnipodUtil { this.omnipodPumpStatus = omnipodPumpStatus; this.sp = sp; this.activePlugins = activePlugins; - this.injector = injector; } - public boolean isLowLevelDebug() { return lowLevelDebug; } - public void setLowLevelDebug(boolean lowLevelDebug) { this.lowLevelDebug = lowLevelDebug; } - public OmnipodCommandType getCurrentCommand() { return currentCommand; } - public void setCurrentCommand(OmnipodCommandType currentCommand) { this.currentCommand = currentCommand; @@ -109,12 +96,10 @@ public class OmnipodUtil { MainApp.gs(R.string.omnipod_error_operation_not_possible_no_configuration), (Runnable) null); } - public OmnipodDriverState getDriverState() { return driverState; } - public void setDriverState(OmnipodDriverState state) { if (driverState == state) return; @@ -132,7 +117,6 @@ public class OmnipodUtil { // } } - private Gson createGson() { GsonBuilder gsonBuilder = new GsonBuilder() .registerTypeAdapter(DateTime.class, (JsonSerializer) (dateTime, typeOfSrc, context) -> @@ -147,10 +131,8 @@ public class OmnipodUtil { return gsonBuilder.create(); } + public void notifyDeviceStatusChanged() { - public void setPodSessionState(PodSessionState podSessionState) { - omnipodPumpStatus.podSessionState = podSessionState; - rxBus.send(new EventOmnipodDeviceStatusChange(podSessionState)); } @@ -158,37 +140,26 @@ public class OmnipodUtil { omnipodPumpStatus.podDeviceState = podDeviceState; } - public void setOmnipodPodType(OmnipodPodType omnipodPodType) { this.omnipodPodType = omnipodPodType; } - public OmnipodPodType getOmnipodPodType() { return this.omnipodPodType; } - public PodDeviceState getPodDeviceState() { return omnipodPumpStatus.podDeviceState; } - - public PodSessionState getPodSessionState() { - return omnipodPumpStatus.podSessionState; - } - - public boolean isOmnipodEros() { return this.activePlugins.getActivePump().model() == PumpType.Insulet_Omnipod; } - public boolean isOmnipodDash() { return this.activePlugins.getActivePump().model() == PumpType.Insulet_Omnipod_Dash; } - public void setPumpType(PumpType pumpType_) { omnipodPumpStatus.pumpType = pumpType_; } @@ -197,33 +168,10 @@ public class OmnipodUtil { return omnipodPumpStatus.pumpType; } - public Gson getGsonInstance() { return this.gsonInstance; } - public Integer getNextPodAddress() { - if (sp.contains(OmnipodConst.Prefs.NextPodAddress)) { - int nextPodAddress = sp.getInt(OmnipodConst.Prefs.NextPodAddress, 0); - if (OmnipodManager.isValidAddress(nextPodAddress)) { - return nextPodAddress; - } - } - return null; - } - - public boolean hasNextPodAddress() { - return getNextPodAddress() != null; - } - - public void setNextPodAddress(int address) { - sp.putInt(OmnipodConst.Prefs.NextPodAddress, address); - } - - public void removeNextPodAddress() { - sp.remove(OmnipodConst.Prefs.NextPodAddress); - } - public AAPSLogger getAapsLogger() { return this.aapsLogger; } @@ -231,25 +179,4 @@ public class OmnipodUtil { public SP getSp() { return this.sp; } - - public PodSessionState loadSessionState() { - PodSessionState podSessionState = null; - - String storedPodState = sp.getString(OmnipodConst.Prefs.PodState, ""); - if (StringUtils.isEmpty(storedPodState)) { - aapsLogger.info(LTag.PUMP, "PodSessionState-SP: no PodSessionState present in SharedPreferences"); - } else { - aapsLogger.info(LTag.PUMP, "PodSessionState-SP: loaded from SharedPreferences: " + storedPodState); - try { - podSessionState = gsonInstance.fromJson(storedPodState, PodSessionState.class); - podSessionState.injectDaggerClass(injector); - } catch (Exception ex) { - aapsLogger.error(LTag.PUMPCOMM, "Could not deserialize Pod state", ex); - } - } - - setPodSessionState(podSessionState); - - return podSessionState; - } } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod_dash/comm/OmnipodDashCommunicationManager.java b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod_dash/comm/OmnipodDashCommunicationManager.java index 4f869bd286..db594e6af1 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod_dash/comm/OmnipodDashCommunicationManager.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod_dash/comm/OmnipodDashCommunicationManager.java @@ -11,7 +11,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.comm.message.response.pod import info.nightscout.androidaps.plugins.pump.omnipod.defs.OmnipodCommunicationManagerInterface; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitActionType; import info.nightscout.androidaps.plugins.pump.omnipod.defs.PodInitReceiver; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodSessionState; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.state.PodStateManager; import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; /** @@ -34,7 +34,7 @@ public class OmnipodDashCommunicationManager implements OmnipodCommunicationMana // RileyLinkConst.Prefs.LastGoodDeviceCommunicationTime, 0L); } - private PodSessionState getPodSessionState() { + private PodStateManager getPodStateManager() { return null; } @@ -114,11 +114,6 @@ public class OmnipodDashCommunicationManager implements OmnipodCommunicationMana return null; } - @Override - public void setPumpStatus(OmnipodPumpStatus pumpStatusLocal) { - - } - @Override public PodInfoRecentPulseLog readPulseLog() { return null; diff --git a/app/src/main/res/layout/omnipod_fragment.xml b/app/src/main/res/layout/omnipod_fragment.xml index 2068f90557..c1ac656f2d 100644 --- a/app/src/main/res/layout/omnipod_fragment.xml +++ b/app/src/main/res/layout/omnipod_fragment.xml @@ -26,8 +26,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:paddingBottom="5dp" android:paddingTop="2dp" + android:paddingBottom="5dp" android:visibility="gone"> @@ -93,10 +93,10 @@ @@ -119,8 +119,8 @@ android:layout_height="wrap_content" android:layout_weight="0" android:gravity="center_horizontal" - android:paddingEnd="2dp" android:paddingStart="2dp" + android:paddingEnd="2dp" android:text=":" android:textSize="14sp" /> @@ -133,12 +133,118 @@ android:paddingLeft="5dp" android:textColor="@android:color/white" android:textSize="14sp" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -175,7 +281,7 @@ - + @@ -212,7 +318,6 @@ android:textColor="@android:color/white" android:textSize="14sp" /> - @@ -270,10 +375,10 @@ @@ -316,10 +421,10 @@ @@ -361,10 +466,10 @@ @@ -406,10 +511,10 @@ @@ -432,8 +537,8 @@ android:layout_height="wrap_content" android:layout_weight="0" android:gravity="center_horizontal" - android:paddingEnd="2dp" android:paddingStart="2dp" + android:paddingEnd="2dp" android:text=":" android:textSize="14sp" /> @@ -453,10 +558,10 @@ @@ -498,10 +603,10 @@ @@ -543,10 +648,10 @@ @@ -621,8 +726,7 @@ android:drawableTop="@drawable/icon_cp_bolus_correction" android:paddingLeft="0dp" android:paddingRight="0dp" - android:text="@string/omnipod_read_pulse_log_short" - /> + android:text="@string/omnipod_read_pulse_log_short" /> diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9f0a23abb0..73f101749e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1863,9 +1863,11 @@ Over 50 U Pod Address Pod Expires - No info - No Pod connected - Not initialized + No Pod connected + Pod setup in progress + Pod not initialized + !!! Pod Fault + Pod running Active Pod Alerts Ack Alerts %1$.2f %2$s (%3$s) @@ -1982,5 +1984,8 @@ Unable to verify whether the bolus succeeded. Please verify that your Pod is bolusing or cancel the bolus. RL Stats Pulse Log + LOT + TID + PM / PI version diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/AapsPodStateManagerTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/AapsPodStateManagerTest.java new file mode 100644 index 0000000000..cd82ae9ea5 --- /dev/null +++ b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/AapsPodStateManagerTest.java @@ -0,0 +1,100 @@ +package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; + +import org.joda.time.DateTime; +import org.joda.time.DateTimeUtils; +import org.joda.time.DateTimeZone; +import org.joda.time.Duration; +import org.junit.After; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.powermock.modules.junit4.PowerMockRunner; + +import info.nightscout.androidaps.logging.AAPSLogger; +import info.nightscout.androidaps.plugins.bus.RxBusWrapper; +import info.nightscout.androidaps.plugins.pump.omnipod.defs.FirmwareVersion; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.OmnipodPumpStatus; +import info.nightscout.androidaps.plugins.pump.omnipod.driver.comm.AapsPodStateManager; +import info.nightscout.androidaps.utils.resources.ResourceHelper; +import info.nightscout.androidaps.utils.sharedPreferences.SP; + +import static org.junit.Assert.assertEquals; + +@RunWith(PowerMockRunner.class) +public class AapsPodStateManagerTest { + @Mock AAPSLogger aapsLogger; + @Mock SP sp; + @Mock OmnipodPumpStatus omnipodPumpStatus; + RxBusWrapper rxBus = new RxBusWrapper(); + @Mock ResourceHelper resourceHelper; + + @Test + public void times() { + DateTimeZone timeZone = DateTimeZone.UTC; + DateTimeZone.setDefault(timeZone); + + DateTime now = new DateTime(2020, 1, 1, 1, 2, 3, timeZone); + + DateTimeUtils.setCurrentMillisFixed(now.getMillis()); + + AapsPodStateManager podStateManager = new AapsPodStateManager(aapsLogger, sp, omnipodPumpStatus, rxBus, resourceHelper); + podStateManager.initState(0x0); + podStateManager.setPairingParameters(0, 0, new FirmwareVersion(1, 1, 1), + new FirmwareVersion(2, 2, 2), timeZone); + + assertEquals(now, podStateManager.getTime()); + assertEquals(Duration.standardHours(1).plus(Duration.standardMinutes(2).plus(Duration.standardSeconds(3))), podStateManager.getScheduleOffset()); + } + + @Test + public void changeSystemTimeZoneWithoutChangingPodTimeZone() { + DateTimeZone timeZone = DateTimeZone.UTC; + DateTimeZone.setDefault(timeZone); + + DateTime now = new DateTime(2020, 1, 1, 1, 2, 3, timeZone); + + DateTimeUtils.setCurrentMillisFixed(now.getMillis()); + + AapsPodStateManager podStateManager = new AapsPodStateManager(aapsLogger, sp, omnipodPumpStatus, rxBus, resourceHelper); + podStateManager.initState(0x0); + podStateManager.setPairingParameters(0, 0, new FirmwareVersion(1, 1, 1), + new FirmwareVersion(2, 2, 2), timeZone); + + DateTimeZone newTimeZone = DateTimeZone.forOffsetHours(2); + DateTimeZone.setDefault(newTimeZone); + + // The system time zone has been updated, but the pod session state's time zone hasn't + // So the pods time should not have been changed + assertEquals(now, podStateManager.getTime()); + assertEquals(Duration.standardHours(1).plus(Duration.standardMinutes(2).plus(Duration.standardSeconds(3))), podStateManager.getScheduleOffset()); + } + + @Test + public void changeSystemTimeZoneAndChangePodTimeZone() { + DateTimeZone timeZone = DateTimeZone.UTC; + DateTimeZone.setDefault(timeZone); + + DateTime now = new DateTime(2020, 1, 1, 1, 2, 3, timeZone); + + DateTimeUtils.setCurrentMillisFixed(now.getMillis()); + + AapsPodStateManager podStateManager = new AapsPodStateManager(aapsLogger, sp, omnipodPumpStatus, rxBus, resourceHelper); + podStateManager.initState(0x0); + podStateManager.setPairingParameters(0, 0, new FirmwareVersion(1, 1, 1), + new FirmwareVersion(2, 2, 2), timeZone); + + DateTimeZone newTimeZone = DateTimeZone.forOffsetHours(2); + DateTimeZone.setDefault(newTimeZone); + podStateManager.setTimeZone(newTimeZone); + + // Both the system time zone have been updated + // So the pods time should have been changed (to +2 hours) + assertEquals(now.withZone(newTimeZone), podStateManager.getTime()); + assertEquals(Duration.standardHours(3).plus(Duration.standardMinutes(2).plus(Duration.standardSeconds(3))), podStateManager.getScheduleOffset()); + } + + @After + public void tearDown() { + DateTimeUtils.setCurrentMillisSystem(); + } +} \ No newline at end of file diff --git a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSessionStateTest.java b/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSessionStateTest.java deleted file mode 100644 index a7ba9cb861..0000000000 --- a/app/src/test/java/info/nightscout/androidaps/plugins/pump/omnipod/defs/state/PodSessionStateTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package info.nightscout.androidaps.plugins.pump.omnipod.defs.state; - -import org.joda.time.DateTime; -import org.joda.time.DateTimeUtils; -import org.joda.time.DateTimeZone; -import org.joda.time.Duration; -import org.junit.After; -import org.junit.Ignore; -import org.junit.Test; -import org.mockito.Mock; - -import dagger.android.HasAndroidInjector; -import info.nightscout.androidaps.plugins.pump.omnipod.defs.FirmwareVersion; - -import static org.junit.Assert.assertEquals; - -public class PodSessionStateTest { - @Mock HasAndroidInjector hasAndroidInjector; - - @Test - @Ignore("Not Dagger compliant") // FIXME - public void times() { - DateTimeZone timeZone = DateTimeZone.UTC; - DateTimeZone.setDefault(timeZone); - - DateTime now = new DateTime(2020, 1, 1, 1, 2, 3, timeZone); - DateTime initialized = now.minus(Duration.standardDays(1)); - - DateTimeUtils.setCurrentMillisFixed(now.getMillis()); - - PodSessionState podSessionState = new PodSessionState(timeZone, 0x0, - new FirmwareVersion(1, 1, 1), - new FirmwareVersion(2, 2, 2), - 0, 0, 0, 0, hasAndroidInjector); - - assertEquals(now, podSessionState.getTime()); - assertEquals(Duration.standardHours(1).plus(Duration.standardMinutes(2).plus(Duration.standardSeconds(3))), podSessionState.getScheduleOffset()); - } - - @Test - @Ignore("Not Dagger compliant") // FIXME - public void changeSystemTimeZoneWithoutChangingPodTimeZone() { - DateTimeZone timeZone = DateTimeZone.UTC; - DateTimeZone.setDefault(timeZone); - - DateTime now = new DateTime(2020, 1, 1, 1, 2, 3, timeZone); - DateTime initialized = now.minus(Duration.standardDays(1)); - - DateTimeUtils.setCurrentMillisFixed(now.getMillis()); - - PodSessionState podSessionState = new PodSessionState(timeZone, 0x0, - new FirmwareVersion(1, 1, 1), - new FirmwareVersion(2, 2, 2), - 0, 0, 0, 0, hasAndroidInjector); - - DateTimeZone newTimeZone = DateTimeZone.forOffsetHours(2); - DateTimeZone.setDefault(newTimeZone); - - // The system time zone has been updated, but the pod session state's time zone hasn't - // So the pods time should not have been changed - assertEquals(now, podSessionState.getTime()); - assertEquals(Duration.standardHours(1).plus(Duration.standardMinutes(2).plus(Duration.standardSeconds(3))), podSessionState.getScheduleOffset()); - } - - @Test - @Ignore("Not Dagger compliant") // FIXME - public void changeSystemTimeZoneAndChangePodTimeZone() { - DateTimeZone timeZone = DateTimeZone.UTC; - DateTimeZone.setDefault(timeZone); - - DateTime now = new DateTime(2020, 1, 1, 1, 2, 3, timeZone); - DateTime initialized = now.minus(Duration.standardDays(1)); - - DateTimeUtils.setCurrentMillisFixed(now.getMillis()); - - PodSessionState podSessionState = new PodSessionState(timeZone, 0x0, - new FirmwareVersion(1, 1, 1), - new FirmwareVersion(2, 2, 2), - 0, 0, 0, 0, hasAndroidInjector); - - DateTimeZone newTimeZone = DateTimeZone.forOffsetHours(2); - DateTimeZone.setDefault(newTimeZone); - podSessionState.setTimeZone(newTimeZone); - - // Both the system time zone have been updated - // So the pods time should have been changed (to +2 hours) - assertEquals(now.withZone(newTimeZone), podSessionState.getTime()); - assertEquals(Duration.standardHours(3).plus(Duration.standardMinutes(2).plus(Duration.standardSeconds(3))), podSessionState.getScheduleOffset()); - } - - @After - public void tearDown() { - DateTimeUtils.setCurrentMillisSystem(); - } -} \ No newline at end of file