sync TBR with temp id

This commit is contained in:
Milos Kozak 2021-05-02 16:08:24 +02:00
parent e48d317d55
commit a9e6cfaa66
7 changed files with 199 additions and 33 deletions

View file

@ -77,7 +77,7 @@ interface PumpSync {
* USAGE: * USAGE:
* Generate unique temporaryId * Generate unique temporaryId
* Call before bolus when no pumpId is known (provide timestamp, amount, temporaryId, type, pumpType, pumpSerial) * Call before bolus when no pumpId is known (provide timestamp, amount, temporaryId, type, pumpType, pumpSerial)
* After reading record from history or completed bolus call syncBolusWithTempId with the same temporaryId provided * After reading record from history or completed bolus call [syncBolusWithTempId] with the same temporaryId provided
* If syncBolusWithTempId is not called afterwards record remains valid and is calculated towards iob * If syncBolusWithTempId is not called afterwards record remains valid and is calculated towards iob
* *
* @param timestamp timestamp of event from pump history * @param timestamp timestamp of event from pump history
@ -276,6 +276,61 @@ interface PumpSync {
**/ **/
fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Create temporary basal with temporary id
*
* Search for combination of temporaryId, PumpType, pumpSerial
*
* If db record doesn't exist, new record is created.
* If exists false is returned and data is ignored
*
* USAGE:
* Generate unique temporaryId
* Call on setting temporary basal when no pumpId is known (provide timestamp, temporaryId, type, pumpType, pumpSerial)
* After reading record from history or completed bolus call [syncTemporaryBasalWithTempId] with the same temporaryId provided
* If syncTemporaryBasalWithTempId is not called afterwards record remains valid and is calculated towards iob
*
* @param timestamp timestamp of event from pump history
* @param rate TBR rate in U/h or % (value of 100% is equal to no TBR)
* @param duration duration in milliseconds
* @param isAbsolute is TBR in U/h or % ?
* @param tempId pump id from history
* @param type type of TBR, from request sent to the driver
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number
* @return true if new record is created
*
* see [info.nightscout.androidaps.database.transactions.InsertTemporaryBasalWithTempIdTransaction]
**/
fun addTemporaryBasalWithTempId(timestamp: Long, rate: Double, duration: Long, isAbsolute: Boolean, tempId: Long, type: TemporaryBasalType, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Synchronization of temporary basal with temporary id
*
* Search for combination of temporaryId, PumpType, pumpSerial
*
* If db record doesn't exist data is ignored and false returned.
* If exists, data is updated, type and pumpId only if provided
* isValid field is preserved
*
* USAGE:
* After reading record from history or completed bolus call syncTemporaryBasalWithTempId and
* provide updated timestamp, rate, duration, pumpId (if known), type (if change needed) with the same temporaryId, pumpType, pumpSerial
*
* @param timestamp timestamp of event from pump history
* @param rate TBR rate in U/h or % (value of 100% is equal to no TBR)
* @param duration duration in milliseconds
* @param isAbsolute is TBR in U/h or % ?
* @param temporaryId temporary id generated when pump id in not know yet
* @param type type of TBR, from request sent to the driver
* @param pumpId pump id from history
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @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
/** /**
* Invalidate of temporary basals that failed to start * Invalidate of temporary basals that failed to start
* EROS specific, replace by setting duration to zero ???? * EROS specific, replace by setting duration to zero ????
@ -284,9 +339,7 @@ interface PumpSync {
* If db record doesn't exist data is ignored and false returned * If db record doesn't exist data is ignored and false returned
* *
* *
* @param pumpId pump id of ending event from history * @param id id of temporary basal
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number
* @return true if running record is found and invalidated * @return true if running record is found and invalidated
**/ **/
fun invalidateTemporaryBasal(id: Long): Boolean fun invalidateTemporaryBasal(id: Long): Boolean

View file

@ -124,11 +124,11 @@ class PumpSyncImplementation @Inject constructor(
pumpSerial = pumpSerial pumpSerial = pumpSerial
) )
) )
repository.runTransactionForResult(InsertPumpBolusWithTempIdTransaction(bolus)) repository.runTransactionForResult(InsertBolusWithTempIdTransaction(bolus))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Bolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted Bolus $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -146,11 +146,11 @@ class PumpSyncImplementation @Inject constructor(
pumpSerial = pumpSerial pumpSerial = pumpSerial
) )
) )
repository.runTransactionForResult(SyncPumpBolusWithTempIdTransaction(bolus, type?.toDBbBolusType())) repository.runTransactionForResult(SyncBolusWithTempIdTransaction(bolus, type?.toDBbBolusType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Bolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated bolus $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated Bolus $it") }
return result.updated.size > 0 return result.updated.size > 0
} }
} }
@ -168,11 +168,11 @@ class PumpSyncImplementation @Inject constructor(
) )
) )
repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType())) repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving bolus", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Bolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted bolus $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted Bolus $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated bolus $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated Bolus $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -189,10 +189,10 @@ class PumpSyncImplementation @Inject constructor(
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) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted carbs $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted Carbs $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -215,11 +215,11 @@ class PumpSyncImplementation @Inject constructor(
) )
repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent)) repository.runTransactionForResult(InsertIfNewByTimestampTherapyEventTransaction(therapyEvent))
.doOnError { .doOnError {
aapsLogger.error(LTag.DATABASE, "Error while saving therapy event", it) aapsLogger.error(LTag.DATABASE, "Error while saving TherapyEvent", it)
} }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted therapy event $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted TherapyEvent $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -249,11 +249,11 @@ class PumpSyncImplementation @Inject constructor(
) )
) )
repository.runTransactionForResult(SyncPumpTemporaryBasalTransaction(temporaryBasal, type?.toDbType())) repository.runTransactionForResult(SyncPumpTemporaryBasalTransaction(temporaryBasal, type?.toDbType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while temporary basal", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while TemporaryBasal", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted temporary basal $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated temporary basal $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated TemporaryBasal $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -261,23 +261,70 @@ class PumpSyncImplementation @Inject constructor(
override fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { override fun syncStopTemporaryBasalWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean {
if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
repository.runTransactionForResult(SyncPumpCancelTemporaryBasalIfAnyTransaction(timestamp, endPumpId, pumpType.toDbPumpType(), pumpSerial)) repository.runTransactionForResult(SyncPumpCancelTemporaryBasalIfAnyTransaction(timestamp, endPumpId, pumpType.toDbPumpType(), pumpSerial))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving temporary basal", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving TemporaryBasal", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.updated.forEach { result.updated.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated temporary basal $it") aapsLogger.debug(LTag.DATABASE, "Updated TemporaryBasal $it")
} }
return result.updated.size > 0 return result.updated.size > 0
} }
} }
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,
rate = rate,
duration = duration,
type = type.toDbType(),
isAbsolute = isAbsolute,
interfaceIDs_backing = InterfaceIDs(
temporaryId = tempId,
pumpType = pumpType.toDbPumpType(),
pumpSerial = pumpSerial
)
)
repository.runTransactionForResult(InsertTemporaryBasalWithTempIdTransaction(temporaryBasal))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving TemporaryBasal", it) }
.blockingGet()
.also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted TemporaryBasal $it") }
return result.inserted.size > 0
}
}
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,
rate = rate,
duration = duration,
type = TemporaryBasal.Type.NORMAL, // not used for update
isAbsolute = isAbsolute,
interfaceIDs_backing = InterfaceIDs(
temporaryId = temporaryId,
pumpId = pumpId,
pumpType = pumpType.toDbPumpType(),
pumpSerial = pumpSerial
)
)
repository.runTransactionForResult(SyncTemporaryBasalWithTempIdTransaction(bolus, type?.toDbType()))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving TemporaryBasal", it) }
.blockingGet()
.also { result ->
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated TemporaryBasal $it") }
return result.updated.size > 0
}
}
override fun invalidateTemporaryBasal(id: Long): Boolean { override fun invalidateTemporaryBasal(id: Long): Boolean {
repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(id)) repository.runTransactionForResult(InvalidateTemporaryBasalTransaction(id))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating temporary basal", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while invalidating TemporaryBasal", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.invalidated.forEach { result.invalidated.forEach {
aapsLogger.debug(LTag.DATABASE, "Invalidated temporary basal $it") aapsLogger.debug(LTag.DATABASE, "Invalidated TemporaryBasal $it")
} }
return result.invalidated.size > 0 return result.invalidated.size > 0
} }
@ -297,11 +344,11 @@ class PumpSyncImplementation @Inject constructor(
) )
) )
repository.runTransactionForResult(SyncPumpExtendedBolusTransaction(extendedBolus)) repository.runTransactionForResult(SyncPumpExtendedBolusTransaction(extendedBolus))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while extended bolus", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while ExtendedBolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted extended bolus $it") } result.inserted.forEach { aapsLogger.debug(LTag.DATABASE, "Inserted ExtendedBolus $it") }
result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated extended bolus $it") } result.updated.forEach { aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it") }
return result.inserted.size > 0 return result.inserted.size > 0
} }
} }
@ -309,11 +356,11 @@ class PumpSyncImplementation @Inject constructor(
override fun syncStopExtendedBolusWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { override fun syncStopExtendedBolusWithPumpId(timestamp: Long, endPumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean {
if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
repository.runTransactionForResult(SyncPumpCancelExtendedBolusIfAnyTransaction(timestamp, endPumpId, pumpType.toDbPumpType(), pumpSerial)) repository.runTransactionForResult(SyncPumpCancelExtendedBolusIfAnyTransaction(timestamp, endPumpId, pumpType.toDbPumpType(), pumpSerial))
.doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving extended bolus", it) } .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving ExtendedBolus", it) }
.blockingGet() .blockingGet()
.also { result -> .also { result ->
result.updated.forEach { result.updated.forEach {
aapsLogger.debug(LTag.DATABASE, "Updated extended bolus $it") aapsLogger.debug(LTag.DATABASE, "Updated ExtendedBolus $it")
} }
return result.updated.size > 0 return result.updated.size > 0
} }

View file

@ -30,6 +30,9 @@ internal interface TemporaryBasalDao : TraceableDao<TemporaryBasal> {
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE nightscoutId = :nsId AND referenceId IS NULL") @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE nightscoutId = :nsId AND referenceId IS NULL")
fun findByNSId(nsId: String): TemporaryBasal? fun findByNSId(nsId: String): TemporaryBasal?
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE temporaryId = :temporaryId AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL")
fun findByPumpTempIds(temporaryId: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): TemporaryBasal?
@Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1") @Query("SELECT * FROM $TABLE_TEMPORARY_BASALS WHERE timestamp <= :timestamp AND (timestamp + duration) > :timestamp AND pumpType = :pumpType AND pumpSerial = :pumpSerial AND referenceId IS NULL AND isValid = 1 ORDER BY timestamp DESC LIMIT 1")
fun getTemporaryBasalActiveAt(timestamp: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): Maybe<TemporaryBasal> fun getTemporaryBasalActiveAt(timestamp: Long, pumpType: InterfaceIDs.PumpType, pumpSerial: String): Maybe<TemporaryBasal>

View file

@ -5,9 +5,9 @@ import info.nightscout.androidaps.database.entities.Bolus
/** /**
* Creates or updates the Bolus from pump synchronization * Creates or updates the Bolus from pump synchronization
*/ */
class InsertPumpBolusWithTempIdTransaction( class InsertBolusWithTempIdTransaction(
private val bolus: Bolus private val bolus: Bolus
) : Transaction<InsertPumpBolusWithTempIdTransaction.TransactionResult>() { ) : Transaction<InsertBolusWithTempIdTransaction.TransactionResult>() {
override fun run(): TransactionResult { override fun run(): TransactionResult {
bolus.interfaceIDs.temporaryId ?: bolus.interfaceIDs.pumpType ?: bolus.interfaceIDs.pumpSerial ?: bolus.interfaceIDs.temporaryId ?: bolus.interfaceIDs.pumpType ?: bolus.interfaceIDs.pumpSerial ?:

View file

@ -0,0 +1,28 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TemporaryBasal
/**
* Creates or updates the TemporaryBasal from pump synchronization
*/
class InsertTemporaryBasalWithTempIdTransaction(private val temporaryBasal: TemporaryBasal
) : Transaction<InsertTemporaryBasalWithTempIdTransaction.TransactionResult>() {
override fun run(): TransactionResult {
temporaryBasal.interfaceIDs.temporaryId ?: temporaryBasal.interfaceIDs.pumpType
?: temporaryBasal.interfaceIDs.pumpSerial
?: throw IllegalStateException("Some pump ID is null")
val result = TransactionResult()
val current = database.temporaryBasalDao.findByPumpTempIds(temporaryBasal.interfaceIDs.temporaryId!!, temporaryBasal.interfaceIDs.pumpType!!, temporaryBasal.interfaceIDs.pumpSerial!!)
if (current == null) {
database.temporaryBasalDao.insert(temporaryBasal)
result.inserted.add(temporaryBasal)
}
return result
}
class TransactionResult {
val inserted = mutableListOf<TemporaryBasal>()
}
}

View file

@ -5,10 +5,10 @@ import info.nightscout.androidaps.database.entities.Bolus
/** /**
* Creates or updates the Bolus from pump synchronization * Creates or updates the Bolus from pump synchronization
*/ */
class SyncPumpBolusWithTempIdTransaction( class SyncBolusWithTempIdTransaction(
private val bolus: Bolus, private val bolus: Bolus,
private val newType: Bolus.Type? private val newType: Bolus.Type?
) : Transaction<SyncPumpBolusWithTempIdTransaction.TransactionResult>() { ) : Transaction<SyncBolusWithTempIdTransaction.TransactionResult>() {
override fun run(): TransactionResult { override fun run(): TransactionResult {
bolus.interfaceIDs.temporaryId ?: bolus.interfaceIDs.pumpType ?: bolus.interfaceIDs.pumpSerial ?: bolus.interfaceIDs.temporaryId ?: bolus.interfaceIDs.pumpType ?: bolus.interfaceIDs.pumpSerial ?:

View file

@ -0,0 +1,35 @@
package info.nightscout.androidaps.database.transactions
import info.nightscout.androidaps.database.entities.TemporaryBasal
/**
* Creates or updates the TemporaryBasal from pump synchronization
*/
class SyncTemporaryBasalWithTempIdTransaction(
private val bolus: TemporaryBasal,
private val newType: TemporaryBasal.Type?
) : Transaction<SyncTemporaryBasalWithTempIdTransaction.TransactionResult>() {
override fun run(): TransactionResult {
bolus.interfaceIDs.temporaryId ?: bolus.interfaceIDs.pumpType
?: bolus.interfaceIDs.pumpSerial ?: throw IllegalStateException("Some pump ID is null")
val result = TransactionResult()
val current = database.temporaryBasalDao.findByPumpTempIds(bolus.interfaceIDs.temporaryId!!, bolus.interfaceIDs.pumpType!!, bolus.interfaceIDs.pumpSerial!!)
if (current != null) {
current.timestamp = bolus.timestamp
current.rate = bolus.rate
current.duration = bolus.duration
current.isAbsolute = bolus.isAbsolute
current.type = newType ?: current.type
current.interfaceIDs.pumpId = bolus.interfaceIDs.pumpId
database.temporaryBasalDao.updateExistingEntry(current)
result.updated.add(current)
}
return result
}
class TransactionResult {
val updated = mutableListOf<TemporaryBasal>()
}
}