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)) setColorSchemeColors(rh.gac(context, R.attr.colorPrimaryDark), rh.gac(context, R.attr.colorPrimary), rh.gac(context, R.attr.colorSecondary))
setOnRefreshListener { setOnRefreshListener {
binding.lastrun.text = rh.gs(R.string.executing) 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.AppRepository
import info.nightscout.androidaps.database.ValueWrapper import info.nightscout.androidaps.database.ValueWrapper
import info.nightscout.androidaps.database.embedments.InterfaceIDs import info.nightscout.androidaps.database.embedments.InterfaceIDs
import info.nightscout.androidaps.database.entities.* import info.nightscout.androidaps.database.entities.Bolus
import info.nightscout.androidaps.database.transactions.* 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.ProfileFunction
import info.nightscout.androidaps.interfaces.PumpSync import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.shared.logging.AAPSLogger import info.nightscout.androidaps.interfaces.ResourceHelper
import info.nightscout.shared.logging.LTag
import info.nightscout.androidaps.logging.UserEntryLogger import info.nightscout.androidaps.logging.UserEntryLogger
import info.nightscout.androidaps.plugins.bus.RxBus import info.nightscout.androidaps.plugins.bus.RxBus
import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification import info.nightscout.androidaps.plugins.general.overview.events.EventNewNotification
import info.nightscout.androidaps.plugins.general.overview.notifications.Notification 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.defs.PumpType
import info.nightscout.androidaps.plugins.pump.virtual.VirtualPumpPlugin
import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.DateUtil
import info.nightscout.androidaps.utils.T 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 info.nightscout.shared.sharedPreferences.SP
import io.reactivex.rxjava3.disposables.CompositeDisposable import io.reactivex.rxjava3.disposables.CompositeDisposable
import io.reactivex.rxjava3.kotlin.plusAssign import io.reactivex.rxjava3.kotlin.plusAssign
@ -32,7 +56,8 @@ class PumpSyncImplementation @Inject constructor(
private val rh: ResourceHelper, private val rh: ResourceHelper,
private val profileFunction: ProfileFunction, private val profileFunction: ProfileFunction,
private val repository: AppRepository, private val repository: AppRepository,
private val uel: UserEntryLogger private val uel: UserEntryLogger,
private val activePlugin: ActivePlugin
) : PumpSync { ) : PumpSync {
private val disposable = CompositeDisposable() private val disposable = CompositeDisposable()
@ -51,6 +76,15 @@ class PumpSyncImplementation @Inject constructor(
sp.remove(R.string.key_active_pump_change_timestamp) 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 * 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 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 // data match
return true return true
} }
if (showNotification && (type.description != storedType || serialNumber != storedSerial) && timestamp >= storedTimestamp) 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))) 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 return false
} }
@ -100,7 +139,7 @@ class PumpSyncImplementation @Inject constructor(
isAbsolute = temporaryBasal.value.isAbsolute, isAbsolute = temporaryBasal.value.isAbsolute,
type = PumpSync.TemporaryBasalType.fromDbType(temporaryBasal.value.type), type = PumpSync.TemporaryBasalType.fromDbType(temporaryBasal.value.type),
pumpId = temporaryBasal.value.interfaceIDs.pumpId, 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 ?: "", pumpSerial = temporaryBasal.value.interfaceIDs.pumpSerial ?: "",
) )
else null, else null,
@ -111,7 +150,7 @@ class PumpSyncImplementation @Inject constructor(
duration = extendedBolus.value.duration, duration = extendedBolus.value.duration,
amount = extendedBolus.value.amount, amount = extendedBolus.value.amount,
rate = extendedBolus.value.rate, 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 ?: "" pumpSerial = extendedBolus.value.interfaceIDs.pumpSerial ?: ""
) )
else null, else null,
@ -203,7 +242,8 @@ class PumpSyncImplementation @Inject constructor(
interfaceIDs_backing = InterfaceIDs( interfaceIDs_backing = InterfaceIDs(
pumpId = pumpId, pumpId = pumpId,
pumpType = pumpType.toDbPumpType(), pumpType = pumpType.toDbPumpType(),
pumpSerial = pumpSerial) pumpSerial = pumpSerial
)
) )
repository.runTransactionForResult(InsertIfNewByTimestampCarbsTransaction(carbs)) repository.runTransactionForResult(InsertIfNewByTimestampCarbsTransaction(carbs))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Carbs", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Carbs", it) }
@ -228,7 +268,8 @@ class PumpSyncImplementation @Inject constructor(
interfaceIDs_backing = InterfaceIDs( interfaceIDs_backing = InterfaceIDs(
pumpId = pumpId, pumpId = pumpId,
pumpType = pumpType.toDbPumpType(), pumpType = pumpType.toDbPumpType(),
pumpSerial = pumpSerial) pumpSerial = pumpSerial
)
) )
uel.log(UserEntry.Action.CAREPORTAL, pumpType.source, note, ValueWithUnit.Timestamp(timestamp), ValueWithUnit.TherapyEventType(type.toDBbEventType())) uel.log(UserEntry.Action.CAREPORTAL, pumpType.source, note, ValueWithUnit.Timestamp(timestamp), ValueWithUnit.TherapyEventType(type.toDBbEventType()))
repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent)) repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent))
@ -252,7 +293,16 @@ class PumpSyncImplementation @Inject constructor(
* TEMPORARY BASALS * 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 if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
val temporaryBasal = TemporaryBasal( val temporaryBasal = TemporaryBasal(
timestamp = timestamp, 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 if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
val temporaryBasal = TemporaryBasal( val temporaryBasal = TemporaryBasal(
timestamp = timestamp, 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 if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
val bolus = TemporaryBasal( val bolus = TemporaryBasal(
timestamp = timestamp, timestamp = timestamp,
@ -349,8 +418,12 @@ class PumpSyncImplementation @Inject constructor(
} }
override fun invalidateTemporaryBasalWithPumpId(pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { override fun invalidateTemporaryBasalWithPumpId(pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean {
repository.runTransactionForResult(InvalidateTemporaryBasalTransactionWithPumpId(pumpId, pumpType.toDbPumpType(), repository.runTransactionForResult(
pumpSerial)) InvalidateTemporaryBasalTransactionWithPumpId(
pumpId, pumpType.toDbPumpType(),
pumpSerial
)
)
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating TemporaryBasal", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating TemporaryBasal", it) }
.blockingGet() .blockingGet()
.also { result -> .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.PumpDescription;
import info.nightscout.androidaps.interfaces.PumpPluginBase; import info.nightscout.androidaps.interfaces.PumpPluginBase;
import info.nightscout.androidaps.interfaces.PumpSync; import info.nightscout.androidaps.interfaces.PumpSync;
import info.nightscout.androidaps.interfaces.ResourceHelper;
import info.nightscout.androidaps.plugins.bus.RxBus; import info.nightscout.androidaps.plugins.bus.RxBus;
import info.nightscout.androidaps.plugins.common.ManufacturerType; import info.nightscout.androidaps.plugins.common.ManufacturerType;
import info.nightscout.androidaps.plugins.general.overview.events.EventDismissNotification; 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.DateUtil;
import info.nightscout.androidaps.utils.InstanceId; import info.nightscout.androidaps.utils.InstanceId;
import info.nightscout.androidaps.utils.T; import info.nightscout.androidaps.utils.T;
import info.nightscout.androidaps.interfaces.ResourceHelper;
import info.nightscout.shared.logging.AAPSLogger; import info.nightscout.shared.logging.AAPSLogger;
import info.nightscout.shared.logging.LTag; import info.nightscout.shared.logging.LTag;
import info.nightscout.shared.sharedPreferences.SP; import info.nightscout.shared.sharedPreferences.SP;
/** /**
* Driver for the Roche Accu-Chek Combo pump, using the ruffy app for BT communication. * 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 * For boluses, the logic is to request a bolus and then read it back from the history to see what was
* actually delivered. * actually delivered.
* * <p>
* TBR-handling doesn't read the pump history. On the pump, TBR records are only created after a TBR has finished. * 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. * 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 * 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 * 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 * 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. * priority was there to make that as safe as possible.
* * <p>
* Created by mike on 05.08.2016. * Created by mike on 05.08.2016.
*/ */
@Singleton @Singleton
@ -424,11 +424,12 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
String lastKnownSN = serialNumber(); String lastKnownSN = serialNumber();
if (!lastKnownSN.equals(fakeSerialNumber()) && !lastKnownSN.equals(macAddress)) { if (!lastKnownSN.equals(fakeSerialNumber()) && !lastKnownSN.equals(macAddress)) {
getAapsLogger().info(LTag.PUMP, "Pump serial number changed " + lastKnownSN + " -> " + macAddress); getAapsLogger().info(LTag.PUMP, "Pump serial number changed " + lastKnownSN + " -> " + macAddress);
pumpSync.connectNewPump(); pumpSync.connectNewPump(true);
} }
sp.putString(R.string.combo_pump_serial, macAddress); 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, // ComboFragment updates state fully only after the pump has initialized,
// so force an update after initialization completed // so force an update after initialization completed
rxBus.send(new EventComboPumpUpdateGUI()); rxBus.send(new EventComboPumpUpdateGUI());
@ -566,7 +567,7 @@ public class ComboPlugin extends PumpPluginBase implements Pump, Constraints {
return new PumpEnactResult(getInjector()).success(true).enacted(false); 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); EventOverviewBolusProgress.INSTANCE.setT(treatment);
// start bolus delivery // 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 * Call this function when new pump is paired to accept data from new pump
* to prevent overlapping pump histories * 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 fun connectNewPump(endRunning: Boolean = true)
// replace by `fun connectNewPump(endRunning: Boolean = true)` after full conversion to kotlin
fun connectNewPump(endRunning: Boolean) /**
fun connectNewPump() = connectNewPump(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 * GENERAL STATUS
@ -355,7 +361,17 @@ interface PumpSync {
* @param pumpSerial pump serial number * @param pumpSerial pump serial number
* @return true if record is successfully updated * @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 * Invalidate of temporary basals that failed to start

View file

@ -110,7 +110,7 @@ public abstract class AbstractDanaRPlugin extends PumpPluginBase implements Pump
.subscribe(event -> { .subscribe(event -> {
if (event.isChanged(getRh(), R.string.key_danar_bt_name)) { if (event.isChanged(getRh(), R.string.key_danar_bt_name)) {
danaPump.reset(); danaPump.reset();
pumpSync.connectNewPump(); pumpSync.connectNewPump(true);
getCommandQueue().readStatus(getRh().gs(R.string.device_changed), null); 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.registerStateCallback(InsightPairingActivity.this);
service.registerExceptionCallback(InsightPairingActivity.this); service.registerExceptionCallback(InsightPairingActivity.this);
onStateChanged(service.getState()); 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()); addToHistory(System.currentTimeMillis(), PodHistoryEntryType.INSERT_CANNULA, result.getComment(), result.getSuccess());
if (result.getSuccess()) { if (result.getSuccess()) {
pumpSync.connectNewPump(); pumpSync.connectNewPump(true);
uploadCareportalEvent(System.currentTimeMillis() - 1000, DetailedBolusInfo.EventType.INSULIN_CHANGE); uploadCareportalEvent(System.currentTimeMillis() - 1000, DetailedBolusInfo.EventType.INSULIN_CHANGE);
uploadCareportalEvent(System.currentTimeMillis(), DetailedBolusInfo.EventType.CANNULA_CHANGE); uploadCareportalEvent(System.currentTimeMillis(), DetailedBolusInfo.EventType.CANNULA_CHANGE);