Ignore active SN for VirtualPump, try to resolve Combo issue

This commit is contained in:
Milos Kozak 2022-10-03 16:18:15 +02:00
parent 9227053447
commit 3f3cdde53b
7 changed files with 124 additions and 34 deletions

View file

@ -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) }
}
}
}

View file

@ -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 ->

View file

@ -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.
*
* <p>
* For boluses, the logic is to request a bolus and then read it back from the history to see what was
* actually delivered.
*
* <p>
* 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.
*
* <p>
* 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

View file

@ -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

View file

@ -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);
}
})

View file

@ -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);
}
}

View file

@ -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);