- reverted PumpSync changes and database changes

- MedtronicPumpPlugin: added Synchronized to all pump commands
- fixing problem with Zero TBRs
- refactoring of TBRs a little: TempBasalProcessDTO
This commit is contained in:
Andy Rozman 2021-11-06 16:03:07 +00:00
parent fc36371ffa
commit 0d0c5e116f
14 changed files with 1999 additions and 150 deletions

View file

@ -90,9 +90,8 @@ interface PumpSync {
**/ **/
fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String): Boolean fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String): Boolean
/** /**
* Synchronization of boluses with temporary id (with * Synchronization of boluses with temporary id
* *
* Search for combination of temporaryId, PumpType, pumpSerial * Search for combination of temporaryId, PumpType, pumpSerial
* *
@ -111,12 +110,9 @@ interface PumpSync {
* @param pumpId pump id from history * @param pumpId pump id from history
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO * @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number * @param pumpSerial pump serial number
* @param ignoreBolusTypeOnUpdate bolusType won't be updated, if item already exists
* @return true if record is successfully updated * @return true if record is successfully updated
**/ **/
fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate : fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean
Boolean = false): Boolean
/** /**
* Synchronization of boluses * Synchronization of boluses
@ -127,8 +123,6 @@ interface PumpSync {
* If exists, amount, type (if provided) and timestamp is updated * If exists, amount, type (if provided) and timestamp is updated
* isValid field is preserved * isValid field is preserved
* *
* NOTE: this method can be removed, when all drivers are in kotlin
*
* @param timestamp timestamp of event from pump history * @param timestamp timestamp of event from pump history
* @param amount amount of insulin * @param amount amount of insulin
* @param type type of bolus (NORMAL, SMB, PRIME) * @param type type of bolus (NORMAL, SMB, PRIME)
@ -139,29 +133,6 @@ interface PumpSync {
**/ **/
fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean
/**
* Synchronization of boluses (with bolusType ignore)
*
* Search for combination of pumpId, PumpType, pumpSerial
*
* If db record doesn't exist, new record is created.
* If exists, amount, type (if provided) and timestamp is updated
* isValid field is preserved
*
* @param timestamp timestamp of event from pump history
* @param amount amount of insulin
* @param type type of bolus (NORMAL, SMB, PRIME)
* @param pumpId pump id from history
* @param pumpType pump type like PumpType.ACCU_CHEK_COMBO
* @param pumpSerial pump serial number
* @param ignoreBolusTypeOnUpdate bolusType won't be updated, if item already exists
* @return true if new record is created
**/
fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate :
Boolean = false): Boolean
/** /**
* Synchronization of carbs * Synchronization of carbs
* *

View file

@ -137,8 +137,7 @@ class PumpSyncImplementation @Inject constructor(
} }
} }
override fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate : override fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean {
Boolean): Boolean {
if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
val bolus = Bolus( val bolus = Bolus(
timestamp = timestamp, timestamp = timestamp,
@ -151,7 +150,7 @@ class PumpSyncImplementation @Inject constructor(
pumpSerial = pumpSerial pumpSerial = pumpSerial
) )
) )
repository.runTransactionForResult(SyncBolusWithTempIdTransaction(bolus, type?.toDBbBolusType(), ignoreBolusTypeOnUpdate)) 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 ->
@ -161,19 +160,6 @@ class PumpSyncImplementation @Inject constructor(
} }
override fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean { override fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String): Boolean {
return syncBolusWithPumpId(
timestamp = timestamp,
amount = amount,
type = type,
pumpId = pumpId,
pumpType = pumpType,
pumpSerial = pumpSerial,
ignoreBolusTypeOnUpdate = false
)
}
override fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate :
Boolean): Boolean {
if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false
val bolus = Bolus( val bolus = Bolus(
timestamp = timestamp, timestamp = timestamp,
@ -185,7 +171,7 @@ class PumpSyncImplementation @Inject constructor(
pumpSerial = pumpSerial pumpSerial = pumpSerial
) )
) )
repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType(), ignoreBolusTypeOnUpdate)) 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 ->

View file

@ -265,11 +265,11 @@ public class DateTimeUtil {
} }
public static long getATDWithAddedMinutes(long atd, int minutesDiff) { public static long getATDWithAddedSeconds(Long atd, int addedSeconds) {
GregorianCalendar oldestEntryTime = DateTimeUtil.toGregorianCalendar(atd); GregorianCalendar oldestEntryTime = DateTimeUtil.toGregorianCalendar(atd);
oldestEntryTime.add(Calendar.MINUTE, minutesDiff); oldestEntryTime.add(Calendar.SECOND, addedSeconds);
return oldestEntryTime.getTimeInMillis(); return toATechDate(oldestEntryTime.getTimeInMillis());
} }
@ -279,7 +279,6 @@ public class DateTimeUtil {
return toATechDate(oldestEntryTime); return toATechDate(oldestEntryTime);
} }
public static long getTimeInFutureFromMinutes(long startTime, int minutes) { public static long getTimeInFutureFromMinutes(long startTime, int minutes) {
return startTime + getTimeInMs(minutes); return startTime + getTimeInMs(minutes);
} }

View file

@ -7,8 +7,7 @@ import info.nightscout.androidaps.database.entities.Bolus
*/ */
class SyncBolusWithTempIdTransaction( class SyncBolusWithTempIdTransaction(
private val bolus: Bolus, private val bolus: Bolus,
private val newType: Bolus.Type?, private val newType: Bolus.Type?
private val ignoreBolusTypeOnUpdate: Boolean
) : Transaction<SyncBolusWithTempIdTransaction.TransactionResult>() { ) : Transaction<SyncBolusWithTempIdTransaction.TransactionResult>() {
override fun run(): TransactionResult { override fun run(): TransactionResult {
@ -19,9 +18,7 @@ class SyncBolusWithTempIdTransaction(
if (current != null) { if (current != null) {
current.timestamp = bolus.timestamp current.timestamp = bolus.timestamp
current.amount = bolus.amount current.amount = bolus.amount
if (!ignoreBolusTypeOnUpdate) { current.type = newType ?: current.type
current.type = newType ?: current.type
}
current.interfaceIDs.pumpId = bolus.interfaceIDs.pumpId current.interfaceIDs.pumpId = bolus.interfaceIDs.pumpId
database.bolusDao.updateExistingEntry(current) database.bolusDao.updateExistingEntry(current)
result.updated.add(current) result.updated.add(current)

View file

@ -7,8 +7,7 @@ import info.nightscout.androidaps.database.entities.Bolus
*/ */
class SyncPumpBolusTransaction( class SyncPumpBolusTransaction(
private val bolus: Bolus, private val bolus: Bolus,
private val bolusType: Bolus.Type?, // extra parameter because field is not nullable in Bolus.class private val bolusType: Bolus.Type? // extra parameter because field is not nullable in Bolus.class
private val ignoreBolusTypeOnUpdate: Boolean
) : Transaction<SyncPumpBolusTransaction.TransactionResult>() { ) : Transaction<SyncPumpBolusTransaction.TransactionResult>() {
override fun run(): TransactionResult { override fun run(): TransactionResult {
@ -20,28 +19,16 @@ class SyncPumpBolusTransaction(
database.bolusDao.insertNewEntry(bolus) database.bolusDao.insertNewEntry(bolus)
result.inserted.add(bolus) result.inserted.add(bolus)
} else { } else {
if (ignoreBolusTypeOnUpdate) { if (
if ( current.timestamp != bolus.timestamp ||
current.timestamp != bolus.timestamp || current.amount != bolus.amount ||
current.amount != bolus.amount current.type != bolusType ?: current.type
) { ) {
current.timestamp = bolus.timestamp current.timestamp = bolus.timestamp
current.amount = bolus.amount current.amount = bolus.amount
database.bolusDao.updateExistingEntry(current) current.type = bolusType ?: current.type
result.updated.add(current) database.bolusDao.updateExistingEntry(current)
} result.updated.add(current)
} else {
if (
current.timestamp != bolus.timestamp ||
current.amount != bolus.amount ||
current.type != bolusType ?: current.type
) {
current.timestamp = bolus.timestamp
current.amount = bolus.amount
current.type = bolusType ?: current.type
database.bolusDao.updateExistingEntry(current)
result.updated.add(current)
}
} }
} }
return result return result

View file

@ -469,6 +469,7 @@ class MedtronicPumpPlugin @Inject constructor(
} }
} }
@Synchronized
override fun isThisProfileSet(profile: Profile): Boolean { override fun isThisProfileSet(profile: Profile): Boolean {
aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.basalProfileStatus) aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.basalProfileStatus)
if (!isInitialized) return true if (!isInitialized) return true
@ -581,6 +582,7 @@ class MedtronicPumpPlugin @Inject constructor(
scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0) scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0)
} }
@Synchronized
override fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { override fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - " + BolusDeliveryType.DeliveryPrepared) aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - " + BolusDeliveryType.DeliveryPrepared)
setRefreshButtonEnabled(false) setRefreshButtonEnabled(false)
@ -692,6 +694,7 @@ class MedtronicPumpPlugin @Inject constructor(
// if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged), // if enforceNew===true current temp basal is canceled and new TBR set (duration is prolonged),
// if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed // if false and the same rate is requested enacted=false and success=true is returned and TBR is not changed
@Synchronized
override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { override fun setTempBasalAbsolute(absoluteRate: Double, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult {
setRefreshButtonEnabled(false) setRefreshButtonEnabled(false)
if (isPumpNotReachable) { if (isPumpNotReachable) {
@ -743,7 +746,7 @@ class MedtronicPumpPlugin @Inject constructor(
return PumpEnactResult(injector).success(false).enacted(false) return PumpEnactResult(injector).success(false).enacted(false)
.comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op) .comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op)
} else { } else {
cancelTBRWithTemporaryId() //cancelTBRWithTemporaryId()
aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.")
} }
} }
@ -774,6 +777,7 @@ class MedtronicPumpPlugin @Inject constructor(
} }
} }
@Deprecated("Not used, TBRs fixed in history, should be removed.")
private fun cancelTBRWithTemporaryId() { private fun cancelTBRWithTemporaryId() {
val tbrs : MutableList<PumpDbEntryTBR> = pumpSyncStorage.getTBRs() val tbrs : MutableList<PumpDbEntryTBR> = pumpSyncStorage.getTBRs()
if (tbrs.size > 0 && medtronicPumpStatus.runningTBRWithTemp!=null) { if (tbrs.size > 0 && medtronicPumpStatus.runningTBRWithTemp!=null) {
@ -829,6 +833,7 @@ class MedtronicPumpPlugin @Inject constructor(
} }
} }
@Synchronized
override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult {
return if (percent == 0) { return if (percent == 0) {
setTempBasalAbsolute(0.0, durationInMinutes, profile, enforceNew, tbrType) setTempBasalAbsolute(0.0, durationInMinutes, profile, enforceNew, tbrType)
@ -1024,6 +1029,7 @@ class MedtronicPumpPlugin @Inject constructor(
} }
} }
@Synchronized
override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult {
aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - started") aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - started")
if (isPumpNotReachable) { if (isPumpNotReachable) {
@ -1084,7 +1090,7 @@ class MedtronicPumpPlugin @Inject constructor(
} }
} }
cancelTBRWithTemporaryId() //cancelTBRWithTemporaryId()
PumpEnactResult(injector).success(true).enacted(true) // PumpEnactResult(injector).success(true).enacted(true) //
.isTempCancel(true) .isTempCancel(true)
@ -1103,6 +1109,7 @@ class MedtronicPumpPlugin @Inject constructor(
return medtronicPumpStatus.serialNumber return medtronicPumpStatus.serialNumber
} }
@Synchronized
override fun setNewBasalProfile(profile: Profile): PumpEnactResult { override fun setNewBasalProfile(profile: Profile): PumpEnactResult {
aapsLogger.info(LTag.PUMP, logPrefix + "setNewBasalProfile") aapsLogger.info(LTag.PUMP, logPrefix + "setNewBasalProfile")

View file

@ -41,7 +41,13 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface {
/** /**
* Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255) * Pump id that will be used with AAPS object (time * 1000 + historyType (max is FF = 255)
*/ */
open var pumpId: Long = 0L var pumpId: Long = 0L
get() {
if (field == 0L) {
field = generatePumpId()
}
return field
}
/** /**
* if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's * if history object is already linked to AAPS object (either Treatment, TempBasal or TDD (tdd's

View file

@ -92,14 +92,6 @@ class PumpHistoryEntry : MedtronicHistoryEntry() {
} }
} }
override var pumpId: Long = 0L
get() {
if (field == 0L) {
field = generatePumpId()
}
return field
}
fun hasBolusChanged(entry: PumpHistoryEntry): Boolean { fun hasBolusChanged(entry: PumpHistoryEntry): Boolean {
if (entryType == PumpHistoryEntryType.Bolus) { if (entryType == PumpHistoryEntryType.Bolus) {
val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO

View file

@ -571,62 +571,42 @@ class MedtronicHistoryData @Inject constructor(
private fun processTBREntries(entryList: MutableList<PumpHistoryEntry>) { private fun processTBREntries(entryList: MutableList<PumpHistoryEntry>) {
entryList.reverse() entryList.reverse()
val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair
var readOldItem = false // var readOldItem = false
if (tbr.isCancelTBR) {
val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined)
if (tbr.isCancelTBR) { // if we have cancel we need to limit previous TBR with this cancel
if (oneMoreEntryFromHistory != null) { if (oneMoreEntryFromHistory != null) {
entryList.add(0, oneMoreEntryFromHistory) entryList.add(0, oneMoreEntryFromHistory)
readOldItem = true
} else { } else {
entryList.removeAt(0) entryList.removeAt(0)
} }
} else {
if (oneMoreEntryFromHistory != null) {
val tbrPrev = oneMoreEntryFromHistory.getDecodedDataEntry("Object") as TempBasalPair
if (tbrPrev.isZeroTBR) { // if we had Zere TBR in last previous TBR, then we need to limit it, so we need to process it too
entryList.add(0, oneMoreEntryFromHistory)
}
}
} }
val tbrRecords = pumpSyncStorage.getTBRs() val tbrRecords = pumpSyncStorage.getTBRs()
aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.description + " List (before filter): %s, FromDb=%s", gson.toJson(entryList),
tbrRecords)) val processList: MutableList<TempBasalProcessDTO> = createTBRProcessList(entryList);
var processDTO: TempBasalProcessDTO? = null
val processList: MutableList<TempBasalProcessDTO> = mutableListOf()
for (treatment in entryList) {
val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair
if (tbr2.isCancelTBR) {
if (processDTO != null) {
processDTO.itemTwo = treatment
processDTO.cancelPresent = true
if (readOldItem) {
processDTO.processOperation = TempBasalProcessDTO.Operation.Edit
readOldItem = false
}
} else {
aapsLogger.warn(LTag.PUMP, "processDTO was null - shouldn't happen, ignoring item. ItemTwo=$treatment")
}
} else {
if (processDTO != null) {
processList.add(processDTO)
}
processDTO = TempBasalProcessDTO(
itemOne = treatment,
processOperation = TempBasalProcessDTO.Operation.Add,
aapsLogger = aapsLogger,
objectType = TempBasalProcessDTO.ObjectType.TemporaryBasal
)
}
}
if (processDTO != null) {
processList.add(processDTO)
}
if (processList.isNotEmpty()) { if (processList.isNotEmpty()) {
for (tempBasalProcessDTO in processList) { for (tempBasalProcessDTO in processList) {
aapsLogger.debug(LTag.PUMP, "DD: tempBasalProcessDTO.itemOne: " + gson.toJson(tempBasalProcessDTO.itemOne)) aapsLogger.debug(LTag.PUMP, "DD: tempBasalProcessDTO: " + tempBasalProcessDTO.toTreatmentString())
aapsLogger.debug(LTag.PUMP, "DD: tempBasalProcessDTO.itemTwo: " + (if (tempBasalProcessDTO.itemTwo == null) "null" else gson.toJson(tempBasalProcessDTO.itemTwo!!))) //aapsLogger.debug(LTag.PUMP, "DD: tempBasalProcessDTO.itemOne: " + gson.toJson(tempBasalProcessDTO.itemOne))
//aapsLogger.debug(LTag.PUMP, "DD: tempBasalProcessDTO.itemTwo: " + (if (tempBasalProcessDTO.itemTwo == null) "null" else gson.toJson(tempBasalProcessDTO.itemTwo!!)))
@Suppress("Unchecked_Cast") @Suppress("Unchecked_Cast")
val entryWithTempId = findDbEntry(tempBasalProcessDTO.itemOne, tbrRecords as MutableList<PumpDbEntry>) as PumpDbEntryTBR? val entryWithTempId = findDbEntry(tempBasalProcessDTO.itemOne, tbrRecords as MutableList<PumpDbEntry>) as PumpDbEntryTBR?
aapsLogger.debug(LTag.PUMP, "DD: entryWithTempId: " + (entryWithTempId?.toString() ?: "null")) aapsLogger.debug(LTag.PUMP, "DD: entryWithTempId: " + (entryWithTempId?.toString() ?: "null"))
val tbrEntry = tempBasalProcessDTO.itemOneTbr //.getDecodedDataEntry("Object") as TempBasalPair val tbrEntry = tempBasalProcessDTO.itemOneTbr
aapsLogger.debug(LTag.PUMP, String.format("DD: tbrEntry=%s, tempBasalProcessDTO=%s", gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO))) aapsLogger.debug(LTag.PUMP, String.format("DD: tbrEntry=%s, tempBasalProcessDTO=%s", gson.toJson(tbrEntry), gson.toJson(tempBasalProcessDTO)))
@ -649,7 +629,7 @@ class MedtronicHistoryData @Inject constructor(
tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime),
tbrEntry.insulinRate, tbrEntry.insulinRate,
tempBasalProcessDTO.durationAsSeconds * 1000L, tempBasalProcessDTO.durationAsSeconds * 1000L,
!tbrEntry.isPercent, isAbsolute = !tbrEntry.isPercent,
entryWithTempId.temporaryId, entryWithTempId.temporaryId,
PumpSync.TemporaryBasalType.NORMAL, PumpSync.TemporaryBasalType.NORMAL,
tempBasalProcessDTO.pumpId, tempBasalProcessDTO.pumpId,
@ -705,10 +685,10 @@ class MedtronicHistoryData @Inject constructor(
date = tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), date = tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime),
pumpType = medtronicPumpStatus.pumpType, pumpType = medtronicPumpStatus.pumpType,
serialNumber = medtronicPumpStatus.serialNumber, serialNumber = medtronicPumpStatus.serialNumber,
entry = PumpDbEntryTBR(rate = tbrEntry.insulinRate, rate = tbrEntry.insulinRate,
isAbsolute = !tbrEntry.isPercent, isAbsolute = !tbrEntry.isPercent,
durationInSeconds = tempBasalProcessDTO.durationAsSeconds, durationInSeconds = tempBasalProcessDTO.durationAsSeconds,
tbrType = PumpSync.TemporaryBasalType.NORMAL), tbrType = PumpSync.TemporaryBasalType.NORMAL,
pumpId = tempBasalProcessDTO.pumpId) pumpId = tempBasalProcessDTO.pumpId)
} }
} }
@ -720,6 +700,56 @@ class MedtronicHistoryData @Inject constructor(
} // collection } // collection
} }
fun createTBRProcessList(entryList: MutableList<PumpHistoryEntry>) : MutableList<TempBasalProcessDTO> {
aapsLogger.debug(LTag.PUMP, "${ProcessHistoryRecord.TBR.description} List (before filter): ${gson.toJson(entryList)}")
var processDTO: TempBasalProcessDTO? = null
val processList: MutableList<TempBasalProcessDTO> = mutableListOf()
for (treatment in entryList) {
val tbr2 = treatment.getDecodedDataEntry("Object") as TempBasalPair
if (tbr2.isCancelTBR) {
if (processDTO != null) {
processDTO.itemTwo = treatment
} else {
aapsLogger.warn(LTag.PUMP, "processDTO was null - shouldn't happen, ignoring item. ItemTwo=$treatment")
}
} else {
if (processDTO != null) {
processList.add(processDTO)
}
processDTO = TempBasalProcessDTO(
itemOne = treatment,
aapsLogger = aapsLogger,
objectType = TempBasalProcessDTO.ObjectType.TemporaryBasal
)
}
}
if (processDTO != null) {
processList.add(processDTO)
}
var previousItem: TempBasalProcessDTO? = null
// fix for Zero TBRs
for (tempBasalProcessDTO in processList) {
if (previousItem!=null) {
var pheEnd = PumpHistoryEntry()
pheEnd.atechDateTime = DateTimeUtil.getATDWithAddedSeconds(tempBasalProcessDTO.itemOne.atechDateTime, -2)
pheEnd.addDecodedData("Object", TempBasalPair(0.0, false, 0))
previousItem.itemTwo = pheEnd
previousItem = null
}
if (tempBasalProcessDTO.itemOneTbr!!.isZeroTBR) {
previousItem = tempBasalProcessDTO
}
}
return processList
}
fun isTBRActive(dbEntry: PumpDbEntryTBR): Boolean { fun isTBRActive(dbEntry: PumpDbEntryTBR): Boolean {
@ -881,7 +911,6 @@ class MedtronicHistoryData @Inject constructor(
while (i < filtered2Items.size) { while (i < filtered2Items.size) {
val tbrProcess = TempBasalProcessDTO( val tbrProcess = TempBasalProcessDTO(
itemOne = filtered2Items[i], itemOne = filtered2Items[i],
processOperation = TempBasalProcessDTO.Operation.Add,
aapsLogger = aapsLogger, aapsLogger = aapsLogger,
objectType = TempBasalProcessDTO.ObjectType.Suspend) objectType = TempBasalProcessDTO.ObjectType.Suspend)
@ -959,7 +988,6 @@ class MedtronicHistoryData @Inject constructor(
if (items.size > 0) { if (items.size > 0) {
val tbrProcess = TempBasalProcessDTO( val tbrProcess = TempBasalProcessDTO(
itemOne = items[items.size - 1], itemOne = items[items.size - 1],
processOperation = TempBasalProcessDTO.Operation.Add,
aapsLogger = aapsLogger, aapsLogger = aapsLogger,
objectType = TempBasalProcessDTO.ObjectType.Suspend) objectType = TempBasalProcessDTO.ObjectType.Suspend)
@ -975,7 +1003,6 @@ class MedtronicHistoryData @Inject constructor(
if (items.size > 0) { if (items.size > 0) {
val tbrProcess = TempBasalProcessDTO( val tbrProcess = TempBasalProcessDTO(
itemOne = items[0], itemOne = items[0],
processOperation = TempBasalProcessDTO.Operation.Add,
aapsLogger = aapsLogger, aapsLogger = aapsLogger,
objectType = TempBasalProcessDTO.ObjectType.Suspend) objectType = TempBasalProcessDTO.ObjectType.Suspend)

View file

@ -91,6 +91,9 @@ class TempBasalPair : TempBasalPair {
val isCancelTBR: Boolean val isCancelTBR: Boolean
get() = MedtronicUtil.isSame(insulinRate, 0.0) && durationMinutes == 0 get() = MedtronicUtil.isSame(insulinRate, 0.0) && durationMinutes == 0
val isZeroTBR: Boolean
get() = MedtronicUtil.isSame(insulinRate, 0.0) && durationMinutes != 0
val description: String val description: String
get() { get() {
if (isCancelTBR) { if (isCancelTBR) {

View file

@ -4,9 +4,9 @@ import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.logging.LTag
import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry
import java.lang.StringBuilder
class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry, class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry,
var processOperation: Operation = Operation.None,
var aapsLogger: AAPSLogger, var aapsLogger: AAPSLogger,
var objectType: ObjectType = ObjectType.TemporaryBasal) { var objectType: ObjectType = ObjectType.TemporaryBasal) {
@ -21,8 +21,6 @@ class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry,
var itemOneTbr: TempBasalPair? = null var itemOneTbr: TempBasalPair? = null
var itemTwoTbr: TempBasalPair? = null var itemTwoTbr: TempBasalPair? = null
var cancelPresent: Boolean = false
val atechDateTime: Long val atechDateTime: Long
get() = itemOne.atechDateTime get() = itemOne.atechDateTime
@ -31,26 +29,26 @@ class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry,
val durationAsSeconds: Int val durationAsSeconds: Int
get() { get() {
aapsLogger.debug(LTag.PUMP, "durationAsSeconds: [objectType=$objectType]") //aapsLogger.debug(LTag.PUMP, "durationAsSeconds: [objectType=$objectType]")
if (objectType == ObjectType.TemporaryBasal) { if (objectType == ObjectType.TemporaryBasal) {
if (itemTwo == null) { if (itemTwo == null) {
if (itemOneTbr != null) { if (itemOneTbr != null) {
aapsLogger.debug("TemporaryBasalPair - itemOneSingle: $itemOneTbr") //aapsLogger.debug("TemporaryBasalPair - itemOneSingle: $itemOneTbr")
return itemOneTbr!!.durationMinutes * 60 return itemOneTbr!!.durationMinutes * 60
} else { } else {
aapsLogger.error("Couldn't find TempBasalPair in entry: $itemOne") //aapsLogger.error("Couldn't find TempBasalPair in entry: $itemOne")
return 0 return 0
} }
} else { } else {
aapsLogger.debug(LTag.PUMP, "Found 2 items for duration: itemOne=$itemOne, itemTwo=$itemTwo") //aapsLogger.debug(LTag.PUMP, "Found 2 items for duration: itemOne=$itemOne, itemTwo=$itemTwo")
val secondsDiff = DateTimeUtil.getATechDateDiferenceAsSeconds(itemOne.atechDateTime, itemTwo!!.atechDateTime) val secondsDiff = DateTimeUtil.getATechDateDiferenceAsSeconds(itemOne.atechDateTime, itemTwo!!.atechDateTime)
aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff") //aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff")
return secondsDiff return secondsDiff
} }
} else { } else {
aapsLogger.debug(LTag.PUMP, "Found 2 items for duration (in SuspendMode): itemOne=$itemOne, itemTwo=$itemTwo") //aapsLogger.debug(LTag.PUMP, "Found 2 items for duration (in SuspendMode): itemOne=$itemOne, itemTwo=$itemTwo")
val secondsDiff = DateTimeUtil.getATechDateDiferenceAsSeconds(itemOne.atechDateTime, itemTwo!!.atechDateTime) val secondsDiff = DateTimeUtil.getATechDateDiferenceAsSeconds(itemOne.atechDateTime, itemTwo!!.atechDateTime)
aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff") //aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff")
return secondsDiff return secondsDiff
} }
} }
@ -61,8 +59,31 @@ class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry,
} }
} }
fun toTreatmentString(): String {
val stringBuilder = StringBuilder()
stringBuilder.append(itemOne.DT)
if (itemTwo!=null) {
stringBuilder.append(" - ")
stringBuilder.append(itemTwo!!.DT)
}
var dur = durationAsSeconds
stringBuilder.append(" " + durationAsSeconds + " s (" + durationAsSeconds/60 + ")")
if (itemTwoTbr!=null) {
stringBuilder.append(" " + itemOneTbr!!.insulinRate + " / " + itemTwoTbr!!.insulinRate)
} else {
stringBuilder.append(" " + itemOneTbr!!.insulinRate)
}
return stringBuilder.toString()
}
override fun toString(): String { override fun toString(): String {
return "ItemOne: $itemOne, ItemTwo: $itemTwo, Duration: $durationAsSeconds, Operation: $processOperation, ObjectType: $objectType" return "ItemOne: $itemOne, ItemTwo: $itemTwo, Duration: $durationAsSeconds, ObjectType: $objectType"
} }
enum class Operation { enum class Operation {

View file

@ -0,0 +1,91 @@
package info.nightscout.androidaps.plugins.pump.medtronic.data
import java.lang.reflect.Type
import com.google.gson.reflect.TypeToken
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.internal.LinkedTreeMap
import dagger.android.AndroidInjector
import dagger.android.HasAndroidInjector
import info.nightscout.androidaps.TestBase
import info.nightscout.androidaps.interfaces.ActivePlugin
import info.nightscout.androidaps.interfaces.PumpSync
import info.nightscout.androidaps.logging.AAPSLogger
import info.nightscout.androidaps.plugins.pump.common.sync.PumpSyncStorage
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.MedtronicPumpHistoryDecoder
import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry
import info.nightscout.androidaps.plugins.pump.medtronic.data.dto.TempBasalPair
import info.nightscout.androidaps.plugins.pump.medtronic.driver.MedtronicPumpStatus
import info.nightscout.androidaps.plugins.pump.medtronic.util.MedtronicUtil
import info.nightscout.androidaps.utils.sharedPreferences.SP
import org.hamcrest.Matchers.notNullValue
import org.junit.Assert.*
import org.junit.Test
import org.mockito.Mock
import java.io.File
import java.net.URL
class MedtronicHistoryDataUTest : TestBase() {
@Mock lateinit var activePlugin: ActivePlugin
@Mock lateinit var medtronicUtil: MedtronicUtil
@Mock lateinit var medtronicPumpHistoryDecoder: MedtronicPumpHistoryDecoder
@Mock lateinit var medtronicPumpStatus: MedtronicPumpStatus
@Mock lateinit var pumpSync: PumpSync
@Mock lateinit var pumpSyncStorage: PumpSyncStorage
@Mock lateinit var sp: SP
private val packetInjector = HasAndroidInjector {
AndroidInjector {
}
}
@Test
fun createTBRProcessList() {
var unitToTest = MedtronicHistoryData(packetInjector, aapsLogger, sp, activePlugin,
medtronicUtil, medtronicPumpHistoryDecoder,
medtronicPumpStatus,
pumpSync,
pumpSyncStorage)
val gson = Gson()
val fileText = ClassLoader.getSystemResource("tbr_data.json").readText()
val listType: Type = object : TypeToken<MutableList<PumpHistoryEntry?>?>() {}.getType()
val yourClassList: MutableList<PumpHistoryEntry> = gson.fromJson(fileText, listType)
for (pumpHistoryEntry in yourClassList) {
val stringObject = pumpHistoryEntry.decodedData["Object"] as LinkedTreeMap<String,Object>
val rate : Double = stringObject.get("insulinRate") as Double
val durationMinutes: Double = stringObject.get("durationMinutes") as Double
val durationMinutesInt : Int = durationMinutes.toInt()
var tmbPair = TempBasalPair(rate, false, durationMinutesInt)
pumpHistoryEntry.decodedData.remove("Object")
pumpHistoryEntry.addDecodedData("Object", tmbPair)
}
System.out.println("TBR Pre-Process List: " + gson.toJson(yourClassList))
val createTBRProcessList = unitToTest.createTBRProcessList(yourClassList)
System.out.println("TBR Process List: " + createTBRProcessList.size)
for (tempBasalProcessDTO in createTBRProcessList) {
System.out.println(tempBasalProcessDTO.toTreatmentString())
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -323,6 +323,7 @@ abstract class PumpPluginAbstract protected constructor(
return ret return ret
} }
@Synchronized
override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult {
return try { return try {
if (detailedBolusInfo.insulin == 0.0 && detailedBolusInfo.carbs == 0.0) { if (detailedBolusInfo.insulin == 0.0 && detailedBolusInfo.carbs == 0.0) {