From 3f3cdde53bcff139515cf9cdfb9bb5dbd68a4ca2 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Mon, 3 Oct 2022 16:18:15 +0200 Subject: [PATCH] Ignore active SN for VirtualPump, try to resolve Combo issue --- .../plugins/aps/loop/LoopFragment.kt | 2 +- .../plugins/pump/PumpSyncImplementation.kt | 107 +++++++++++++++--- .../plugins/pump/combo/ComboPlugin.java | 15 +-- .../androidaps/interfaces/PumpSync.kt | 28 ++++- .../androidaps/danar/AbstractDanaRPlugin.java | 2 +- .../activities/InsightPairingActivity.java | 2 +- .../eros/manager/AapsOmnipodErosManager.java | 2 +- 7 files changed, 124 insertions(+), 34 deletions(-) rename {core => app}/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt (82%) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt index 1d44fa75d0..eaaee1c41e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/aps/loop/LoopFragment.kt @@ -66,7 +66,7 @@ class LoopFragment : DaggerFragment(), MenuProvider { setColorSchemeColors(rh.gac(context, R.attr.colorPrimaryDark), rh.gac(context, R.attr.colorPrimary), rh.gac(context, R.attr.colorSecondary)) setOnRefreshListener { binding.lastrun.text = rh.gs(R.string.executing) - handler.post { loop.invoke("Loop swiperefresh", true) } + handler.post { loop.invoke("Loop swipe refresh", true) } } } } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt b/app/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt similarity index 82% rename from core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt rename to app/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt index 9e4f9fb189..83704b9489 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt @@ -5,20 +5,44 @@ import info.nightscout.androidaps.data.DetailedBolusInfo import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.embedments.InterfaceIDs -import info.nightscout.androidaps.database.entities.* -import info.nightscout.androidaps.database.transactions.* +import info.nightscout.androidaps.database.entities.Bolus +import info.nightscout.androidaps.database.entities.Carbs +import info.nightscout.androidaps.database.entities.ExtendedBolus +import info.nightscout.androidaps.database.entities.TemporaryBasal +import info.nightscout.androidaps.database.entities.TherapyEvent +import info.nightscout.androidaps.database.entities.TotalDailyDose +import info.nightscout.androidaps.database.entities.UserEntry +import info.nightscout.androidaps.database.entities.ValueWithUnit +import info.nightscout.androidaps.database.transactions.InsertBolusWithTempIdTransaction +import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampCarbsTransaction +import info.nightscout.androidaps.database.transactions.InsertIfNewByTimestampTherapyEventTransaction +import info.nightscout.androidaps.database.transactions.InsertTemporaryBasalWithTempIdTransaction +import info.nightscout.androidaps.database.transactions.InsertTherapyEventAnnouncementTransaction +import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalTransaction +import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalTransactionWithPumpId +import info.nightscout.androidaps.database.transactions.InvalidateTemporaryBasalWithTempIdTransaction +import info.nightscout.androidaps.database.transactions.SyncBolusWithTempIdTransaction +import info.nightscout.androidaps.database.transactions.SyncPumpBolusTransaction +import info.nightscout.androidaps.database.transactions.SyncPumpCancelExtendedBolusIfAnyTransaction +import info.nightscout.androidaps.database.transactions.SyncPumpCancelTemporaryBasalIfAnyTransaction +import info.nightscout.androidaps.database.transactions.SyncPumpExtendedBolusTransaction +import info.nightscout.androidaps.database.transactions.SyncPumpTemporaryBasalTransaction +import info.nightscout.androidaps.database.transactions.SyncPumpTotalDailyDoseTransaction +import info.nightscout.androidaps.database.transactions.SyncTemporaryBasalWithTempIdTransaction +import info.nightscout.androidaps.interfaces.ActivePlugin import info.nightscout.androidaps.interfaces.ProfileFunction import info.nightscout.androidaps.interfaces.PumpSync -import info.nightscout.shared.logging.AAPSLogger -import info.nightscout.shared.logging.LTag +import info.nightscout.androidaps.interfaces.ResourceHelper import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.notifications.Notification import info.nightscout.androidaps.plugins.pump.common.defs.PumpType +import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.T -import info.nightscout.androidaps.interfaces.ResourceHelper +import info.nightscout.shared.logging.AAPSLogger +import info.nightscout.shared.logging.LTag import info.nightscout.shared.sharedPreferences.SP import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.kotlin.plusAssign @@ -32,7 +56,8 @@ class PumpSyncImplementation @Inject constructor( private val rh: ResourceHelper, private val profileFunction: ProfileFunction, private val repository: AppRepository, - private val uel: UserEntryLogger + private val uel: UserEntryLogger, + private val activePlugin: ActivePlugin ) : PumpSync { private val disposable = CompositeDisposable() @@ -51,6 +76,15 @@ class PumpSyncImplementation @Inject constructor( sp.remove(R.string.key_active_pump_change_timestamp) } + override fun verifyPumpIdentification(type: PumpType, serialNumber: String): Boolean { + val storedType = sp.getString(R.string.key_active_pump_type, "") + val storedSerial = sp.getString(R.string.key_active_pump_serial_number, "") + if (activePlugin.activePump is VirtualPumpPlugin) return true + if (type.description == storedType && serialNumber == storedSerial) return true + aapsLogger.debug(LTag.PUMP, "verifyPumpIdentification failed for $type $serialNumber") + return false + } + /** * Check if data is coming from currently active pump to prevent overlapping pump histories * @@ -73,14 +107,19 @@ class PumpSyncImplementation @Inject constructor( return timestamp > dateUtil.now() - T.mins(1).msecs() // allow first record to be 1 min old } - if (type.description == storedType && serialNumber == storedSerial && timestamp >= storedTimestamp) { + if (activePlugin.activePump is VirtualPumpPlugin || (type.description == storedType && serialNumber == storedSerial && timestamp >= storedTimestamp)) { // data match return true } if (showNotification && (type.description != storedType || serialNumber != storedSerial) && timestamp >= storedTimestamp) rxBus.send(EventNewNotification(Notification(Notification.WRONG_PUMP_DATA, rh.gs(R.string.wrong_pump_data), Notification.URGENT))) - aapsLogger.error(LTag.PUMP, "Ignoring pump history record Allowed: ${dateUtil.dateAndTimeAndSecondsString(storedTimestamp)} $storedType $storedSerial Received: $timestamp ${dateUtil.dateAndTimeAndSecondsString(timestamp)} ${type.description} $serialNumber") + aapsLogger.error( + LTag.PUMP, + "Ignoring pump history record Allowed: ${dateUtil.dateAndTimeAndSecondsString(storedTimestamp)} $storedType $storedSerial Received: $timestamp ${ + dateUtil.dateAndTimeAndSecondsString(timestamp) + } ${type.description} $serialNumber" + ) return false } @@ -100,7 +139,7 @@ class PumpSyncImplementation @Inject constructor( isAbsolute = temporaryBasal.value.isAbsolute, type = PumpSync.TemporaryBasalType.fromDbType(temporaryBasal.value.type), pumpId = temporaryBasal.value.interfaceIDs.pumpId, - pumpType = temporaryBasal.value.interfaceIDs.pumpType?.let { PumpType.fromDbPumpType(it)} ?: PumpType.USER, + pumpType = temporaryBasal.value.interfaceIDs.pumpType?.let { PumpType.fromDbPumpType(it) } ?: PumpType.USER, pumpSerial = temporaryBasal.value.interfaceIDs.pumpSerial ?: "", ) else null, @@ -111,7 +150,7 @@ class PumpSyncImplementation @Inject constructor( duration = extendedBolus.value.duration, amount = extendedBolus.value.amount, rate = extendedBolus.value.rate, - pumpType = extendedBolus.value.interfaceIDs.pumpType?.let { PumpType.fromDbPumpType(it)} ?: PumpType.USER, + pumpType = extendedBolus.value.interfaceIDs.pumpType?.let { PumpType.fromDbPumpType(it) } ?: PumpType.USER, pumpSerial = extendedBolus.value.interfaceIDs.pumpSerial ?: "" ) else null, @@ -203,7 +242,8 @@ class PumpSyncImplementation @Inject constructor( interfaceIDs_backing = InterfaceIDs( pumpId = pumpId, pumpType = pumpType.toDbPumpType(), - pumpSerial = pumpSerial) + pumpSerial = pumpSerial + ) ) repository.runTransactionForResult(InsertIfNewByTimestampCarbsTransaction(carbs)) .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Carbs", it) } @@ -228,7 +268,8 @@ class PumpSyncImplementation @Inject constructor( interfaceIDs_backing = InterfaceIDs( pumpId = pumpId, pumpType = pumpType.toDbPumpType(), - pumpSerial = pumpSerial) + pumpSerial = pumpSerial + ) ) uel.log(UserEntry.Action.CAREPORTAL, pumpType.source, note, ValueWithUnit.Timestamp(timestamp), ValueWithUnit.TherapyEventType(type.toDBbEventType())) repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent)) @@ -252,7 +293,16 @@ class PumpSyncImplementation @Inject constructor( * TEMPORARY BASALS */ - override fun syncTemporaryBasalWithPumpId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, type: PumpSync.TemporaryBasalType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { + override fun syncTemporaryBasalWithPumpId( + timestamp: Long, + rate: Double, + duration: Long, + isAbsolute: Boolean, + type: PumpSync.TemporaryBasalType?, + pumpId: Long, + pumpType: PumpType, + pumpSerial: String + ): Boolean { if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false val temporaryBasal = TemporaryBasal( timestamp = timestamp, @@ -289,7 +339,16 @@ class PumpSyncImplementation @Inject constructor( } } - override fun addTemporaryBasalWithTempId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, tempId: Long, type: PumpSync.TemporaryBasalType, pumpType: PumpType, pumpSerial: String): Boolean { + override fun addTemporaryBasalWithTempId( + timestamp: Long, + rate: Double, + duration: Long, + isAbsolute: Boolean, + tempId: Long, + type: PumpSync.TemporaryBasalType, + pumpType: PumpType, + pumpSerial: String + ): Boolean { if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false val temporaryBasal = TemporaryBasal( timestamp = timestamp, @@ -312,7 +371,17 @@ class PumpSyncImplementation @Inject constructor( } } - override fun syncTemporaryBasalWithTempId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, temporaryId: Long, type: PumpSync.TemporaryBasalType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean { + override fun syncTemporaryBasalWithTempId( + timestamp: Long, + rate: Double, + duration: Long, + isAbsolute: Boolean, + temporaryId: Long, + type: PumpSync.TemporaryBasalType?, + pumpId: Long?, + pumpType: PumpType, + pumpSerial: String + ): Boolean { if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false val bolus = TemporaryBasal( timestamp = timestamp, @@ -349,8 +418,12 @@ class PumpSyncImplementation @Inject constructor( } override fun invalidateTemporaryBasalWithPumpId(pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { - repository.runTransactionForResult(InvalidateTemporaryBasalTransactionWithPumpId(pumpId, pumpType.toDbPumpType(), - pumpSerial)) + repository.runTransactionForResult( + InvalidateTemporaryBasalTransactionWithPumpId( + pumpId, pumpType.toDbPumpType(), + pumpSerial + ) + ) .doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating TemporaryBasal", it) } .blockingGet() .also { result -> diff --git a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java index 0c70619feb..bc40358970 100644 --- a/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java +++ b/combo/src/main/java/info/nightscout/androidaps/plugins/pump/combo/ComboPlugin.java @@ -38,6 +38,7 @@ import info.nightscout.androidaps.interfaces.Pump; import info.nightscout.androidaps.interfaces.PumpDescription; import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpSync; +import info.nightscout.androidaps.interfaces.ResourceHelper; import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.common.ManufacturerType; import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; @@ -61,17 +62,16 @@ import info.nightscout.androidaps.plugins.pump.common.defs.PumpType; import info.nightscout.androidaps.utils.DateUtil; import info.nightscout.androidaps.utils.InstanceId; import info.nightscout.androidaps.utils.T; -import info.nightscout.androidaps.interfaces.ResourceHelper; import info.nightscout.shared.logging.AAPSLogger; import info.nightscout.shared.logging.LTag; import info.nightscout.shared.sharedPreferences.SP; /** * Driver for the Roche Accu-Chek Combo pump, using the ruffy app for BT communication. - * + *

* For boluses, the logic is to request a bolus and then read it back from the history to see what was * actually delivered. - * + *

* TBR-handling doesn't read the pump history. On the pump, TBR records are only created after a TBR has finished. * So when a TBR is started on the pump, it can't be known when it started until the TBR ends or is cancelled. * Cancelling would assume a user works against the loop, and creating a temporary TBR (AAPS-side) and updating it @@ -85,7 +85,7 @@ import info.nightscout.shared.sharedPreferences.SP; * This approach skipped implementing edge-cases that pose no real risk, in part due to limited resources to * implement every edge-case scenario. Insulin amount given via boluses are significantly higher, so the * priority was there to make that as safe as possible. - * + *

* Created by mike on 05.08.2016. */ @Singleton @@ -424,11 +424,12 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { String lastKnownSN = serialNumber(); if (!lastKnownSN.equals(fakeSerialNumber()) && !lastKnownSN.equals(macAddress)) { getAapsLogger().info(LTag.PUMP, "Pump serial number changed " + lastKnownSN + " -> " + macAddress); - pumpSync.connectNewPump(); + pumpSync.connectNewPump(true); } sp.putString(R.string.combo_pump_serial, macAddress); } - + if (!pumpSync.verifyPumpIdentification(pumpDescription.getPumpType(), serialNumber())) + pumpSync.connectNewPump(true); // ComboFragment updates state fully only after the pump has initialized, // so force an update after initialization completed rxBus.send(new EventComboPumpUpdateGUI()); @@ -566,7 +567,7 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints { return new PumpEnactResult(getInjector()).success(true).enacted(false); } - EventOverviewBolusProgress.Treatment treatment = new EventOverviewBolusProgress.Treatment(0.0, 0,detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB, detailedBolusInfo.getId()); + EventOverviewBolusProgress.Treatment treatment = new EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo.getBolusType() == DetailedBolusInfo.BolusType.SMB, detailedBolusInfo.getId()); EventOverviewBolusProgress.INSTANCE.setT(treatment); // start bolus delivery diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt index 4a6662608f..a81d3fda36 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt @@ -27,13 +27,19 @@ interface PumpSync { * * Call this function when new pump is paired to accept data from new pump * to prevent overlapping pump histories - * @param endRunning if true end previous running TBR and EB + * @param endRunning if true end previous running TBR and EB */ - // @JvmOverloads and default value impossible on interface - // replace by `fun connectNewPump(endRunning: Boolean = true)` after full conversion to kotlin - fun connectNewPump(endRunning: Boolean) - fun connectNewPump() = connectNewPump(true) + fun connectNewPump(endRunning: Boolean = true) + + /** + * Verify if current pump type and SN is properly registered + * @param type current PumpType + * @param serialNumber current serial number + * + * @return true if type and SN match to last call of connectNewPump + */ + fun verifyPumpIdentification(type: PumpType, serialNumber: String): Boolean /* * GENERAL STATUS @@ -355,7 +361,17 @@ interface PumpSync { * @param pumpSerial pump serial number * @return true if record is successfully updated **/ - fun syncTemporaryBasalWithTempId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, temporaryId: Long, type: TemporaryBasalType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean + fun syncTemporaryBasalWithTempId( + timestamp: Long, + rate: Double, + duration: Long, + isAbsolute: Boolean, + temporaryId: Long, + type: TemporaryBasalType?, + pumpId: Long?, + pumpType: PumpType, + pumpSerial: String + ): Boolean /** * Invalidate of temporary basals that failed to start diff --git a/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java b/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java index 77588a77bf..881eda371f 100644 --- a/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java +++ b/danar/src/main/java/info/nightscout/androidaps/danar/AbstractDanaRPlugin.java @@ -110,7 +110,7 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump .subscribe(event -> { if (event.isChanged(getRh(), R.string.key_danar_bt_name)) { danaPump.reset(); - pumpSync.connectNewPump(); + pumpSync.connectNewPump(true); getCommandQueue().readStatus(getRh().gs(R.string.device_changed), null); } }) diff --git a/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java b/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java index e88086499b..fda0450c1f 100644 --- a/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java +++ b/insight/src/main/java/info/nightscout/androidaps/plugins/pump/insight/activities/InsightPairingActivity.java @@ -74,7 +74,7 @@ public class InsightPairingActivity extends NoSplashAppCompatActivity implements service.registerStateCallback(InsightPairingActivity.this); service.registerExceptionCallback(InsightPairingActivity.this); onStateChanged(service.getState()); - pumpSync.connectNewPump(); + pumpSync.connectNewPump(true); } } diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java index 26a5a3445d..d017a7e7d2 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/manager/AapsOmnipodErosManager.java @@ -209,7 +209,7 @@ public class AapsOmnipodErosManager { addToHistory(System.currentTimeMillis(), PodHistoryEntryType.INSERT_CANNULA, result.getComment(), result.getSuccess()); if (result.getSuccess()) { - pumpSync.connectNewPump(); + pumpSync.connectNewPump(true); uploadCareportalEvent(System.currentTimeMillis() - 1000, DetailedBolusInfo.EventType.INSULIN_CHANGE); uploadCareportalEvent(System.currentTimeMillis(), DetailedBolusInfo.EventType.CANNULA_CHANGE);