From 22d78f356b490a7f24ce0d8ead21a6d1b9fd43f0 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 24 Jun 2021 22:37:29 +0200 Subject: [PATCH 01/15] recover pod activation status when lost during activation --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 9 ++++++- .../pod/state/OmnipodDashPodStateManager.kt | 6 +++++ .../state/OmnipodDashPodStateManagerImpl.kt | 26 ++++++++++++++++++- .../dash/ui/OmnipodDashOverviewFragment.kt | 17 ++++++------ 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 6851f3a7ff..5898ce8688 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -130,7 +130,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } override fun getPumpStatus(reason: String) { - if (reason != "REQUESTED BY USER" && !podStateManager.isActivationCompleted) { + if (reason != "REQUESTED BY USER" && !podStateManager.isActivationCompleted) { // prevent races on BLE when the pod is not activated return } @@ -140,6 +140,13 @@ class OmnipodDashPumpPlugin @Inject constructor( aapsLogger.error(LTag.PUMP, "Error in getPumpStatus", throwable) } else { aapsLogger.info(LTag.PUMP, "getPumpStatus executed with success") + if (!podStateManager.isActivationCompleted) { + val msg = podStateManager.recoverActivationFromPodStatus() + msg?.let { + // TODO: show dialog with "try again, the pod is busy now" + aapsLogger.info(LTag.PUMP, "recoverActivationFromPodStatus msg=$msg") + } + } } } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index 15fcd4f84e..9a7b094846 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -96,6 +96,12 @@ interface OmnipodDashPodStateManager { fun createLastBolus(requestedUnits: Double, historyId: String, bolusType: DetailedBolusInfo.BolusType) fun markLastBolusComplete(): LastBolus? fun onStart() + /* + This is called only:. It overwrites activationStatus + - when activation was interrupted(application crash, killed, etc) + - after getPodStatus was successful(we have an up-to-date podStatus) + */ + fun recoverActivationFromPodStatus(): String? data class ActiveCommand( val sequence: Short, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 2da1889ba9..96aa31a78c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -312,6 +312,29 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } } + override fun recoverActivationFromPodStatus(): String? { + val newActivationProgress = when (podState.podStatus) { + PodStatus.FILLED -> + ActivationProgress.NOT_STARTED + PodStatus.UID_SET -> + ActivationProgress.SET_UNIQUE_ID + PodStatus.ENGAGING_CLUTCH_DRIVE, PodStatus.PRIMING -> + return "Busy" + PodStatus.CLUTCH_DRIVE_ENGAGED -> + ActivationProgress.PRIME_COMPLETED + PodStatus.BASAL_PROGRAM_SET -> + ActivationProgress.PROGRAMMED_BASAL + PodStatus.RUNNING_ABOVE_MIN_VOLUME, PodStatus.RUNNING_BELOW_MIN_VOLUME -> + ActivationProgress.CANNULA_INSERTED + else -> + null + } + newActivationProgress?.let { + podState.activationProgress = it + } + return null + } + @Synchronized override fun updateActiveCommand() = Maybe.create { source -> val activeCommand = podState.activeCommand @@ -402,6 +425,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.lastStatusResponseReceived = now + 2 podState.activeCommand = newCommand } + CommandSendingNotConfirmed -> { val now = System.currentTimeMillis() val newCommand = podState.activeCommand?.copy( @@ -410,10 +434,10 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( ) podState.lastStatusResponseReceived = 0 } + CommandSendingFailure, NoActiveCommand -> podState.activeCommand = null } - } override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index b9d0103e8c..64b2a22b70 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -296,7 +296,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // Update time on Pod // TODO: For now: derive from podStateManager.minutesSinceActivation val timeOnPod = getTimeOnPod() - podInfoBinding.timeOnPod.text = podStateManager.time?.let{ + podInfoBinding.timeOnPod.text = podStateManager.time?.let { readableZonedTime(it) } ?: PLACEHOLDER @@ -304,13 +304,12 @@ class OmnipodDashOverviewFragment : DaggerFragment() { podStateManager.timeBehind?.let { if (it.abs().isLongerThan(Duration.standardMinutes(MAX_TIME_DEVIATION_MINUTES))) { Color.RED - }else { + } else { Color.WHITE } } ?: Color.WHITE ) - // Update Pod expiry time val expiresAt = getExpiryAt() if (expiresAt == null) { @@ -318,11 +317,13 @@ class OmnipodDashOverviewFragment : DaggerFragment() { podInfoBinding.podExpiryDate.setTextColor(Color.WHITE) } else { podInfoBinding.podExpiryDate.text = readableZonedTime(expiresAt) - podInfoBinding.podExpiryDate.setTextColor(if (DateTime.now().isAfter(expiresAt)) { - Color.RED - } else { - Color.WHITE - }) + podInfoBinding.podExpiryDate.setTextColor( + if (DateTime.now().isAfter(expiresAt)) { + Color.RED + } else { + Color.WHITE + } + ) } podStateManager.alarmType?.let { From 19ff58ac95d119b80ae3ac109eb812d52aab431b Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 24 Jun 2021 23:08:32 +0200 Subject: [PATCH 02/15] fix timeOnPod --- .../dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 96aa31a78c..a8fcd7844f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -189,7 +189,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( if ((activationTime != null) && (minutesSinceActivation != null)) { return DateTime(activationTime) .plusMinutes(minutesSinceActivation.toInt()) - .plus(Duration(podState.lastStatusResponseReceived, System.currentTimeMillis())) + .plus(Duration(podState.lastUpdatedSystem, System.currentTimeMillis())) } return null } From 3ed9cd0f78d854b9c63e6784308ff95a71f3f572 Mon Sep 17 00:00:00 2001 From: Theo van Elsberg Date: Fri, 25 Jun 2021 13:40:32 +0200 Subject: [PATCH 03/15] - Fixed loading PodState (failed to serialize) - Moved Pod expiry time calculation to Pod Manager/PodState - Show local date/time in overview (TODO: handle TZ) --- .../pod/state/OmnipodDashPodStateManager.kt | 3 +- .../state/OmnipodDashPodStateManagerImpl.kt | 16 +++- .../dash/ui/OmnipodDashOverviewFragment.kt | 73 ++++++++----------- 3 files changed, 47 insertions(+), 45 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index 9a7b094846..fd6d1f5aff 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -35,11 +35,12 @@ interface OmnipodDashPodStateManager { val isPodKaput: Boolean var bluetoothConnectionState: BluetoothConnectionState - var timeZone: DateTimeZone + var timeZone: String val lastUpdatedSystem: Long // System.currentTimeMillis() val lastStatusResponseReceived: Long val time: DateTime? val timeBehind: Duration? + val expiry: DateTime? val messageSequenceNumber: Short val sequenceNumberOfLastProgrammingCommand: Short? diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index a8fcd7844f..5414606941 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -99,7 +99,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } } - override var timeZone: DateTimeZone + override var timeZone: String get() = podState.timeZone set(tz) { podState.timeZone = tz @@ -199,6 +199,18 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( return Duration(DateTime.now(), time) } + override val expiry: DateTime? + // TODO: Consider storing expiry datetime in pod state saving continuesly recalculating to the same value + get() { + val podLifeInHours = podLifeInHours + val minutesSinceActivation = minutesSinceActivation + if (podLifeInHours != null && minutesSinceActivation != null) { + val expiresInMinutes = podLifeInHours * 60 - minutesSinceActivation + return DateTime().plusMinutes(expiresInMinutes) + } + return null + } + override var bluetoothConnectionState: OmnipodDashPodStateManager.BluetoothConnectionState get() = podState.bluetoothConnectionState set(bluetoothConnectionState) { @@ -589,7 +601,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var ltk: ByteArray? = null var eapAkaSequenceNumber: Long = 1 var bolusPulsesRemaining: Short = 0 - var timeZone = DateTimeZone.getDefault() + var timeZone: String = "" // DateTimeZone.getDefault() var bleVersion: SoftwareVersion? = null var firmwareVersion: SoftwareVersion? = null diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 64b2a22b70..972bdaa418 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -237,31 +237,6 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } } - // Get time on pod from activation time and minutes since activation - private fun getTimeOnPod(): DateTime? { - var timeOnPod: DateTime? = null - val minutesSinceActivation = podStateManager.minutesSinceActivation - val activationTime = podStateManager.activationTime - if ((activationTime != null) && (minutesSinceActivation != null)) { - timeOnPod = DateTime(activationTime) - .plusMinutes(minutesSinceActivation.toInt()) - .plus(Duration(podStateManager.lastStatusResponseReceived, System.currentTimeMillis())) - } - return timeOnPod - } - - // TODO: Consider storing expiry datetime in pod state saving continuesly recalculating to the same value - private fun getExpiryAt(): DateTime? { - var expiresAt: DateTime? = null - val podLifeInHours = podStateManager.podLifeInHours - val minutesSinceActivation = podStateManager.minutesSinceActivation - if (podLifeInHours != null && minutesSinceActivation != null) { - val expiresInMinutes = podLifeInHours * 60 - minutesSinceActivation - expiresAt = DateTime().plusMinutes(expiresInMinutes) - } - return expiresAt - } - private fun updateOmnipodStatus() { updateLastConnection() updateLastBolus() @@ -294,8 +269,6 @@ class OmnipodDashOverviewFragment : DaggerFragment() { ) // Update time on Pod - // TODO: For now: derive from podStateManager.minutesSinceActivation - val timeOnPod = getTimeOnPod() podInfoBinding.timeOnPod.text = podStateManager.time?.let { readableZonedTime(it) } ?: PLACEHOLDER @@ -311,7 +284,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { ) // Update Pod expiry time - val expiresAt = getExpiryAt() + val expiresAt = podStateManager.expiry if (expiresAt == null) { podInfoBinding.podExpiryDate.text = PLACEHOLDER podInfoBinding.podExpiryDate.setTextColor(Color.WHITE) @@ -631,25 +604,41 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } } - private fun getTimeZone(): DateTimeZone { - // TODO: Get timezone as configured/podState - // return getSafe(() -> podState.getTimeZone()); - return DateTimeZone.getDefault() + // private fun getTimeZone(): DateTimeZone { + // // return getSafe(() -> podState.getTimeZone()); + // return podStateManager.timeZone + // } + private fun getTimeZone(): String { + // Return timezone ID (e.g "Europe/Amsterdam") + return podStateManager.timeZone } private fun readableZonedTime(time: DateTime): String { val timeAsJavaData = time.toLocalDateTime().toDate() + return dateUtil.dateAndTimeString(timeAsJavaData.time) - val timeZone = getTimeZone().toTimeZone() - if (timeZone == TimeZone.getDefault()) { - return dateUtil.dateAndTimeString(timeAsJavaData.time) - } - - // Get full timezoned time - val isDaylightTime = timeZone.inDaylightTime(timeAsJavaData) - val locale = resources.configuration.locales.get(0) - val timeZoneDisplayName = timeZone.getDisplayName(isDaylightTime, TimeZone.SHORT, locale) + " " + timeZone.getDisplayName(isDaylightTime, TimeZone.LONG, locale) - return resourceHelper.gs(R.string.omnipod_common_time_with_timezone, dateUtil.dateAndTimeString(timeAsJavaData.time), timeZoneDisplayName) + // // TODO: Handle timeZone ID + // val timeZone = getTimeZone() + // if (timeZone == "") { + // // No timezone defined, use local time (default) + // return dateUtil.dateAndTimeString(timeAsJavaData.time) + // } + // else { + // // Get full timezoned time + // val isDaylightTime = timeZone.inDaylightTime(timeAsJavaData) + // val locale = resources.configuration.locales.get(0) + // val timeZoneDisplayName = + // timeZone.getDisplayName(isDaylightTime, TimeZone.SHORT, locale) + " " + timeZone.getDisplayName( + // isDaylightTime, + // TimeZone.LONG, + // locale + // ) + // return resourceHelper.gs( + // R.string.omnipod_common_time_with_timezone, + // dateUtil.dateAndTimeString(timeAsJavaData.time), + // timeZoneDisplayName + // ) + // } } private fun readableDuration(duration: Duration): String { From b82d9cf457ec9fdd741931308ba36e9cddb60559 Mon Sep 17 00:00:00 2001 From: Theo van Elsberg Date: Fri, 25 Jun 2021 14:37:54 +0200 Subject: [PATCH 04/15] - Redo Pod expiry datetime based on activation time --- .../driver/pod/state/OmnipodDashPodStateManagerImpl.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 5414606941..b57c8a3eb0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -203,10 +203,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( // TODO: Consider storing expiry datetime in pod state saving continuesly recalculating to the same value get() { val podLifeInHours = podLifeInHours - val minutesSinceActivation = minutesSinceActivation - if (podLifeInHours != null && minutesSinceActivation != null) { - val expiresInMinutes = podLifeInHours * 60 - minutesSinceActivation - return DateTime().plusMinutes(expiresInMinutes) + val activationTime = podState.activationTime + if (podLifeInHours != null && activationTime != null) { + return DateTime(podState.activationTime).plusHours(podLifeInHours.toInt()) } return null } @@ -601,7 +600,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var ltk: ByteArray? = null var eapAkaSequenceNumber: Long = 1 var bolusPulsesRemaining: Short = 0 - var timeZone: String = "" // DateTimeZone.getDefault() + var timeZone: String = "" // TimeZone ID (e.g. "Europe/Amsterdam") var bleVersion: SoftwareVersion? = null var firmwareVersion: SoftwareVersion? = null From d882428cc0d83c7c87467e790487f1d7a7869129 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 19:45:38 +0200 Subject: [PATCH 05/15] set timezone --- .../pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt | 3 +++ .../dash/driver/pod/state/OmnipodDashPodStateManager.kt | 2 +- .../dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt | 6 +++--- .../pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index 78b778def9..63cfb403ae 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -425,6 +425,9 @@ class OmnipodDashManagerImpl @Inject constructor( observeConnectToPod, observeSendProgramBasalCommand(basalProgram, hasBasalBeepEnabled) ) + .doOnComplete { + podStateManager.timeZone = TimeZone.getDefault() + } // TODO these would be common for any observable returned in a public function in this class .doOnNext(PodEventInterceptor()) .doOnError(ErrorInterceptor()) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index fd6d1f5aff..fce985edc2 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -35,7 +35,7 @@ interface OmnipodDashPodStateManager { val isPodKaput: Boolean var bluetoothConnectionState: BluetoothConnectionState - var timeZone: String + var timeZone: TimeZone val lastUpdatedSystem: Long // System.currentTimeMillis() val lastStatusResponseReceived: Long val time: DateTime? diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index b57c8a3eb0..03bf7468e5 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -99,10 +99,10 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } } - override var timeZone: String - get() = podState.timeZone + override var timeZone: TimeZone + get() = TimeZone.getTimeZone(podState.timeZone) set(tz) { - podState.timeZone = tz + podState.timeZone = tz.getDisplayName(true, TimeZone.SHORT) store() } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 972bdaa418..e524444513 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -608,7 +608,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { // // return getSafe(() -> podState.getTimeZone()); // return podStateManager.timeZone // } - private fun getTimeZone(): String { + private fun getTimeZone(): TimeZone { // Return timezone ID (e.g "Europe/Amsterdam") return podStateManager.timeZone } From efd3acbb2a8beb3fd65a67baa23876ea4ee7792b Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 20:52:32 +0200 Subject: [PATCH 06/15] save tx after setting basal. save basal in pod state when the basal command is confirmed --- .../omnipod/dash/driver/OmnipodDashManagerImpl.kt | 9 ++++----- .../driver/pod/state/OmnipodDashPodStateManager.kt | 2 +- .../pod/state/OmnipodDashPodStateManagerImpl.kt | 13 +++++-------- .../omnipod/dash/ui/DashPodManagementActivity.kt | 2 +- .../omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 6 ++---- 5 files changed, 13 insertions(+), 19 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index 63cfb403ae..487ecf2c6c 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -173,8 +173,7 @@ class OmnipodDashManagerImpl @Inject constructor( DefaultStatusResponse::class ) }.doOnComplete { - // TODO: remove podStateManager.basalProgram? - podStateManager.basalProgram = basalProgram + podStateManager.timeZone = TimeZone.getDefault() } } @@ -246,6 +245,7 @@ class OmnipodDashManagerImpl @Inject constructor( observeVerifyPrime.doOnComplete(ActivationProgressUpdater(ActivationProgress.PRIME_COMPLETED)) ) } + if (podStateManager.activationProgress.isBefore(ActivationProgress.PRIMING)) { observables.add(observeConnectToPod) // connection can time out while waiting observables.add( @@ -270,6 +270,7 @@ class OmnipodDashManagerImpl @Inject constructor( }.doOnComplete(ActivationProgressUpdater(ActivationProgress.PRIMING)) ) } + if (podStateManager.activationProgress.isBefore(ActivationProgress.REPROGRAMMED_LUMP_OF_COAL_ALERT)) { observables.add( observeSendProgramAlertsCommand( @@ -304,6 +305,7 @@ class OmnipodDashManagerImpl @Inject constructor( ).doOnComplete(ActivationProgressUpdater(ActivationProgress.PROGRAMMED_LOW_RESERVOIR_ALERTS)) ) } + if (podStateManager.activationProgress.isBefore(ActivationProgress.SET_UNIQUE_ID)) { observables.add( observeSendSetUniqueIdCommand.doOnComplete(ActivationProgressUpdater(ActivationProgress.SET_UNIQUE_ID)) @@ -425,9 +427,6 @@ class OmnipodDashManagerImpl @Inject constructor( observeConnectToPod, observeSendProgramBasalCommand(basalProgram, hasBasalBeepEnabled) ) - .doOnComplete { - podStateManager.timeZone = TimeZone.getDefault() - } // TODO these would be common for any observable returned in a public function in this class .doOnNext(PodEventInterceptor()) .doOnError(ErrorInterceptor()) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index fce985edc2..3eeab834ad 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -39,7 +39,7 @@ interface OmnipodDashPodStateManager { val lastUpdatedSystem: Long // System.currentTimeMillis() val lastStatusResponseReceived: Long val time: DateTime? - val timeBehind: Duration? + val timeDrift: Duration? val expiry: DateTime? val messageSequenceNumber: Short diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 03bf7468e5..95df4367a7 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -194,13 +194,13 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( return null } - override val timeBehind: Duration? + override val timeDrift: Duration? get() { return Duration(DateTime.now(), time) } override val expiry: DateTime? - // TODO: Consider storing expiry datetime in pod state saving continuesly recalculating to the same value + // TODO: Consider storing expiry datetime in pod state saving continuously recalculating to the same value get() { val podLifeInHours = podLifeInHours val activationTime = podState.activationTime @@ -466,6 +466,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.lastUpdatedSystem = System.currentTimeMillis() podState.lastStatusResponseReceived = SystemClock.elapsedRealtime() updateLastBolusFromResponse(response.bolusPulsesRemaining) + if (podState.activationTime == null) { + podState.activationTime = System.currentTimeMillis() - (response.minutesSinceActivation * 60000) + } store() rxBus.send(EventOmnipodDashPumpValuesChanged()) @@ -514,12 +517,6 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.uniqueId = response.uniqueIdReceivedInCommand podState.lastUpdatedSystem = System.currentTimeMillis() - // TODO: what is considered to be the pod activation time? - // LTK negotiation ? - // setUniqueId? - // compute it from the number of "minutesOnPod"? - podState.activationTime = System.currentTimeMillis() - store() rxBus.send(EventOmnipodDashPumpValuesChanged()) } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/DashPodManagementActivity.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/DashPodManagementActivity.kt index e3f6f97138..3d89be5da8 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/DashPodManagementActivity.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/DashPodManagementActivity.kt @@ -125,7 +125,7 @@ class DashPodManagementActivity : NoSplashAppCompatActivity() { binding.buttonActivatePod.isEnabled = podStateManager.activationProgress.isBefore(ActivationProgress.COMPLETED) binding.buttonDeactivatePod.isEnabled = - podStateManager.activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID) || + podStateManager.ltk != null || podStateManager.podStatus == PodStatus.ALARM if (podStateManager.activationProgress.isAtLeast(ActivationProgress.PHASE_1_COMPLETED)) { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index e524444513..80b14e98b3 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -45,7 +45,6 @@ import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.plusAssign import org.apache.commons.lang3.StringUtils import org.joda.time.DateTime -import org.joda.time.DateTimeZone import org.joda.time.Duration import java.util.* import javax.inject.Inject @@ -69,7 +68,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { private const val REFRESH_INTERVAL_MILLIS = 15 * 1000L // 15 seconds private const val PLACEHOLDER = "-" - private const val MAX_TIME_DEVIATION_MINUTES = 15L + private const val MAX_TIME_DEVIATION_MINUTES = 10L } private var disposables: CompositeDisposable = CompositeDisposable() @@ -274,7 +273,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { } ?: PLACEHOLDER podInfoBinding.timeOnPod.setTextColor( - podStateManager.timeBehind?.let { + podStateManager.timeDrift?.let { if (it.abs().isLongerThan(Duration.standardMinutes(MAX_TIME_DEVIATION_MINUTES))) { Color.RED } else { @@ -526,7 +525,6 @@ class OmnipodDashOverviewFragment : DaggerFragment() { private fun updateRefreshStatusButton() { buttonBinding.buttonRefreshStatus.isEnabled = podStateManager.isUniqueIdSet && - podStateManager.activationProgress.isAtLeast(ActivationProgress.PHASE_1_COMPLETED) && isQueueEmpty() } From 989a20d02305800148634f082f6b608d277581a7 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 21:38:01 +0200 Subject: [PATCH 07/15] less notifications on unconfirmed commands when switching profile --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 5898ce8688..49364229ea 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -269,7 +269,7 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventTempBasalChange()) } .ignoreElements() - ).doFinally { + ).doOnComplete() { notifyOnUnconfirmed( Notification.FAILED_UPDATE_PROFILE, "Suspend delivery is unconfirmed! " + From a62b5f7f7018747ddcfec44bc69511da76e66309 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 21:50:25 +0200 Subject: [PATCH 08/15] dismiss notifications --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 49364229ea..2a2c38ee30 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -884,7 +884,7 @@ class OmnipodDashPumpPlugin @Inject constructor( .ignoreElements() ).doFinally { notifyOnUnconfirmed( - Notification.PUMP_ERROR, + Notification.FAILED_UPDATE_PROFILE, "Unconfirmed resumeDelivery command. Please refresh pod status", R.raw.boluserror ) @@ -1013,6 +1013,7 @@ class OmnipodDashPumpPlugin @Inject constructor( ) } rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) + rxBus.send(EventDismissNotification(Notification.FAILED_UPDATE_PROFILE)) } OmnipodCommandType.SET_TEMPORARY_BASAL -> { From 8f5ecfd0d6e39d6bf9e69f7f5ac32c6cb885f987 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 22:14:05 +0200 Subject: [PATCH 09/15] restart service discovery --- .../pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt | 1 + .../omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt index 284b6d975d..664db805e0 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/ServiceDiscoverer.kt @@ -21,6 +21,7 @@ class ServiceDiscoverer( */ fun discoverServices(): Map { logger.debug(LTag.PUMPBTCOMM, "Discovering services") + bleCallbacks.startServiceDiscovery() val discover = gatt.discoverServices() if (!discover) { throw ConnectException("Could not start discovering services`") diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt index de2fceafe9..3d4d3d1339 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/comm/callbacks/BleCommCallbacks.kt @@ -61,6 +61,10 @@ class BleCommCallbacks( } } + fun startServiceDiscovery() { + serviceDiscoveryComplete = CountDownLatch(1) + } + fun waitForServiceDiscovery(timeoutMs: Int) { try { serviceDiscoveryComplete.await(timeoutMs.toLong(), TimeUnit.MILLISECONDS) From 4e4cc4cdfa2f16693fe25ce2f7bc710f10c89213 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 22:39:05 +0200 Subject: [PATCH 10/15] pumpSync on new pod --- .../viewmodel/action/DashInsertCannulaViewModel.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index c7bc85a539..fcff9a9e3d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -2,13 +2,17 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.ui.wizard.activatio import androidx.annotation.StringRes import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.data.PumpEnactResult import info.nightscout.androidaps.interfaces.ProfileFunction +import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.plugins.pump.common.defs.PumpType import info.nightscout.androidaps.plugins.pump.omnipod.common.ui.wizard.activation.viewmodel.action.InsertCannulaViewModel import info.nightscout.androidaps.plugins.pump.omnipod.dash.R import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager +import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.state.OmnipodDashPodStateManager import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram import io.reactivex.Single import io.reactivex.rxkotlin.subscribeBy @@ -17,6 +21,8 @@ import javax.inject.Inject class DashInsertCannulaViewModel @Inject constructor( private val omnipodManager: OmnipodDashManager, private val profileFunction: ProfileFunction, + private val pumpSync: PumpSync, + private val podStateManager: OmnipodDashPodStateManager, injector: HasAndroidInjector, logger: AAPSLogger ) : InsertCannulaViewModel(injector, logger) { @@ -52,6 +58,13 @@ class DashInsertCannulaViewModel @Inject constructor( }, onComplete = { logger.debug("Pod activation part 2 completed") + pumpSync.connectNewPump() + pumpSync.insertTherapyEventIfNewWithTimestamp( + timestamp = System.currentTimeMillis(), + type = DetailedBolusInfo.EventType.CANNULA_CHANGE, + pumpType = PumpType.OMNIPOD_DASH, + pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" + ) source.onSuccess(PumpEnactResult(injector).success(true)) } ) From 80c24a23dcf0b32c0a2f1b19c379f32cc0d0ef39 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 23:26:38 +0200 Subject: [PATCH 11/15] do not display last connection if the pod is not activated --- .../pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 80b14e98b3..59e90ef7dc 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -386,9 +386,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { podInfoBinding.lastConnection.setTextColor(lastConnectionColor) } else { podInfoBinding.lastConnection.setTextColor(Color.WHITE) - podInfoBinding.lastConnection.text = readableDuration( - Duration(podStateManager.lastUpdatedSystem, System.currentTimeMillis()) - ) + podInfoBinding.lastConnection.text = PLACEHOLDER } } From c803f6504bd36eac84cd869e53769d61255aaa3d Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 25 Jun 2021 23:34:38 +0200 Subject: [PATCH 12/15] add both INSULIN and CANULA change --- .../viewmodel/action/DashInsertCannulaViewModel.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index fcff9a9e3d..143fb8fb91 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -65,6 +65,12 @@ class DashInsertCannulaViewModel @Inject constructor( pumpType = PumpType.OMNIPOD_DASH, pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" ) + pumpSync.insertTherapyEventIfNewWithTimestamp( + timestamp = System.currentTimeMillis(), + type = DetailedBolusInfo.EventType.INSULIN_CHANGE, + pumpType = PumpType.OMNIPOD_DASH, + pumpSerial = podStateManager.uniqueId?.toString() ?: "n/a" + ) source.onSuccess(PumpEnactResult(injector).success(true)) } ) From 2a35c60e81eb71f995763052cabc3aff64e010e4 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 26 Jun 2021 11:10:19 +0200 Subject: [PATCH 13/15] notification on pod suspend. try to getpodstatus on activecommands --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 86 +++++++++++++++++-- 1 file changed, 77 insertions(+), 9 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 2a2c38ee30..197921ae76 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -1,6 +1,8 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash import android.content.Context +import android.os.Handler +import android.os.Looper import dagger.android.HasAndroidInjector import info.nightscout.androidaps.activities.ErrorHelperActivity.Companion.runAlarm import info.nightscout.androidaps.data.DetailedBolusInfo @@ -19,6 +21,7 @@ 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.defs.PumpType +import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.omnipod.common.definition.OmnipodCommandType import info.nightscout.androidaps.plugins.pump.omnipod.common.queue.command.* import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.OmnipodDashManager @@ -67,10 +70,14 @@ class OmnipodDashPumpPlugin @Inject constructor( commandQueue: CommandQueueProvider ) : PumpPluginBase(pluginDescription, injector, aapsLogger, resourceHelper, commandQueue), Pump { @Volatile var bolusCanceled = false + private val handler: Handler = Handler(Looper.getMainLooper()) + lateinit private var statusChecker: Runnable + var nextPodWarningCheck : Long = 0 companion object { private const val BOLUS_RETRY_INTERVAL_MS = 2000.toLong() - private const val BOLUS_RETRIES = 5 // numer of retries for cancel/get bolus status + private const val BOLUS_RETRIES = 5 // number of retries for cancel/get bolus status + private const val STATUS_CHECK_INTERVAL_MS = (60L * 1000) private val pluginDescription = PluginDescription() .mainType(PluginType.PUMP) @@ -84,6 +91,52 @@ class OmnipodDashPumpPlugin @Inject constructor( private val pumpDescription = PumpDescription(PumpType.OMNIPOD_DASH) } + init { + statusChecker = Runnable { + refreshStatusOnUnacknowledgedCommands() + updatePodWarnings() + handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) + } + } + + private fun updatePodWarnings() { + if (System.currentTimeMillis() > nextPodWarningCheck) { + if (!podStateManager.isPodRunning) { + val notification = + Notification( + Notification.OMNIPOD_POD_NOT_ATTACHED, + "Pod not activated", + Notification.NORMAL + ) + rxBus.send(EventNewNotification(notification)) + } else { + rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_NOT_ATTACHED)) + if (podStateManager.isSuspended) { + val notification = + Notification( + Notification.OMNIPOD_POD_SUSPENDED, + "Insulin delivery suspended", + Notification.NORMAL + ) + rxBus.send(EventNewNotification(notification)) + } else { + rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) + // TODO: time out of sync notification? + } + } + nextPodWarningCheck = DateTimeUtil.getTimeInFutureFromMinutes(15) + } + } + + private fun refreshStatusOnUnacknowledgedCommands() { + if (podStateManager.isPodRunning && + podStateManager.activeCommand != null && + commandQueue.size() == 0 && + commandQueue.performing() == null) { + commandQueue.readStatus("Unconfirmed command", null) + } + } + override fun isInitialized(): Boolean { // TODO return true @@ -129,6 +182,8 @@ class OmnipodDashPumpPlugin @Inject constructor( // TODO } + + override fun getPumpStatus(reason: String) { if (reason != "REQUESTED BY USER" && !podStateManager.isActivationCompleted) { // prevent races on BLE when the pod is not activated @@ -279,16 +334,15 @@ class OmnipodDashPumpPlugin @Inject constructor( } } - /* override fun onStop() { - super.onStop() - disposable.clear() - } - - */ - override fun onStart() { super.onStart() podStateManager.onStart() + handler.postDelayed(statusChecker, STATUS_CHECK_INTERVAL_MS) + } + + override fun onStop() { + super.onStop() + handler.removeCallbacks(statusChecker) } private fun observeDeliverySuspended(): Completable = Completable.defer { @@ -979,7 +1033,19 @@ class OmnipodDashPumpPlugin @Inject constructor( val historyEntry = history.getById(command.historyId) aapsLogger.debug(LTag.PUMPCOMM, "handling command confirmation: $confirmation") when (historyEntry.commandType) { - OmnipodCommandType.CANCEL_TEMPORARY_BASAL, + OmnipodCommandType.CANCEL_TEMPORARY_BASAL -> { + if (confirmation.success) { + pumpSync.syncStopTemporaryBasalWithPumpId( + historyEntry.createdAt, + historyEntry.pumpId(), + PumpType.OMNIPOD_DASH, + serialNumber() + ) + podStateManager.tempBasal = null + } + rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) + + } OmnipodCommandType.RESUME_DELIVERY -> { // We can't invalidate this command, // and this is why it is pumpSync-ed at this point @@ -991,6 +1057,7 @@ class OmnipodDashPumpPlugin @Inject constructor( serialNumber() ) podStateManager.tempBasal = null + rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) } rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) } @@ -1011,6 +1078,7 @@ class OmnipodDashPumpPlugin @Inject constructor( PumpType.OMNIPOD_DASH, serialNumber() ) + rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) } rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) rxBus.send(EventDismissNotification(Notification.FAILED_UPDATE_PROFILE)) From b9acc21633b2d6cb82d61ebef09865d3bfad6434 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 26 Jun 2021 11:40:01 +0200 Subject: [PATCH 14/15] update notifications --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 197921ae76..bd69f261fb 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -1079,9 +1079,9 @@ class OmnipodDashPumpPlugin @Inject constructor( serialNumber() ) rxBus.send(EventDismissNotification(Notification.OMNIPOD_POD_SUSPENDED)) + rxBus.send(EventDismissNotification(Notification.FAILED_UPDATE_PROFILE)) + rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) } - rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) - rxBus.send(EventDismissNotification(Notification.FAILED_UPDATE_PROFILE)) } OmnipodCommandType.SET_TEMPORARY_BASAL -> { From cb45e51b990f41d043fb6a8e163787a253ec9890 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 26 Jun 2021 15:06:57 +0200 Subject: [PATCH 15/15] add logging. try to prevent race condition --- .../pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index bd69f261fb..df8f87a507 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -185,6 +185,7 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun getPumpStatus(reason: String) { + aapsLogger.debug(LTag.PUMP, "getPumpStatus reason=$reason") if (reason != "REQUESTED BY USER" && !podStateManager.isActivationCompleted) { // prevent races on BLE when the pod is not activated return @@ -263,6 +264,7 @@ class OmnipodDashPumpPlugin @Inject constructor( if (!podStateManager.isActivationCompleted) { return PumpEnactResult(injector).success(true).enacted(true) } + aapsLogger.debug(LTag.PUMP, "setNewBasalProfile profile=$profile") val basalProgram = mapProfileToBasalProgram(profile) var deliverySuspended = false return executeProgrammingCommand( @@ -324,7 +326,7 @@ class OmnipodDashPumpPlugin @Inject constructor( rxBus.send(EventTempBasalChange()) } .ignoreElements() - ).doOnComplete() { + ).doOnComplete { notifyOnUnconfirmed( Notification.FAILED_UPDATE_PROFILE, "Suspend delivery is unconfirmed! " + @@ -734,10 +736,11 @@ class OmnipodDashPumpPlugin @Inject constructor( executeProgrammingCommand( historyEntry = history.createRecord(OmnipodCommandType.CANCEL_TEMPORARY_BASAL), command = omnipodManager.stopTempBasal(hasTempBasalBeepEnabled()).ignoreElements() - ).doFinally { + ).doOnComplete { notifyOnUnconfirmed( Notification.OMNIPOD_TBR_ALERTS, - "Setting temp basal failed. If a temp basal was previously running, it might have been cancelled. " + + "Cancelling temp basal might have failed." + + "If a temp basal was previously running, it might have been cancelled." + "Please manually refresh the Pod status from the Omnipod tab.", // TODO: i8n R.raw.boluserror, ) @@ -795,6 +798,7 @@ class OmnipodDashPumpPlugin @Inject constructor( private fun notifyOnUnconfirmed(notificationId: Int, msg: String, sound: Int?) { if (podStateManager.activeCommand != null) { + aapsLogger.debug(LTag.PUMP, "Notification for active command: ${podStateManager.activeCommand}") showNotification(notificationId, msg, Notification.URGENT, sound) } } @@ -1044,7 +1048,6 @@ class OmnipodDashPumpPlugin @Inject constructor( podStateManager.tempBasal = null } rxBus.send(EventDismissNotification(Notification.OMNIPOD_TBR_ALERTS)) - } OmnipodCommandType.RESUME_DELIVERY -> { // We can't invalidate this command,