From 63ddf999135e04af2c3455365773b4a508b6e608 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sun, 31 Oct 2021 12:39:23 +0000 Subject: [PATCH 01/34] - TBR problem fix: when TBR is cancelled, if there is TBR with TemporalId waiting, we update duration on that item - Bolus/SMB problem: extended pumpSync to add ignoreBolusTypeOnUpdate to both methods: syncBolusWithTempId, syncBolusWithPumpId --- .../androidaps/interfaces/PumpSync.kt | 35 +++++++++- .../plugins/pump/PumpSyncImplementation.kt | 20 +++++- .../SyncBolusWithTempIdTransaction.kt | 7 +- .../transactions/SyncPumpBolusTransaction.kt | 35 ++++++---- .../pump/medtronic/MedtronicPumpPlugin.kt | 64 ++++++++++++++++++- .../medtronic/data/MedtronicHistoryData.kt | 28 ++++---- .../medtronic/driver/MedtronicPumpStatus.kt | 1 + 7 files changed, 156 insertions(+), 34 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt index cc14666dac..1b6111e483 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt @@ -90,8 +90,9 @@ interface PumpSync { **/ fun addBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType, pumpType: PumpType, pumpSerial: String): Boolean + /** - * Synchronization of boluses with temporary id + * Synchronization of boluses with temporary id (with * * Search for combination of temporaryId, PumpType, pumpSerial * @@ -110,9 +111,12 @@ interface PumpSync { * @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 record is successfully updated **/ - fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean + fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate : + Boolean = false): Boolean + /** * Synchronization of boluses @@ -123,15 +127,40 @@ interface PumpSync { * If exists, amount, type (if provided) and timestamp is updated * 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 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 + * @return true if new record is created + **/ + 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): Boolean + fun syncBolusWithPumpId(timestamp: Long, amount: Double, type: DetailedBolusInfo.BolusType?, pumpId: Long, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate : + Boolean = false): Boolean + /** * Synchronization of carbs diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt index 1a92af8ae6..444dc6338a 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt @@ -137,7 +137,8 @@ class PumpSyncImplementation @Inject constructor( } } - override fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean { + override fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate : + Boolean): Boolean { if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false val bolus = Bolus( timestamp = timestamp, @@ -150,7 +151,7 @@ class PumpSyncImplementation @Inject constructor( pumpSerial = pumpSerial ) ) - repository.runTransactionForResult(SyncBolusWithTempIdTransaction(bolus, type?.toDBbBolusType())) + repository.runTransactionForResult(SyncBolusWithTempIdTransaction(bolus, type?.toDBbBolusType(), ignoreBolusTypeOnUpdate)) .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Bolus", it) } .blockingGet() .also { result -> @@ -160,6 +161,19 @@ class PumpSyncImplementation @Inject constructor( } 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 val bolus = Bolus( timestamp = timestamp, @@ -171,7 +185,7 @@ class PumpSyncImplementation @Inject constructor( pumpSerial = pumpSerial ) ) - repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType())) + repository.runTransactionForResult(SyncPumpBolusTransaction(bolus, type?.toDBbBolusType(), ignoreBolusTypeOnUpdate)) .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving Bolus", it) } .blockingGet() .also { result -> diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt index 99449f5ce7..e3f9a02423 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt @@ -7,7 +7,8 @@ import info.nightscout.androidaps.database.entities.Bolus */ class SyncBolusWithTempIdTransaction( private val bolus: Bolus, - private val newType: Bolus.Type? + private val newType: Bolus.Type?, + private val ignoreBolusTypeOnUpdate: Boolean ) : Transaction() { override fun run(): TransactionResult { @@ -18,7 +19,9 @@ class SyncBolusWithTempIdTransaction( if (current != null) { current.timestamp = bolus.timestamp current.amount = bolus.amount - current.type = newType ?: current.type + if (!ignoreBolusTypeOnUpdate) { + current.type = newType ?: current.type + } current.interfaceIDs.pumpId = bolus.interfaceIDs.pumpId database.bolusDao.updateExistingEntry(current) result.updated.add(current) diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt index c7ff85ba21..fb0fecda19 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt @@ -7,7 +7,8 @@ import info.nightscout.androidaps.database.entities.Bolus */ class SyncPumpBolusTransaction( 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() { override fun run(): TransactionResult { @@ -19,16 +20,28 @@ class SyncPumpBolusTransaction( database.bolusDao.insertNewEntry(bolus) result.inserted.add(bolus) } 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) + if (ignoreBolusTypeOnUpdate) { + if ( + current.timestamp != bolus.timestamp || + current.amount != bolus.amount + ) { + current.timestamp = bolus.timestamp + current.amount = bolus.amount + 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 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 665b5c8f34..3f11910c5f 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -32,6 +32,7 @@ import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.Riley import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ResetRileyLinkConfigurationTask import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.ServiceTaskExecutor import info.nightscout.androidaps.plugins.pump.common.hw.rileylink.service.tasks.WakeAndTuneTask +import info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.common.utils.ProfileUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry @@ -742,6 +743,7 @@ class MedtronicPumpPlugin @Inject constructor( return PumpEnactResult(injector).success(false).enacted(false) .comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op) } else { + cancelTBRWithTemporaryId() aapsLogger.info(LTag.PUMP, logPrefix + "setTempBasalAbsolute - Current TBR cancelled.") } } @@ -760,8 +762,9 @@ class MedtronicPumpPlugin @Inject constructor( medtronicPumpStatus.tempBasalAmount = absoluteRate medtronicPumpStatus.tempBasalLength = durationInMinutes - val tempData = info.nightscout.androidaps.plugins.pump.common.sync.PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + val tempData = PumpDbEntryTBR(absoluteRate, true, durationInMinutes, tbrType) + medtronicPumpStatus.runningTBRWithTemp = tempData pumpSyncStorage.addTemporaryBasalRateWithTempId(tempData, true, this) incrementStatistics(MedtronicConst.Statistics.TBRsSet) @@ -771,6 +774,61 @@ class MedtronicPumpPlugin @Inject constructor( } } + private fun cancelTBRWithTemporaryId() { + val tbrs : MutableList = pumpSyncStorage.getTBRs() + if (tbrs.size > 0 && medtronicPumpStatus.runningTBRWithTemp!=null) { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTBRWithTemporaryId - TBR items: ${tbrs.size}") + + var item : PumpDbEntryTBR? = null + + if (tbrs.size==1) { + item = tbrs.get(0); + } else { + for (tbr in tbrs) { + if (tbr.date == medtronicPumpStatus.runningTBRWithTemp!!.date) { + item = tbr + break; + } + } + } + + if (item!=null) { + + aapsLogger.debug(LTag.PUMP, "DD: cancelTBRWithTemporaryId: tempIdEntry=${item}") + + val differenceS = (System.currentTimeMillis() - item.date) / 1000 + + aapsLogger.debug(LTag.PUMP, "syncTemporaryBasalWithTempId " + + "[date=${item.date}, " + + "rate=${item.rate}, " + + "duration=${differenceS} s, " + + "isAbsolute=${!item.isAbsolute}, temporaryId=${item.temporaryId}, " + + "pumpId=NO, pumpType=${medtronicPumpStatus.pumpType}, " + + "pumpSerial=${medtronicPumpStatus.serialNumber}]") + + val result = pumpSync.syncTemporaryBasalWithTempId( + timestamp = item.date, + rate = item.rate, + duration= differenceS * 1000L, + isAbsolute = item.isAbsolute, + temporaryId = item.temporaryId, + type = item.tbrType, + pumpId = null, + pumpType = medtronicPumpStatus.pumpType, + pumpSerial = medtronicPumpStatus.serialNumber) + + aapsLogger.debug(LTag.PUMP, "syncTemporaryBasalWithTempId - Result: $result") + } + + } else { + aapsLogger.info(LTag.PUMP, logPrefix + "cancelTBRWithTemporaryId - TBR items: ${tbrs.size}, runningTBRWithTemp=${medtronicPumpStatus.runningTBRWithTemp}") + } + + if (medtronicPumpStatus.runningTBRWithTemp!=null) { + medtronicPumpStatus.runningTBRWithTemp = null + } + } + override fun setTempBasalPercent(percent: Int, durationInMinutes: Int, profile: Profile, enforceNew: Boolean, tbrType: TemporaryBasalType): PumpEnactResult { return if (percent == 0) { setTempBasalAbsolute(0.0, durationInMinutes, profile, enforceNew, tbrType) @@ -1001,7 +1059,7 @@ class MedtronicPumpPlugin @Inject constructor( aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - Cancel TBR successful.") val runningTBR = medtronicPumpStatus.runningTBR - + // TODO if (runningTBR != null) { if (medtronicHistoryData.isTBRActive(runningTBR)) { @@ -1026,6 +1084,8 @@ class MedtronicPumpPlugin @Inject constructor( } } + cancelTBRWithTemporaryId() + PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) } diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 4a23d5e222..a984e2f117 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -508,25 +508,27 @@ class MedtronicHistoryData @Inject constructor( if (temporaryId != null) { val result = pumpSync.syncBolusWithTempId( - tryToGetByLocalTime(bolus.atechDateTime), - deliveredAmount, - temporaryId, - type, - bolus.pumpId, - medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber) + timestamp = tryToGetByLocalTime(bolus.atechDateTime), + amount = deliveredAmount, + temporaryId = temporaryId, + type = type, + pumpId = bolus.pumpId, + pumpType = medtronicPumpStatus.pumpType, + pumpSerial = medtronicPumpStatus.serialNumber, + ignoreBolusTypeOnUpdate = true) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithTempId [date=%d, temporaryId=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", bolus.atechDateTime, temporaryId, bolus.pumpId, deliveredAmount, medtronicPumpStatus.serialNumber, result)) } else { val result = pumpSync.syncBolusWithPumpId( - tryToGetByLocalTime(bolus.atechDateTime), - deliveredAmount, - type, - bolus.pumpId, - medtronicPumpStatus.pumpType, - medtronicPumpStatus.serialNumber) + timestamp = tryToGetByLocalTime(bolus.atechDateTime), + amount = deliveredAmount, + type = type, + pumpId = bolus.pumpId, + pumpType = medtronicPumpStatus.pumpType, + pumpSerial = medtronicPumpStatus.serialNumber, + ignoreBolusTypeOnUpdate = true) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithPumpId [date=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", bolus.atechDateTime, bolus.pumpId, deliveredAmount, diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt index c417a22a1d..499ad6dfb7 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/driver/MedtronicPumpStatus.kt @@ -34,6 +34,7 @@ class MedtronicPumpStatus @Inject constructor(private val resourceHelper: Resour var maxBolus: Double? = null var maxBasal: Double? = null var runningTBR: PumpDbEntryTBR? = null + var runningTBRWithTemp: PumpDbEntryTBR? = null // statuses var pumpDeviceState = PumpDeviceState.NeverContacted From fc36371ffa8f58c44f33399da0f855b4985d22f4 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sun, 31 Oct 2021 18:07:40 +0000 Subject: [PATCH 02/34] - trying to use old implementation (not setting type so that old one is taken over) --- .../pump/medtronic/data/MedtronicHistoryData.kt | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index a984e2f117..0f1e177de3 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -511,11 +511,10 @@ class MedtronicHistoryData @Inject constructor( timestamp = tryToGetByLocalTime(bolus.atechDateTime), amount = deliveredAmount, temporaryId = temporaryId, - type = type, + type = null, pumpId = bolus.pumpId, pumpType = medtronicPumpStatus.pumpType, - pumpSerial = medtronicPumpStatus.serialNumber, - ignoreBolusTypeOnUpdate = true) + pumpSerial = medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithTempId [date=%d, temporaryId=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", bolus.atechDateTime, temporaryId, bolus.pumpId, deliveredAmount, @@ -524,11 +523,10 @@ class MedtronicHistoryData @Inject constructor( val result = pumpSync.syncBolusWithPumpId( timestamp = tryToGetByLocalTime(bolus.atechDateTime), amount = deliveredAmount, - type = type, + type = null, pumpId = bolus.pumpId, pumpType = medtronicPumpStatus.pumpType, - pumpSerial = medtronicPumpStatus.serialNumber, - ignoreBolusTypeOnUpdate = true) + pumpSerial = medtronicPumpStatus.serialNumber) aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, "syncBolusWithPumpId [date=%d, pumpId=%d, insulin=%.2f, pumpSerial=%s] - Result: %b", bolus.atechDateTime, bolus.pumpId, deliveredAmount, From 0d0c5e116f2d9a8a6ed68ea27b1421895f9ea33c Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Sat, 6 Nov 2021 16:03:07 +0000 Subject: [PATCH 03/34] - reverted PumpSync changes and database changes - MedtronicPumpPlugin: added Synchronized to all pump commands - fixing problem with Zero TBRs - refactoring of TBRs a little: TempBasalProcessDTO --- .../androidaps/interfaces/PumpSync.kt | 33 +- .../plugins/pump/PumpSyncImplementation.kt | 20 +- .../pump/common/utils/DateTimeUtil.java | 7 +- .../SyncBolusWithTempIdTransaction.kt | 7 +- .../transactions/SyncPumpBolusTransaction.kt | 35 +- .../pump/medtronic/MedtronicPumpPlugin.kt | 11 +- .../comm/history/MedtronicHistoryEntry.kt | 8 +- .../comm/history/pump/PumpHistoryEntry.kt | 8 - .../medtronic/data/MedtronicHistoryData.kt | 121 +- .../pump/medtronic/data/dto/TempBasalPair.kt | 3 + .../medtronic/data/dto/TempBasalProcessDTO.kt | 43 +- .../data/MedtronicHistoryDataUTest.kt | 91 + medtronic/src/test/resources/tbr_data.json | 1761 +++++++++++++++++ .../plugins/pump/common/PumpPluginAbstract.kt | 1 + 14 files changed, 1999 insertions(+), 150 deletions(-) create mode 100644 medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryDataUTest.kt create mode 100644 medtronic/src/test/resources/tbr_data.json diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt index 1b6111e483..cc14666dac 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt @@ -90,9 +90,8 @@ interface PumpSync { **/ 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 * @@ -111,12 +110,9 @@ interface PumpSync { * @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 record is successfully updated **/ - fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String, ignoreBolusTypeOnUpdate : - Boolean = false): Boolean - + fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean /** * Synchronization of boluses @@ -127,8 +123,6 @@ interface PumpSync { * If exists, amount, type (if provided) and timestamp is updated * 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 amount amount of insulin * @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 - - /** - * 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 * diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt index 444dc6338a..1a92af8ae6 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt @@ -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 : - Boolean): Boolean { + override fun syncBolusWithTempId(timestamp: Long, amount: Double, temporaryId: Long, type: DetailedBolusInfo.BolusType?, pumpId: Long?, pumpType: PumpType, pumpSerial: String): Boolean { if (!confirmActivePump(timestamp, pumpType, pumpSerial)) return false val bolus = Bolus( timestamp = timestamp, @@ -151,7 +150,7 @@ class PumpSyncImplementation @Inject constructor( 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) } .blockingGet() .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 { - 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 val bolus = Bolus( timestamp = timestamp, @@ -185,7 +171,7 @@ class PumpSyncImplementation @Inject constructor( 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) } .blockingGet() .also { result -> diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java index 2f37f541a6..eee40443e2 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/utils/DateTimeUtil.java @@ -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); - 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); } - public static long getTimeInFutureFromMinutes(long startTime, int minutes) { return startTime + getTimeInMs(minutes); } diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt index e3f9a02423..99449f5ce7 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncBolusWithTempIdTransaction.kt @@ -7,8 +7,7 @@ import info.nightscout.androidaps.database.entities.Bolus */ class SyncBolusWithTempIdTransaction( private val bolus: Bolus, - private val newType: Bolus.Type?, - private val ignoreBolusTypeOnUpdate: Boolean + private val newType: Bolus.Type? ) : Transaction() { override fun run(): TransactionResult { @@ -19,9 +18,7 @@ class SyncBolusWithTempIdTransaction( if (current != null) { current.timestamp = bolus.timestamp current.amount = bolus.amount - if (!ignoreBolusTypeOnUpdate) { - current.type = newType ?: current.type - } + current.type = newType ?: current.type current.interfaceIDs.pumpId = bolus.interfaceIDs.pumpId database.bolusDao.updateExistingEntry(current) result.updated.add(current) diff --git a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt index fb0fecda19..c7ff85ba21 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/transactions/SyncPumpBolusTransaction.kt @@ -7,8 +7,7 @@ import info.nightscout.androidaps.database.entities.Bolus */ class SyncPumpBolusTransaction( private val bolus: Bolus, - private val bolusType: Bolus.Type?, // extra parameter because field is not nullable in Bolus.class - private val ignoreBolusTypeOnUpdate: Boolean + private val bolusType: Bolus.Type? // extra parameter because field is not nullable in Bolus.class ) : Transaction() { override fun run(): TransactionResult { @@ -20,28 +19,16 @@ class SyncPumpBolusTransaction( database.bolusDao.insertNewEntry(bolus) result.inserted.add(bolus) } else { - if (ignoreBolusTypeOnUpdate) { - if ( - current.timestamp != bolus.timestamp || - current.amount != bolus.amount - ) { - current.timestamp = bolus.timestamp - current.amount = bolus.amount - 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) - } + 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 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 3f11910c5f..0f287db750 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -469,6 +469,7 @@ class MedtronicPumpPlugin @Inject constructor( } } + @Synchronized override fun isThisProfileSet(profile: Profile): Boolean { aapsLogger.debug(LTag.PUMP, "isThisProfileSet: basalInitalized=" + medtronicPumpStatus.basalProfileStatus) if (!isInitialized) return true @@ -581,6 +582,7 @@ class MedtronicPumpPlugin @Inject constructor( scheduleNextRefresh(MedtronicStatusRefreshType.PumpTime, 0) } + @Synchronized override fun deliverBolus(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { aapsLogger.info(LTag.PUMP, "MedtronicPumpPlugin::deliverBolus - " + BolusDeliveryType.DeliveryPrepared) 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 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 { setRefreshButtonEnabled(false) if (isPumpNotReachable) { @@ -743,7 +746,7 @@ class MedtronicPumpPlugin @Inject constructor( return PumpEnactResult(injector).success(false).enacted(false) .comment(R.string.medtronic_cmd_cant_cancel_tbr_stop_op) } else { - cancelTBRWithTemporaryId() + //cancelTBRWithTemporaryId() 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() { val tbrs : MutableList = pumpSyncStorage.getTBRs() 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 { return if (percent == 0) { setTempBasalAbsolute(0.0, durationInMinutes, profile, enforceNew, tbrType) @@ -1024,6 +1029,7 @@ class MedtronicPumpPlugin @Inject constructor( } } + @Synchronized override fun cancelTempBasal(enforceNew: Boolean): PumpEnactResult { aapsLogger.info(LTag.PUMP, logPrefix + "cancelTempBasal - started") if (isPumpNotReachable) { @@ -1084,7 +1090,7 @@ class MedtronicPumpPlugin @Inject constructor( } } - cancelTBRWithTemporaryId() + //cancelTBRWithTemporaryId() PumpEnactResult(injector).success(true).enacted(true) // .isTempCancel(true) @@ -1103,6 +1109,7 @@ class MedtronicPumpPlugin @Inject constructor( return medtronicPumpStatus.serialNumber } + @Synchronized override fun setNewBasalProfile(profile: Profile): PumpEnactResult { aapsLogger.info(LTag.PUMP, logPrefix + "setNewBasalProfile") diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index dc38b62601..6730439a4b 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -41,7 +41,13 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { /** * 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 diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt index 0bc1e8106e..c16bf5c362 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/pump/PumpHistoryEntry.kt @@ -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 { if (entryType == PumpHistoryEntryType.Bolus) { val thisOne: BolusDTO = this.decodedData["Object"] as BolusDTO diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt index 0f1e177de3..edd3de2c35 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryData.kt @@ -571,62 +571,42 @@ class MedtronicHistoryData @Inject constructor( private fun processTBREntries(entryList: MutableList) { entryList.reverse() val tbr = entryList[0].getDecodedDataEntry("Object") as TempBasalPair - var readOldItem = false - if (tbr.isCancelTBR) { - val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) +// var readOldItem = false + + val oneMoreEntryFromHistory = getOneMoreEntryFromHistory(PumpHistoryEntryType.TempBasalCombined) + + if (tbr.isCancelTBR) { // if we have cancel we need to limit previous TBR with this cancel if (oneMoreEntryFromHistory != null) { entryList.add(0, oneMoreEntryFromHistory) - readOldItem = true } else { 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() - aapsLogger.debug(LTag.PUMP, String.format(Locale.ENGLISH, ProcessHistoryRecord.TBR.description + " List (before filter): %s, FromDb=%s", gson.toJson(entryList), - tbrRecords)) - var processDTO: TempBasalProcessDTO? = null - val processList: MutableList = 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) - } + + val processList: MutableList = createTBRProcessList(entryList); + if (processList.isNotEmpty()) { for (tempBasalProcessDTO in processList) { - 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!!))) + aapsLogger.debug(LTag.PUMP, "DD: tempBasalProcessDTO: " + tempBasalProcessDTO.toTreatmentString()) + //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") val entryWithTempId = findDbEntry(tempBasalProcessDTO.itemOne, tbrRecords as MutableList) as PumpDbEntryTBR? 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))) @@ -649,7 +629,7 @@ class MedtronicHistoryData @Inject constructor( tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), tbrEntry.insulinRate, tempBasalProcessDTO.durationAsSeconds * 1000L, - !tbrEntry.isPercent, + isAbsolute = !tbrEntry.isPercent, entryWithTempId.temporaryId, PumpSync.TemporaryBasalType.NORMAL, tempBasalProcessDTO.pumpId, @@ -705,10 +685,10 @@ class MedtronicHistoryData @Inject constructor( date = tryToGetByLocalTime(tempBasalProcessDTO.atechDateTime), pumpType = medtronicPumpStatus.pumpType, serialNumber = medtronicPumpStatus.serialNumber, - entry = PumpDbEntryTBR(rate = tbrEntry.insulinRate, - isAbsolute = !tbrEntry.isPercent, - durationInSeconds = tempBasalProcessDTO.durationAsSeconds, - tbrType = PumpSync.TemporaryBasalType.NORMAL), + rate = tbrEntry.insulinRate, + isAbsolute = !tbrEntry.isPercent, + durationInSeconds = tempBasalProcessDTO.durationAsSeconds, + tbrType = PumpSync.TemporaryBasalType.NORMAL, pumpId = tempBasalProcessDTO.pumpId) } } @@ -720,6 +700,56 @@ class MedtronicHistoryData @Inject constructor( } // collection } + fun createTBRProcessList(entryList: MutableList) : MutableList { + + aapsLogger.debug(LTag.PUMP, "${ProcessHistoryRecord.TBR.description} List (before filter): ${gson.toJson(entryList)}") + + var processDTO: TempBasalProcessDTO? = null + val processList: MutableList = 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 { @@ -881,7 +911,6 @@ class MedtronicHistoryData @Inject constructor( while (i < filtered2Items.size) { val tbrProcess = TempBasalProcessDTO( itemOne = filtered2Items[i], - processOperation = TempBasalProcessDTO.Operation.Add, aapsLogger = aapsLogger, objectType = TempBasalProcessDTO.ObjectType.Suspend) @@ -959,7 +988,6 @@ class MedtronicHistoryData @Inject constructor( if (items.size > 0) { val tbrProcess = TempBasalProcessDTO( itemOne = items[items.size - 1], - processOperation = TempBasalProcessDTO.Operation.Add, aapsLogger = aapsLogger, objectType = TempBasalProcessDTO.ObjectType.Suspend) @@ -975,7 +1003,6 @@ class MedtronicHistoryData @Inject constructor( if (items.size > 0) { val tbrProcess = TempBasalProcessDTO( itemOne = items[0], - processOperation = TempBasalProcessDTO.Operation.Add, aapsLogger = aapsLogger, objectType = TempBasalProcessDTO.ObjectType.Suspend) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt index fcc7e71996..3c48934552 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalPair.kt @@ -91,6 +91,9 @@ class TempBasalPair : TempBasalPair { val isCancelTBR: Boolean get() = MedtronicUtil.isSame(insulinRate, 0.0) && durationMinutes == 0 + val isZeroTBR: Boolean + get() = MedtronicUtil.isSame(insulinRate, 0.0) && durationMinutes != 0 + val description: String get() { if (isCancelTBR) { diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt index a0ce5241de..b4b3b6cefb 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/data/dto/TempBasalProcessDTO.kt @@ -4,9 +4,9 @@ import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.pump.common.utils.DateTimeUtil import info.nightscout.androidaps.plugins.pump.medtronic.comm.history.pump.PumpHistoryEntry +import java.lang.StringBuilder class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry, - var processOperation: Operation = Operation.None, var aapsLogger: AAPSLogger, var objectType: ObjectType = ObjectType.TemporaryBasal) { @@ -21,8 +21,6 @@ class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry, var itemOneTbr: TempBasalPair? = null var itemTwoTbr: TempBasalPair? = null - var cancelPresent: Boolean = false - val atechDateTime: Long get() = itemOne.atechDateTime @@ -31,26 +29,26 @@ class TempBasalProcessDTO constructor(var itemOne: PumpHistoryEntry, val durationAsSeconds: Int get() { - aapsLogger.debug(LTag.PUMP, "durationAsSeconds: [objectType=$objectType]") + //aapsLogger.debug(LTag.PUMP, "durationAsSeconds: [objectType=$objectType]") if (objectType == ObjectType.TemporaryBasal) { if (itemTwo == null) { if (itemOneTbr != null) { - aapsLogger.debug("TemporaryBasalPair - itemOneSingle: $itemOneTbr") + //aapsLogger.debug("TemporaryBasalPair - itemOneSingle: $itemOneTbr") return itemOneTbr!!.durationMinutes * 60 } else { - aapsLogger.error("Couldn't find TempBasalPair in entry: $itemOne") + //aapsLogger.error("Couldn't find TempBasalPair in entry: $itemOne") return 0 } } 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) - aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff") + //aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff") return secondsDiff } } 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) - aapsLogger.debug(LTag.PUMP, "Difference in seconds: $secondsDiff") + //aapsLogger.debug(LTag.PUMP, "Difference in seconds: $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 { - return "ItemOne: $itemOne, ItemTwo: $itemTwo, Duration: $durationAsSeconds, Operation: $processOperation, ObjectType: $objectType" + return "ItemOne: $itemOne, ItemTwo: $itemTwo, Duration: $durationAsSeconds, ObjectType: $objectType" } enum class Operation { diff --git a/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryDataUTest.kt b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryDataUTest.kt new file mode 100644 index 0000000000..4f9fef20c1 --- /dev/null +++ b/medtronic/src/test/java/info/nightscout/androidaps/plugins/pump/medtronic/data/MedtronicHistoryDataUTest.kt @@ -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?>() {}.getType() + val yourClassList: MutableList = gson.fromJson(fileText, listType) + + for (pumpHistoryEntry in yourClassList) { + val stringObject = pumpHistoryEntry.decodedData["Object"] as LinkedTreeMap + + 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()) + } + + } + + +} \ No newline at end of file diff --git a/medtronic/src/test/resources/tbr_data.json b/medtronic/src/test/resources/tbr_data.json new file mode 100644 index 0000000000..7e2aa44b84 --- /dev/null +++ b/medtronic/src/test/resources/tbr_data.json @@ -0,0 +1,1761 @@ +[{ + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:35:08", + "atechDateTime": 20211031013508, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:39:47", + "atechDateTime": 20211031013947, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:39:49", + "atechDateTime": 20211031013949, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.1500000000000001, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:49:41", + "atechDateTime": 20211031014941, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:49:43", + "atechDateTime": 20211031014943, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.8, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:54:59", + "atechDateTime": 20211031015459, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:55:05", + "atechDateTime": 20211031015505, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 01:59:43", + "atechDateTime": 20211031015943, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:04:45", + "atechDateTime": 20211031020445, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.55, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:09:47", + "atechDateTime": 20211031020947, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:09:48", + "atechDateTime": 20211031020948, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.35000000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:14:56", + "atechDateTime": 20211031021456, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:14:57", + "atechDateTime": 20211031021457, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.3000000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:25:16", + "atechDateTime": 20211031022516, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:25:18", + "atechDateTime": 20211031022518, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.85, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:29:50", + "atechDateTime": 20211031022950, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:29:51", + "atechDateTime": 20211031022951, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.25, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:34:45", + "atechDateTime": 20211031023445, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:34:47", + "atechDateTime": 20211031023447, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.0500000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:45:16", + "atechDateTime": 20211031024516, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:45:18", + "atechDateTime": 20211031024518, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.75, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:50:16", + "atechDateTime": 20211031025016, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:50:18", + "atechDateTime": 20211031025018, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:54:45", + "atechDateTime": 20211031025445, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:54:46", + "atechDateTime": 20211031025446, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.75, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 02:59:47", + "atechDateTime": 20211031025947, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:05:16", + "atechDateTime": 20211031030516, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.85, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:10:07", + "atechDateTime": 20211031031007, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:10:08", + "atechDateTime": 20211031031008, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.05, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:15:11", + "atechDateTime": 20211031031511, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:15:13", + "atechDateTime": 20211031031513, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:35:16", + "atechDateTime": 20211031033516, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:35:18", + "atechDateTime": 20211031033518, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:49:50", + "atechDateTime": 20211031034950, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:49:52", + "atechDateTime": 20211031034952, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.35000000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:55:07", + "atechDateTime": 20211031035507, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 03:55:08", + "atechDateTime": 20211031035508, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.9000000000000004, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:00:16", + "atechDateTime": 20211031040016, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:04:45", + "atechDateTime": 20211031040445, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.2, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:09:47", + "atechDateTime": 20211031040947, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:09:49", + "atechDateTime": 20211031040949, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:14:44", + "atechDateTime": 20211031041444, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.7000000000000002, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:24:42", + "atechDateTime": 20211031042442, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:24:43", + "atechDateTime": 20211031042443, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.05, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:30:16", + "atechDateTime": 20211031043016, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:30:18", + "atechDateTime": 20211031043018, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.2, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:34:45", + "atechDateTime": 20211031043445, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:34:47", + "atechDateTime": 20211031043447, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.35, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:44:43", + "atechDateTime": 20211031044443, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:44:44", + "atechDateTime": 20211031044444, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.85, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:49:41", + "atechDateTime": 20211031044941, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:49:43", + "atechDateTime": 20211031044943, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.35, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:54:44", + "atechDateTime": 20211031045444, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:54:45", + "atechDateTime": 20211031045445, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.8, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 04:59:51", + "atechDateTime": 20211031045951, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:04:44", + "atechDateTime": 20211031050444, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.35, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:09:46", + "atechDateTime": 20211031050946, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:09:47", + "atechDateTime": 20211031050947, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:15:16", + "atechDateTime": 20211031051516, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:15:18", + "atechDateTime": 20211031051518, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.5, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:20:07", + "atechDateTime": 20211031052007, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:20:08", + "atechDateTime": 20211031052008, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:34:44", + "atechDateTime": 20211031053444, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.6, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:39:46", + "atechDateTime": 20211031053946, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:39:47", + "atechDateTime": 20211031053947, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:49:48", + "atechDateTime": 20211031054948, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:49:49", + "atechDateTime": 20211031054949, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.4000000000000004, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 05:59:45", + "atechDateTime": 20211031055945, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:05:43", + "atechDateTime": 20211031060543, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:10:14", + "atechDateTime": 20211031061014, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:10:15", + "atechDateTime": 20211031061015, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.25, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:35:13", + "atechDateTime": 20211031063513, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:35:15", + "atechDateTime": 20211031063515, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.35, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:50:13", + "atechDateTime": 20211031065013, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:50:14", + "atechDateTime": 20211031065014, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.15000000000000002, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:51:08", + "atechDateTime": 20211031065108, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:51:10", + "atechDateTime": 20211031065110, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.9000000000000001, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:54:45", + "atechDateTime": 20211031065445, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 06:54:47", + "atechDateTime": 20211031065447, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:00:15", + "atechDateTime": 20211031070015, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:04:46", + "atechDateTime": 20211031070446, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.35, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:14:56", + "atechDateTime": 20211031071456, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:14:58", + "atechDateTime": 20211031071458, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.35000000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:19:53", + "atechDateTime": 20211031071953, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:19:55", + "atechDateTime": 20211031071955, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:25:20", + "atechDateTime": 20211031072520, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:25:22", + "atechDateTime": 20211031072522, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:39:46", + "atechDateTime": 20211031073946, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:44:44", + "atechDateTime": 20211031074444, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:44:46", + "atechDateTime": 20211031074446, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:55:14", + "atechDateTime": 20211031075514, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 07:55:16", + "atechDateTime": 20211031075516, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:00:17", + "atechDateTime": 20211031080017, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:04:46", + "atechDateTime": 20211031080446, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.1, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:14:48", + "atechDateTime": 20211031081448, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:14:50", + "atechDateTime": 20211031081450, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.55, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:29:46", + "atechDateTime": 20211031082946, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:29:48", + "atechDateTime": 20211031082948, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.4000000000000004, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:40:27", + "atechDateTime": 20211031084027, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:40:28", + "atechDateTime": 20211031084028, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.8, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:49:46", + "atechDateTime": 20211031084946, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:49:48", + "atechDateTime": 20211031084948, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.85, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:56:11", + "atechDateTime": 20211031085611, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:56:13", + "atechDateTime": 20211031085613, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.35, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 08:56:26", + "atechDateTime": 20211031085626, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:00:49", + "atechDateTime": 20211031090049, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.6, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:04:43", + "atechDateTime": 20211031090443, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:04:44", + "atechDateTime": 20211031090444, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:15:16", + "atechDateTime": 20211031091516, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:15:18", + "atechDateTime": 20211031091518, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.05, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:19:47", + "atechDateTime": 20211031091947, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:19:49", + "atechDateTime": 20211031091949, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.25, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:30:02", + "atechDateTime": 20211031093002, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:30:04", + "atechDateTime": 20211031093004, + "decodedData": { + "Object": { + "durationMinutes": 60, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:54:44", + "atechDateTime": 20211031095444, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.0500000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 09:59:51", + "atechDateTime": 20211031095951, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:05:22", + "atechDateTime": 20211031100522, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.8, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:09:45", + "atechDateTime": 20211031100945, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:09:47", + "atechDateTime": 20211031100947, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.2000000000000002, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:24:48", + "atechDateTime": 20211031102448, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:24:49", + "atechDateTime": 20211031102449, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.5, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:30:19", + "atechDateTime": 20211031103019, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:30:20", + "atechDateTime": 20211031103020, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.6000000000000001, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:35:16", + "atechDateTime": 20211031103516, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:35:17", + "atechDateTime": 20211031103517, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.4000000000000004, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:41:00", + "atechDateTime": 20211031104100, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:41:02", + "atechDateTime": 20211031104102, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 5.3500000000000005, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:49:48", + "atechDateTime": 20211031104948, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:49:49", + "atechDateTime": 20211031104949, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.2000000000000002, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 10:59:44", + "atechDateTime": 20211031105944, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:05:18", + "atechDateTime": 20211031110518, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.9000000000000001, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:10:34", + "atechDateTime": 20211031111034, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:10:35", + "atechDateTime": 20211031111035, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 1.4500000000000002, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:14:48", + "atechDateTime": 20211031111448, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:14:50", + "atechDateTime": 20211031111450, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:30:15", + "atechDateTime": 20211031113015, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.5, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:45:43", + "atechDateTime": 20211031114543, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:45:44", + "atechDateTime": 20211031114544, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.25, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:50:12", + "atechDateTime": 20211031115012, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:50:13", + "atechDateTime": 20211031115013, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.05, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:54:45", + "atechDateTime": 20211031115445, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:54:46", + "atechDateTime": 20211031115446, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.8000000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 11:59:49", + "atechDateTime": 20211031115949, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:04:47", + "atechDateTime": 20211031120447, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.25, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:14:46", + "atechDateTime": 20211031121446, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:14:48", + "atechDateTime": 20211031121448, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.5500000000000003, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:19:45", + "atechDateTime": 20211031121945, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:19:47", + "atechDateTime": 20211031121947, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.2, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:20:24", + "atechDateTime": 20211031122024, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:20:26", + "atechDateTime": 20211031122026, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.15, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:24:52", + "atechDateTime": 20211031122452, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:24:53", + "atechDateTime": 20211031122453, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 0.05, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:25:01", + "atechDateTime": 20211031122501, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:25:03", + "atechDateTime": 20211031122503, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.15, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:34:45", + "atechDateTime": 20211031123445, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:34:47", + "atechDateTime": 20211031123447, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 2.95, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:39:47", + "atechDateTime": 20211031123947, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:39:49", + "atechDateTime": 20211031123949, + "decodedData": { + "Object": { + "durationMinutes": 30, + "insulinRate": 3.6, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:41:18", + "atechDateTime": 20211031124118, + "decodedData": { + "Object": { + "durationMinutes": 0, + "insulinRate": 0.0, + "isPercent": false + } + } +}, { + "entryType": "TempBasalCombined", + "DT": "31.10.2021 12:41:19", + "atechDateTime": 20211031124119, + "decodedData": { + "Object": { + "durationMinutes": 60, + "insulinRate": 0.0, + "isPercent": false + } + } +}] diff --git a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt index ac39b3fab1..7b34490067 100644 --- a/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt +++ b/pump-common/src/main/java/info/nightscout/androidaps/plugins/pump/common/PumpPluginAbstract.kt @@ -323,6 +323,7 @@ abstract class PumpPluginAbstract protected constructor( return ret } + @Synchronized override fun deliverTreatment(detailedBolusInfo: DetailedBolusInfo): PumpEnactResult { return try { if (detailedBolusInfo.insulin == 0.0 && detailedBolusInfo.carbs == 0.0) { From 25c048640d1f7d0721cb05f4b66e5caea17d1894 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 9 Nov 2021 15:26:09 +0100 Subject: [PATCH 04/34] Glunovo plugin --- .../activities/MyPreferenceFragment.kt | 3 + .../dependencyInjection/PluginsModule.kt | 6 + .../plugins/source/BGSourceFragment.kt | 1 + .../plugins/source/GlunovoPlugin.kt | 125 ++++++++++++++++++ app/src/main/res/values/strings.xml | 2 + .../userEntry/UserEntryPresentationHelper.kt | 1 + core/src/main/res/drawable/ic_glunovo.xml | 85 ++++++++++++ .../database/entities/GlucoseValue.kt | 1 + .../androidaps/database/entities/UserEntry.kt | 1 + 9 files changed, 225 insertions(+) create mode 100644 app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt create mode 100644 core/src/main/res/drawable/ic_glunovo.xml diff --git a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt index 143919db87..b9cd7b9d0a 100644 --- a/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/activities/MyPreferenceFragment.kt @@ -48,6 +48,7 @@ import info.nightscout.androidaps.plugins.source.EversensePlugin import info.nightscout.androidaps.plugins.source.GlimpPlugin import info.nightscout.androidaps.plugins.source.PoctechPlugin import info.nightscout.androidaps.plugins.source.TomatoPlugin +import info.nightscout.androidaps.plugins.source.GlunovoPlugin import info.nightscout.androidaps.utils.SafeParse import info.nightscout.androidaps.utils.alertDialogs.OKDialog.show import info.nightscout.androidaps.utils.protection.PasswordCheck @@ -90,6 +91,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang @Inject lateinit var glimpPlugin: GlimpPlugin @Inject lateinit var poctechPlugin: PoctechPlugin @Inject lateinit var tomatoPlugin: TomatoPlugin + @Inject lateinit var glunovoPlugin: GlunovoPlugin @Inject lateinit var smsCommunicatorPlugin: SmsCommunicatorPlugin @Inject lateinit var statusLinePlugin: StatusLinePlugin @Inject lateinit var tidepoolPlugin: TidepoolPlugin @@ -160,6 +162,7 @@ class MyPreferenceFragment : PreferenceFragmentCompat(), OnSharedPreferenceChang addPreferencesFromResourceIfEnabled(eversensePlugin, rootKey) addPreferencesFromResourceIfEnabled(dexcomPlugin, rootKey) addPreferencesFromResourceIfEnabled(tomatoPlugin, rootKey) + addPreferencesFromResourceIfEnabled(glunovoPlugin, rootKey) addPreferencesFromResourceIfEnabled(poctechPlugin, rootKey) addPreferencesFromResourceIfEnabled(glimpPlugin, rootKey) addPreferencesFromResourceIfEnabled(loopPlugin, rootKey, config.APS) diff --git a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt index 2a14115056..6d58752f2b 100644 --- a/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt +++ b/app/src/main/java/info/nightscout/androidaps/dependencyInjection/PluginsModule.kt @@ -353,6 +353,12 @@ abstract class PluginsModule { @AllConfigs @IntoMap @IntKey(470) + abstract fun bindGlunovoPlugin(plugin: GlunovoPlugin): PluginBase + + @Binds + @AllConfigs + @IntoMap + @IntKey(475) abstract fun bindRandomBgPlugin(plugin: RandomBgPlugin): PluginBase // @Binds diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt index 48b3dbc80e..c942bf413d 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/BGSourceFragment.kt @@ -140,6 +140,7 @@ class BGSourceFragment : DaggerFragment() { R.string.nsclientbg -> Sources.NSClientSource R.string.poctech -> Sources.PocTech R.string.tomato -> Sources.Tomato + R.string.glunovo -> Sources.Glunovo R.string.xdrip -> Sources.Xdrip else -> Sources.Unknown } diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt new file mode 100644 index 0000000000..ed5ebc609d --- /dev/null +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -0,0 +1,125 @@ +package info.nightscout.androidaps.plugins.source + +import android.content.Context +import android.net.Uri +import android.os.Handler +import android.os.HandlerThread +import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.R +import info.nightscout.androidaps.database.AppRepository +import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.transactions.CgmSourceTransaction +import info.nightscout.androidaps.interfaces.BgSource +import info.nightscout.androidaps.interfaces.PluginBase +import info.nightscout.androidaps.interfaces.PluginDescription +import info.nightscout.androidaps.interfaces.PluginType +import info.nightscout.androidaps.logging.AAPSLogger +import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.XDripBroadcast +import info.nightscout.androidaps.utils.resources.ResourceHelper +import info.nightscout.androidaps.utils.sharedPreferences.SP +import io.reactivex.disposables.CompositeDisposable +import java.util.* +import javax.inject.Inject +import javax.inject.Singleton + +@Singleton +class GlunovoPlugin @Inject constructor( + injector: HasAndroidInjector, + resourceHelper: ResourceHelper, + aapsLogger: AAPSLogger, + private val sp: SP, + private val context: Context, + private val repository: AppRepository, + private val broadcastToXDrip: XDripBroadcast +) : PluginBase( + PluginDescription() + .mainType(PluginType.BGSOURCE) + .fragmentClass(BGSourceFragment::class.java.name) + .pluginIcon(R.drawable.ic_glunovo) + .pluginName(R.string.glunovo) + .preferencesId(R.xml.pref_bgsource) + .shortName(R.string.glunovo) + .description(R.string.description_source_glunovo), + aapsLogger, resourceHelper, injector +), BgSource { + + private val loopHandler: Handler = Handler(HandlerThread(this::class.java.simpleName + "Handler").also { it.start() }.looper) + private lateinit var refreshLoop: Runnable + + private val contentUri: Uri = Uri.parse("content://$AUTHORITY/$TABLE_NAME") + + init { + refreshLoop = Runnable { + loopHandler.postDelayed(refreshLoop, INTERVAL) + handleNewData() + } + } + + private val disposable = CompositeDisposable() + + override fun onStart() { + super.onStart() + loopHandler.postDelayed(refreshLoop, INTERVAL) + } + + override fun onStop() { + super.onStop() + loopHandler.removeCallbacks(refreshLoop) + disposable.clear() + } + + private fun handleNewData() { + if (!isEnabled()) return + + context.contentResolver.query(contentUri, null, null, null, null)?.let { cr -> + cr.moveToLast() + val curTime = Calendar.getInstance().timeInMillis + val time = cr.getLong(0) + val value = cr.getDouble(1) //value in mmol/l... + if (time > curTime || time == 0L) { + aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $time") + return + } + + if (value < 2 || value > 25) { + aapsLogger.error(LTag.BGSOURCE, "Error in received data value (value out of bounds) $value") + return + } + + val glucoseValues = mutableListOf() + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = time, + value = value, + raw = 0.0, + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE + ) + repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) + } + .blockingGet() + .also { savedValues -> + savedValues.inserted.forEach { + broadcastToXDrip(it) + aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") + } + } + + cr.close() + } + } + + override fun shouldUploadToNs(glucoseValue: GlucoseValue): Boolean = + glucoseValue.sourceSensor == GlucoseValue.SourceSensor.GLUNOVO_NATIVE && sp.getBoolean(R.string.key_dexcomg5_nsupload, false) + + companion object { + + @Suppress("SpellCheckingInspection") + const val AUTHORITY = "alexpr.co.uk.infinivocgm.cgm_db.CgmExternalProvider/" + const val TABLE_NAME = "CgmReading" + const val INTERVAL = 180000L // 3 min + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4d24ca2e1d..f776a6b2de 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -807,6 +807,8 @@ Time elapsed Poctech Receive BG values from Poctech app + Glunovo + Receive values from Glunovo app Receive BG values from Tomato app (MiaoMiao device) high_temptarget_raises_sensitivity low_temptarget_lowers_sensitivity diff --git a/core/src/main/java/info/nightscout/androidaps/utils/userEntry/UserEntryPresentationHelper.kt b/core/src/main/java/info/nightscout/androidaps/utils/userEntry/UserEntryPresentationHelper.kt index 2472ef84b8..615a0be902 100644 --- a/core/src/main/java/info/nightscout/androidaps/utils/userEntry/UserEntryPresentationHelper.kt +++ b/core/src/main/java/info/nightscout/androidaps/utils/userEntry/UserEntryPresentationHelper.kt @@ -70,6 +70,7 @@ class UserEntryPresentationHelper @Inject constructor( Sources.NSClientSource -> R.drawable.ic_nsclient_bg Sources.PocTech -> R.drawable.ic_poctech Sources.Tomato -> R.drawable.ic_sensor + Sources.Glunovo -> R.drawable.ic_glunovo Sources.Xdrip -> R.drawable.ic_blooddrop_48 Sources.LocalProfile -> R.drawable.ic_local_profile Sources.Loop -> R.drawable.ic_loop_closed_white diff --git a/core/src/main/res/drawable/ic_glunovo.xml b/core/src/main/res/drawable/ic_glunovo.xml new file mode 100644 index 0000000000..6fe7de817b --- /dev/null +++ b/core/src/main/res/drawable/ic_glunovo.xml @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt index a292557866..241485a254 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/GlucoseValue.kt @@ -108,6 +108,7 @@ data class GlucoseValue( GLIMP("Glimp"), LIBRE_2_NATIVE("Libre2"), POCTECH_NATIVE("Poctech"), + GLUNOVO_NATIVE("Glunovo"), MM_600_SERIES("MM600Series"), EVERSENSE("Eversense"), RANDOM("Random"), diff --git a/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt b/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt index 889f365ec4..0b0db5bf82 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/entities/UserEntry.kt @@ -146,6 +146,7 @@ data class UserEntry( NSClientSource, PocTech, Tomato, + Glunovo, Xdrip, LocalProfile, //From LocalProfile plugin Loop, //From Loop plugin From ffa4120cd5278b637dd47579ba95f8698cb32618 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 9 Nov 2021 18:42:55 +0100 Subject: [PATCH 05/34] improve glunovo logic --- .../plugins/source/GlunovoPlugin.kt | 95 +++++++++++-------- app/src/main/res/values/strings.xml | 1 + 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index ed5ebc609d..cc2639e41e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -5,6 +5,7 @@ import android.net.Uri import android.os.Handler import android.os.HandlerThread import dagger.android.HasAndroidInjector +import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue @@ -15,13 +16,16 @@ import info.nightscout.androidaps.interfaces.PluginDescription import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.utils.DateUtil +import info.nightscout.androidaps.utils.FabricPrivacy +import info.nightscout.androidaps.utils.T import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable -import java.util.* import javax.inject.Inject import javax.inject.Singleton +import kotlin.math.min @Singleton class GlunovoPlugin @Inject constructor( @@ -31,7 +35,9 @@ class GlunovoPlugin @Inject constructor( private val sp: SP, private val context: Context, private val repository: AppRepository, - private val broadcastToXDrip: XDripBroadcast + private val broadcastToXDrip: XDripBroadcast, + private val dateUtil: DateUtil, + private val fabricPrivacy: FabricPrivacy ) : PluginBase( PluginDescription() .mainType(PluginType.BGSOURCE) @@ -51,8 +57,15 @@ class GlunovoPlugin @Inject constructor( init { refreshLoop = Runnable { - loopHandler.postDelayed(refreshLoop, INTERVAL) - handleNewData() + try { + handleNewData() + } catch (e: Exception) { + fabricPrivacy.logException(e) + aapsLogger.error("Error while processing data", e) + } + val lastReadTimestamp = sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L) + val differenceToNow = min(INTERVAL, dateUtil.now() - lastReadTimestamp + INTERVAL + T.secs(10).msecs()) + loopHandler.postDelayed(refreshLoop, differenceToNow) } } @@ -60,7 +73,7 @@ class GlunovoPlugin @Inject constructor( override fun onStart() { super.onStart() - loopHandler.postDelayed(refreshLoop, INTERVAL) + loopHandler.postDelayed(refreshLoop, T.secs(30).msecs()) // do not start immediately, app may be still starting } override fun onStop() { @@ -73,42 +86,50 @@ class GlunovoPlugin @Inject constructor( if (!isEnabled()) return context.contentResolver.query(contentUri, null, null, null, null)?.let { cr -> - cr.moveToLast() - val curTime = Calendar.getInstance().timeInMillis - val time = cr.getLong(0) - val value = cr.getDouble(1) //value in mmol/l... - if (time > curTime || time == 0L) { - aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $time") - return - } - - if (value < 2 || value > 25) { - aapsLogger.error(LTag.BGSOURCE, "Error in received data value (value out of bounds) $value") - return - } - val glucoseValues = mutableListOf() - glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( - timestamp = time, - value = value, - raw = 0.0, - noise = null, - trendArrow = GlucoseValue.TrendArrow.NONE, - sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE - ) - repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) - .doOnError { - aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) - } - .blockingGet() - .also { savedValues -> - savedValues.inserted.forEach { - broadcastToXDrip(it) - aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") - } + cr.moveToFirst() + + while (!cr.isAfterLast) { + val timestamp = cr.getLong(0) + val value = cr.getDouble(1) //value in mmol/l... + if (timestamp > dateUtil.now() || timestamp == 0L) { + aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $timestamp") + continue } + if (value < 2 || value > 25) { + aapsLogger.error(LTag.BGSOURCE, "Error in received data value (value out of bounds) $value") + continue + } + + // bypass already processed + if (timestamp < sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L)) continue + + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = timestamp, + value = value * Constants.MMOLL_TO_MGDL, + raw = 0.0, + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE + ) + sp.putLong(R.string.key_last_processed_glunovo_timestamp, timestamp) + cr.moveToNext() + } cr.close() + + if (glucoseValues.isNotEmpty()) + repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) + .doOnError { + aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) + } + .blockingGet() + .also { savedValues -> + savedValues.inserted.forEach { + broadcastToXDrip(it) + aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") + } + } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index f776a6b2de..1beca8f6d9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1134,5 +1134,6 @@ BG data status Recalculated data used BG too close:\n%1$s\n%2$s + last_processed_glunovo_timestamp From 56d97861e3522b6a53436f8895548c6d2bb50ea9 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Tue, 9 Nov 2021 20:22:33 +0100 Subject: [PATCH 06/34] fix glunovo loop --- .../nightscout/androidaps/plugins/source/GlunovoPlugin.kt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index cc2639e41e..c15c4a6ce0 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -94,16 +94,21 @@ class GlunovoPlugin @Inject constructor( val value = cr.getDouble(1) //value in mmol/l... if (timestamp > dateUtil.now() || timestamp == 0L) { aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $timestamp") + cr.moveToNext() continue } if (value < 2 || value > 25) { aapsLogger.error(LTag.BGSOURCE, "Error in received data value (value out of bounds) $value") + cr.moveToNext() continue } // bypass already processed - if (timestamp < sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L)) continue + if (timestamp < sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L)) { + cr.moveToNext() + continue + } glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( timestamp = timestamp, From af7a22a5dfe987f057f7203f04c980328a684419 Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Tue, 9 Nov 2021 19:53:47 +0000 Subject: [PATCH 07/34] - small fix on MedtronicHistoryEntry initialization - added version string into initialixzation of MedtrinicPumpPlugin --- .../plugins/pump/medtronic/MedtronicPumpPlugin.kt | 2 +- .../medtronic/comm/history/MedtronicHistoryEntry.kt | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt index 0f287db750..b6c5933895 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/MedtronicPumpPlugin.kt @@ -112,7 +112,7 @@ class MedtronicPumpPlugin @Inject constructor( private var isBusy = false override fun onStart() { - aapsLogger.debug(LTag.PUMP, deviceID() + " started.") + aapsLogger.debug(LTag.PUMP, deviceID() + " started. (V2.0005)") serviceConnection = object : ServiceConnection { override fun onServiceDisconnected(name: ComponentName) { aapsLogger.debug(LTag.PUMP, "RileyLinkMedtronicService is disconnected") diff --git a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt index 6730439a4b..8776906d95 100644 --- a/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt +++ b/medtronic/src/main/java/info/nightscout/androidaps/plugins/pump/medtronic/comm/history/MedtronicHistoryEntry.kt @@ -14,13 +14,13 @@ import info.nightscout.androidaps.plugins.pump.common.utils.StringUtil */ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { - lateinit var rawData: List + var rawData: List = listOf() protected var sizes = IntArray(3) - lateinit var head: ByteArray - lateinit var datetime: ByteArray - lateinit var body: ByteArray + var head: ByteArray = byteArrayOf() + var datetime: ByteArray = byteArrayOf() + var body: ByteArray = byteArrayOf() var id: Long = 0 @@ -164,7 +164,7 @@ abstract class MedtronicHistoryEntry : MedtronicHistoryEntryInterface { sb.append("]") return sb.toString() } - if (head.size != 0) { + if (head!=null && head.size != 0) { sb.append(", head=") sb.append(ByteUtil.shortHexString(head)) } From bb7632aa806f66b78284c15348a2c6e5d3762f56 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Wed, 10 Nov 2021 12:25:07 +0100 Subject: [PATCH 08/34] Glunovo change schedule --- .../info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index c15c4a6ce0..f8af965921 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -25,7 +25,6 @@ import info.nightscout.androidaps.utils.sharedPreferences.SP import io.reactivex.disposables.CompositeDisposable import javax.inject.Inject import javax.inject.Singleton -import kotlin.math.min @Singleton class GlunovoPlugin @Inject constructor( @@ -64,7 +63,7 @@ class GlunovoPlugin @Inject constructor( aapsLogger.error("Error while processing data", e) } val lastReadTimestamp = sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L) - val differenceToNow = min(INTERVAL, dateUtil.now() - lastReadTimestamp + INTERVAL + T.secs(10).msecs()) + val differenceToNow = INTERVAL - (dateUtil.now() - lastReadTimestamp) % INTERVAL + T.secs(10).msecs() loopHandler.postDelayed(refreshLoop, differenceToNow) } } From d5ae4cabf282d7a3f18e573cc622fc33bf0bc320 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Wed, 10 Nov 2021 23:10:26 +0100 Subject: [PATCH 09/34] call stopConnecting only once --- .../main/java/info/nightscout/androidaps/queue/QueueThread.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt index 1bdbdc7d64..df3ce83881 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt @@ -60,7 +60,6 @@ class QueueThread internal constructor( //write time sp.putLong(R.string.key_btwatchdog_lastbark, System.currentTimeMillis()) //toggle BT - pump.stopConnecting() pump.disconnect("watchdog") SystemClock.sleep(1000) val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter() From 3a9213992b9332cc6cb22381cd05e7fc200e752e Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 11 Nov 2021 00:18:56 +0100 Subject: [PATCH 10/34] fix connnecting quality counter --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 4 +-- .../pod/state/OmnipodDashPodStateManager.kt | 4 +++ .../state/OmnipodDashPodStateManagerImpl.kt | 33 ++++++++++++++----- .../dash/ui/OmnipodDashOverviewFragment.kt | 10 +++--- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index ce3a4a3e7b..3e8d4920bb 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -235,7 +235,6 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun connect(reason: String) { aapsLogger.info(LTag.PUMP, "connect reason=$reason") podStateManager.bluetoothConnectionState = OmnipodDashPodStateManager.BluetoothConnectionState.CONNECTING - synchronized(this) { stopConnecting?.let { aapsLogger.warn(LTag.PUMP, "Already connecting: $stopConnecting") @@ -244,7 +243,7 @@ class OmnipodDashPumpPlugin @Inject constructor( val stop = CountDownLatch(1) stopConnecting = stop } - + podStateManager.incrementConnectionAttemptsWithRetries() thread( start = true, name = "ConnectionThread", @@ -270,6 +269,7 @@ class OmnipodDashPumpPlugin @Inject constructor( override fun stopConnecting() { aapsLogger.info(LTag.PUMP, "stopConnecting") + podStateManager.incrementFailedConnectionsAfterRetries() stopConnecting?.countDown() omnipodManager.disconnect(true) } diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index 6f5ab0ee62..652819fa11 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -33,6 +33,8 @@ interface OmnipodDashPodStateManager { var bluetoothConnectionState: BluetoothConnectionState var connectionAttempts: Int var successfulConnections: Int + val connectionAttemptsWithRetries: Int + val failedConnectionsAfterRetries: Int var timeZone: TimeZone val sameTimeZone: Boolean // The TimeZone is the same on the phone and on the pod @@ -85,6 +87,8 @@ interface OmnipodDashPodStateManager { fun updateFromPairing(uniqueId: Id, pairResult: PairResult) fun reset() fun connectionSuccessRatio(): Float + fun incrementConnectionAttemptsWithRetries() + fun incrementFailedConnectionsAfterRetries() fun createActiveCommand( historyId: String, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 07404b8607..9ab82212c1 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -114,6 +114,23 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.successfulConnections = value } + override val connectionAttemptsWithRetries: Int + @Synchronized + get() = podState.connectionAttemptsWithRetries + + @Synchronized + override fun incrementConnectionAttemptsWithRetries() { + podState.connectionAttemptsWithRetries++ + } + + override val failedConnectionsAfterRetries: Int + @Synchronized + get() = podState.failedConnectionsAfterRetries + + override fun incrementFailedConnectionsAfterRetries() { + podState.failedConnectionsAfterRetries++ + } + override var timeZone: TimeZone get() = TimeZone.getTimeZone(podState.timeZone) set(tz) { @@ -129,10 +146,12 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( val podOffset = timeZone.getOffset(now) logger.debug( LTag.PUMPCOMM, - "sameTimeZone currentTimezone=${currentTimezone.getDisplayName( + "sameTimeZone currentTimezone=${ + currentTimezone.getDisplayName( true, TimeZone.SHORT - )} " + + ) + } " + "currentOffset=$currentOffset " + "podOffset=$podOffset" ) @@ -627,13 +646,10 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } override fun connectionSuccessRatio(): Float { - if (connectionAttempts == 0) { + if (connectionAttemptsWithRetries == 0) { return 0.0F - } else if (connectionAttempts <= successfulConnections) { - // Prevent bogus quality > 1 during initialisation - return 1.0F } - return successfulConnections.toFloat() / connectionAttempts.toFloat() + return 1 - (failedConnectionsAfterRetries.toFloat() / connectionAttemptsWithRetries) } override fun reset() { @@ -675,6 +691,8 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED var connectionAttempts = 0 var successfulConnections = 0 + var connectionAttemptsWithRetries = 0 + var failedConnectionsAfterRetries = 0 var messageSequenceNumber: Short = 0 var sequenceNumberOfLastProgrammingCommand: Short? = null var activationTime: Long? = null @@ -682,7 +700,6 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var bluetoothAddress: String? = null var ltk: ByteArray? = null var eapAkaSequenceNumber: Long = 1 - var bolusPulsesRemaining: Short = 0 var timeZone: String = "" // TimeZone ID (e.g. "Europe/Amsterdam") var alarmSynced: Boolean = false diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 4703b82d0c..3f87aad83d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -256,15 +256,15 @@ class OmnipodDashOverviewFragment : DaggerFragment() { val connectionSuccessPercentage = podStateManager.connectionSuccessRatio() * 100 val successPercentageString = String.format("%.2f %%", connectionSuccessPercentage) val quality = - "${podStateManager.successfulConnections}/${podStateManager.connectionAttempts} :: $successPercentageString" + "${podStateManager.connectionAttemptsWithRetries - podStateManager.failedConnectionsAfterRetries}/${podStateManager.connectionAttemptsWithRetries} :: $successPercentageString" bluetoothStatusBinding.omnipodDashBluetoothConnectionQuality.text = quality val connectionStatsColor = when { - connectionSuccessPercentage > 90 -> - Color.WHITE - connectionSuccessPercentage > 60 -> + connectionSuccessPercentage < 70 && podStateManager.connectionAttemptsWithRetries > 50 -> + Color.RED + connectionSuccessPercentage < 90 && podStateManager.connectionAttemptsWithRetries > 50 -> Color.YELLOW else -> - Color.RED + Color.WHITE } bluetoothStatusBinding.omnipodDashBluetoothConnectionQuality.setTextColor(connectionStatsColor) bluetoothStatusBinding.omnipodDashDeliveryStatus.text = podStateManager.deliveryStatus?.let { From 311f04fe6d358c81c6e2d969453a402def0c25ec Mon Sep 17 00:00:00 2001 From: Andy Rozman Date: Wed, 10 Nov 2021 23:40:27 +0000 Subject: [PATCH 11/34] - add changelog file --- medtronic/Changelog.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 medtronic/Changelog.txt diff --git a/medtronic/Changelog.txt b/medtronic/Changelog.txt new file mode 100644 index 0000000000..fc0b934b1c --- /dev/null +++ b/medtronic/Changelog.txt @@ -0,0 +1,11 @@ + +V1 - Medtronic initial implementation +... lots of changes + + +V2 - Rewrite into kotlin, new database (for v3.0) +0001 - initial version +0002 - some fixes +0003 - SMB fix (798) +0004 - Zero TBR Duration fix (798), refactoring of TempBasalProcessDTO +0005 - fixes to MedtronicHistoryEntry lateinit problem \ No newline at end of file From 85178ee19ff628dfe4422409973c6f8ae7b511b5 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 11:04:24 +0100 Subject: [PATCH 12/34] End TBR before connectNewPump --- .../androidaps/interfaces/PumpSync.kt | 32 +++++++++++++++-- .../configBuilder/RunningConfiguration.kt | 2 +- .../plugins/pump/PumpSyncImplementation.kt | 20 ++++++++--- .../plugins/pump/common/defs/PumpType.kt | 35 +++++++++++++++++++ .../database/embedments/InterfaceIDs.kt | 2 -- 5 files changed, 81 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt index cc14666dac..f7a6acb102 100644 --- a/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt +++ b/core/src/main/java/info/nightscout/androidaps/interfaces/PumpSync.kt @@ -27,8 +27,13 @@ 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 */ - fun connectNewPump() + + // @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) /* * GENERAL STATUS @@ -55,8 +60,29 @@ interface PumpSync { */ data class PumpState(val temporaryBasal: TemporaryBasal?, val extendedBolus: ExtendedBolus?, val bolus: Bolus?, val profile: Profile?) { - data class TemporaryBasal(val timestamp: Long, val duration: Long, val rate: Double, val isAbsolute: Boolean, val type: TemporaryBasalType, val id: Long, val pumpId: Long?) - data class ExtendedBolus(val timestamp: Long, val duration: Long, val amount: Double, val rate: Double) + data class TemporaryBasal @JvmOverloads constructor( + val timestamp: Long, + val duration: Long, + val rate: Double, + val isAbsolute: Boolean, + val type: TemporaryBasalType, + val id: Long, + val pumpId: Long?, + // used only to cancel TBR on pump change + val pumpType: PumpType = PumpType.USER, + val pumpSerial: String = "" + ) + + data class ExtendedBolus @JvmOverloads constructor( + val timestamp: Long, + val duration: Long, + val amount: Double, + val rate: Double, + // used only to cancel EB on pump change + val pumpType: PumpType = PumpType.USER, + val pumpSerial: String = "" + ) + data class Bolus(val timestamp: Long, val amount: Double) } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt b/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt index 2e5b3871b5..b255a7e327 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt @@ -100,7 +100,7 @@ class RunningConfiguration @Inject constructor( if (sp.getString(R.string.key_virtualpump_type, "fake") != pumpType) { sp.putString(R.string.key_virtualpump_type, pumpType) activePlugin.activePump.pumpDescription.fillFor(PumpType.getByDescription(pumpType)) - pumpSync.connectNewPump() + pumpSync.connectNewPump(endRunning = false) // do not end running TBRs, we call this only to accept data properly aapsLogger.debug(LTag.CORE, "Changing pump type to $pumpType") } } diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt index 7cf4d09b88..66b7112b96 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/PumpSyncImplementation.kt @@ -37,7 +37,15 @@ class PumpSyncImplementation @Inject constructor( private val disposable = CompositeDisposable() - override fun connectNewPump() { + override fun connectNewPump(endRunning: Boolean) { + if (endRunning) { + expectedPumpState().temporaryBasal?.let { + syncStopTemporaryBasalWithPumpId(dateUtil.now(), dateUtil.now(), it.pumpType, it.pumpSerial) + } + expectedPumpState().extendedBolus?.let { + syncStopExtendedBolusWithPumpId(dateUtil.now(), dateUtil.now(), it.pumpType, it.pumpSerial) + } + } sp.remove(R.string.key_active_pump_type) sp.remove(R.string.key_active_pump_serial_number) sp.remove(R.string.key_active_pump_change_timestamp) @@ -77,7 +85,7 @@ class PumpSyncImplementation @Inject constructor( } override fun expectedPumpState(): PumpSync.PumpState { - val bolus = repository.getLastBolusRecordWrapped().blockingGet(); + val bolus = repository.getLastBolusRecordWrapped().blockingGet() val temporaryBasal = repository.getTemporaryBasalActiveAt(dateUtil.now()).blockingGet() val extendedBolus = repository.getExtendedBolusActiveAt(dateUtil.now()).blockingGet() @@ -91,7 +99,9 @@ class PumpSyncImplementation @Inject constructor( rate = temporaryBasal.value.rate, isAbsolute = temporaryBasal.value.isAbsolute, 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, + pumpSerial = temporaryBasal.value.interfaceIDs.pumpSerial ?: "", ) else null, extendedBolus = @@ -100,7 +110,9 @@ class PumpSyncImplementation @Inject constructor( timestamp = extendedBolus.value.timestamp, duration = extendedBolus.value.duration, amount = extendedBolus.value.amount, - rate = extendedBolus.value.rate + rate = extendedBolus.value.rate, + pumpType = extendedBolus.value.interfaceIDs.pumpType?.let { PumpType.fromDbPumpType(it)} ?: PumpType.USER, + pumpSerial = extendedBolus.value.interfaceIDs.pumpSerial ?: "" ) else null, bolus = diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt index 8783644cde..be39b6dda7 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/pump/common/defs/PumpType.kt @@ -359,6 +359,41 @@ enum class PumpType { fun getByDescription(desc: String): PumpType = values().firstOrNull { it.description == desc } ?: GENERIC_AAPS + + fun fromDbPumpType(pt: InterfaceIDs.PumpType): PumpType = + when (pt) { + InterfaceIDs.PumpType.GENERIC_AAPS -> GENERIC_AAPS + InterfaceIDs.PumpType.CELLNOVO -> CELLNOVO + InterfaceIDs.PumpType.ACCU_CHEK_COMBO -> ACCU_CHEK_COMBO + InterfaceIDs.PumpType.ACCU_CHEK_SPIRIT -> ACCU_CHEK_SPIRIT + InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT -> ACCU_CHEK_INSIGHT_VIRTUAL + InterfaceIDs.PumpType.ACCU_CHEK_INSIGHT_BLUETOOTH -> ACCU_CHEK_INSIGHT + InterfaceIDs.PumpType.ACCU_CHEK_SOLO -> ACCU_CHEK_SOLO + InterfaceIDs.PumpType.ANIMAS_VIBE -> ANIMAS_VIBE + InterfaceIDs.PumpType.ANIMAS_PING -> ANIMAS_PING + InterfaceIDs.PumpType.DANA_R -> DANA_R + InterfaceIDs.PumpType.DANA_R_KOREAN -> DANA_R_KOREAN + InterfaceIDs.PumpType.DANA_RS -> DANA_RS + InterfaceIDs.PumpType.DANA_RS_KOREAN -> DANA_RS_KOREAN + InterfaceIDs.PumpType.DANA_RV2 -> DANA_RV2 + InterfaceIDs.PumpType.DANA_I -> DANA_I + InterfaceIDs.PumpType.OMNIPOD_EROS -> OMNIPOD_EROS + InterfaceIDs.PumpType.OMNIPOD_DASH -> OMNIPOD_DASH + InterfaceIDs.PumpType.MEDTRONIC_512_517 -> MEDTRONIC_512_712 + InterfaceIDs.PumpType.MEDTRONIC_515_715 -> MEDTRONIC_515_715 + InterfaceIDs.PumpType.MEDTRONIC_522_722 -> MEDTRONIC_522_722 + InterfaceIDs.PumpType.MEDTRONIC_523_723_REVEL -> MEDTRONIC_523_723_REVEL + InterfaceIDs.PumpType.MEDTRONIC_554_754_VEO -> MEDTRONIC_554_754_VEO + InterfaceIDs.PumpType.MEDTRONIC_640G -> MEDTRONIC_640G + InterfaceIDs.PumpType.TANDEM_T_SLIM -> TANDEM_T_SLIM + InterfaceIDs.PumpType.TANDEM_T_SLIM_G4 -> TANDEM_T_SLIM_G4 + InterfaceIDs.PumpType.TANDEM_T_FLEX -> TANDEM_T_FLEX + InterfaceIDs.PumpType.TANDEM_T_SLIM_X2 -> TANDEM_T_SLIM_X2 + InterfaceIDs.PumpType.YPSOPUMP -> YPSOPUMP + InterfaceIDs.PumpType.MDI -> MDI + InterfaceIDs.PumpType.USER -> USER + InterfaceIDs.PumpType.DIACONN_G8 -> DIACONN_G8 + } } constructor(description: String, model: String, parent: PumpType, pumpCapability: PumpCapability? = null, source: Sources? = null) { diff --git a/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt b/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt index b06098f4ee..0477dc1c8d 100644 --- a/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt +++ b/database/src/main/java/info/nightscout/androidaps/database/embedments/InterfaceIDs.kt @@ -1,7 +1,5 @@ package info.nightscout.androidaps.database.embedments -import info.nightscout.androidaps.database.entities.TherapyEvent - data class InterfaceIDs( var nightscoutSystemId: String? = null, var nightscoutId: String? = null, From 88a8d08f5657805c7c68f36505387fc9f13c77a6 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 14:23:22 +0100 Subject: [PATCH 13/34] restore xdrip broadcast --- .../nsclient/services/NSClientService.kt | 75 ++---------------- .../nightscout/androidaps/services/Intents.kt | 7 +- .../androidaps/utils/XDripBroadcast.kt | 76 ++++++++++++++++++- 3 files changed, 81 insertions(+), 77 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt index 77a09e402e..5a5bda55a3 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/nsclient/services/NSClientService.kt @@ -3,7 +3,6 @@ package info.nightscout.androidaps.plugins.general.nsclient.services import android.annotation.SuppressLint import android.content.Context import android.content.Intent -import android.content.pm.ResolveInfo import android.os.* import androidx.work.OneTimeWorkRequest import com.google.common.base.Charsets @@ -17,7 +16,6 @@ import info.nightscout.androidaps.events.EventConfigBuilderChange import info.nightscout.androidaps.events.EventPreferenceChange import info.nightscout.androidaps.interfaces.Config import info.nightscout.androidaps.interfaces.DataSyncSelector -import info.nightscout.androidaps.interfaces.PluginType import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag import info.nightscout.androidaps.plugins.bus.RxBus @@ -41,12 +39,12 @@ import info.nightscout.androidaps.plugins.general.overview.notifications.Notific import info.nightscout.androidaps.plugins.profile.local.LocalProfilePlugin import info.nightscout.androidaps.plugins.source.NSClientSourcePlugin.NSClientSourceWorker import info.nightscout.androidaps.receivers.DataWorker -import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.utils.DateUtil import info.nightscout.androidaps.utils.FabricPrivacy import info.nightscout.androidaps.utils.JsonHelper.safeGetString import info.nightscout.androidaps.utils.JsonHelper.safeGetStringAllowNull import info.nightscout.androidaps.utils.T.Companion.mins +import info.nightscout.androidaps.utils.XDripBroadcast import info.nightscout.androidaps.utils.buildHelper.BuildHelper import info.nightscout.androidaps.utils.resources.ResourceHelper import info.nightscout.androidaps.utils.rx.AapsSchedulers @@ -80,6 +78,7 @@ class NSClientService : DaggerService() { @Inject lateinit var dataWorker: DataWorker @Inject lateinit var dataSyncSelector: DataSyncSelector @Inject lateinit var repository: AppRepository + @Inject lateinit var xDripBroadcast: XDripBroadcast companion object { @@ -476,15 +475,7 @@ class NSClientService : DaggerService() { OneTimeWorkRequest.Builder(LocalProfilePlugin.NSProfileWorker::class.java) .setInputData(dataWorker.storeInputData(profileStoreJson, null)) .build()) - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - val bundle = Bundle() - bundle.putString("profile", profileStoreJson.toString()) - bundle.putBoolean("delta", isDelta) - val intent = Intent(Intents.ACTION_NEW_PROFILE) - intent.putExtras(bundle) - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - broadcast(intent) - } + xDripBroadcast.sendProfile(profileStoreJson) } } if (data.has("treatments")) { @@ -502,18 +493,7 @@ class NSClientService : DaggerService() { OneTimeWorkRequest.Builder(NSClientAddUpdateWorker::class.java) .setInputData(dataWorker.storeInputData(addedOrUpdatedTreatments, null)) .build()) - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - val splitted = splitArray(addedOrUpdatedTreatments) - for (part in splitted) { - val bundle = Bundle() - bundle.putString("treatments", part.toString()) - bundle.putBoolean("delta", isDelta) - val intent = Intent(Intents.ACTION_CHANGED_TREATMENT) - intent.putExtras(bundle) - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - broadcast(intent) - } - } + xDripBroadcast.sendTreatments(addedOrUpdatedTreatments) } } if (data.has("devicestatus")) { @@ -550,18 +530,7 @@ class NSClientService : DaggerService() { dataWorker.enqueue(OneTimeWorkRequest.Builder(NSClientSourceWorker::class.java) .setInputData(dataWorker.storeInputData(sgvs, null)) .build()) - val splitted = splitArray(sgvs) - if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) { - for (part in splitted) { - val bundle = Bundle() - bundle.putString("sgvs", part.toString()) - bundle.putBoolean("delta", isDelta) - val intent = Intent(Intents.ACTION_NEW_SGV) - intent.putExtras(bundle) - intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) - broadcast(intent) - } - } + xDripBroadcast.sendSgvs(sgvs) } rxBus.send(EventNSClientNewLog("LAST", dateUtil.dateAndTimeString(latestDateInReceivedData))) } catch (e: JSONException) { @@ -675,40 +644,6 @@ class NSClientService : DaggerService() { } } - private fun splitArray(array: JSONArray): List { - var ret: MutableList = ArrayList() - try { - val size = array.length() - var count = 0 - var newarr: JSONArray? = null - for (i in 0 until size) { - if (count == 0) { - if (newarr != null) ret.add(newarr) - newarr = JSONArray() - count = 20 - } - newarr?.put(array[i]) - --count - } - if (newarr != null && newarr.length() > 0) ret.add(newarr) - } catch (e: JSONException) { - aapsLogger.error("Unhandled exception", e) - ret = ArrayList() - ret.add(array) - } - return ret - } - - private fun broadcast(intent: Intent) { - val receivers: List = packageManager.queryBroadcastReceivers(intent, 0) - for (resolveInfo in receivers) - resolveInfo.activityInfo.packageName?.let { - intent.setPackage(it) - sendBroadcast(intent) - aapsLogger.debug(LTag.CORE, "Sending broadcast " + intent.action + " to: " + it) - } - } - init { if (handler == null) { val handlerThread = HandlerThread(NSClientService::class.java.simpleName + "Handler") diff --git a/app/src/main/java/info/nightscout/androidaps/services/Intents.kt b/app/src/main/java/info/nightscout/androidaps/services/Intents.kt index c52c68e4c6..bf3a8d3695 100644 --- a/app/src/main/java/info/nightscout/androidaps/services/Intents.kt +++ b/app/src/main/java/info/nightscout/androidaps/services/Intents.kt @@ -7,12 +7,11 @@ interface Intents { // AAPS -> Xdrip const val ACTION_NEW_TREATMENT = "info.nightscout.client.NEW_TREATMENT" - const val ACTION_CHANGED_TREATMENT = "info.nightscout.client.CHANGED_TREATMENT" - const val ACTION_REMOVED_TREATMENT = "info.nightscout.client.REMOVED_TREATMENT" const val ACTION_NEW_PROFILE = "info.nightscout.client.NEW_PROFILE" const val ACTION_NEW_SGV = "info.nightscout.client.NEW_SGV" - const val ACTION_NEW_MBG = "info.nightscout.client.NEW_MBG" - const val ACTION_NEW_CAL = "info.nightscout.client.NEW_CAL" + + // AAPS -> xDrip 640G mode + const val XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR" // xDrip -> AAPS const val ACTION_NEW_BG_ESTIMATE = "com.eveningoutpost.dexdrip.BgEstimate" diff --git a/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt b/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt index d669ef8bc3..98cf2c90f9 100644 --- a/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt +++ b/app/src/main/java/info/nightscout/androidaps/utils/XDripBroadcast.kt @@ -7,6 +7,7 @@ import info.nightscout.androidaps.R import info.nightscout.androidaps.database.entities.GlucoseValue import info.nightscout.androidaps.logging.AAPSLogger import info.nightscout.androidaps.logging.LTag +import info.nightscout.androidaps.services.Intents import info.nightscout.androidaps.utils.sharedPreferences.SP import org.json.JSONArray import org.json.JSONException @@ -24,6 +25,7 @@ class XDripBroadcast @Inject constructor( private val sp: SP ) { + // sent in 640G mode fun send(glucoseValue: GlucoseValue) { if (sp.getBoolean(R.string.key_dexcomg5_xdripupload, false)) { val format = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US) @@ -41,7 +43,7 @@ class XDripBroadcast @Inject constructor( bundle.putString("action", "add") bundle.putString("collection", "entries") bundle.putString("data", entriesBody.toString()) - val intent = Intent(XDRIP_PLUS_NS_EMULATOR) + val intent = Intent(Intents.XDRIP_PLUS_NS_EMULATOR) intent.putExtras(bundle).addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) context.sendBroadcast(intent) val receivers = context.packageManager.queryBroadcastReceivers(intent, 0) @@ -57,7 +59,75 @@ class XDripBroadcast @Inject constructor( } } - companion object { - const val XDRIP_PLUS_NS_EMULATOR = "com.eveningoutpost.dexdrip.NS_EMULATOR" + // sent in NSClient dbaccess mode + fun sendProfile(profileStoreJson: JSONObject) { + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) + broadcast( + Intent(Intents.ACTION_NEW_PROFILE).apply { + addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + putExtras(Bundle().apply { putString("profile", profileStoreJson.toString()) }) + } + ) + + } + + // sent in NSClient dbaccess mode + fun sendTreatments(addedOrUpdatedTreatments: JSONArray) { + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) + splitArray(addedOrUpdatedTreatments).forEach { part -> + broadcast( + Intent(Intents.ACTION_NEW_TREATMENT).apply { + addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + putExtras(Bundle().apply { putString("treatments", part.toString()) }) + } + ) + } + } + + // sent in NSClient dbaccess mode + fun sendSgvs(sgvs: JSONArray) { + if (sp.getBoolean(R.string.key_nsclient_localbroadcasts, false)) + splitArray(sgvs).forEach { part -> + broadcast( + Intent(Intents.ACTION_NEW_SGV).apply { + addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + putExtras(Bundle().apply { putString("sgvs", part.toString()) }) + } + ) + } + } + + private fun splitArray(array: JSONArray): List { + var ret: MutableList = ArrayList() + try { + val size = array.length() + var count = 0 + var newarr: JSONArray? = null + for (i in 0 until size) { + if (count == 0) { + if (newarr != null) ret.add(newarr) + newarr = JSONArray() + count = 20 + } + newarr?.put(array[i]) + --count + } + if (newarr != null && newarr.length() > 0) ret.add(newarr) + } catch (e: JSONException) { + aapsLogger.error("Unhandled exception", e) + ret = ArrayList() + ret.add(array) + } + return ret + } + + private fun broadcast(intent: Intent) { + context.packageManager.queryBroadcastReceivers(intent, 0).forEach { resolveInfo -> + resolveInfo.activityInfo.packageName?.let { + intent.setPackage(it) + context.sendBroadcast(intent) + aapsLogger.debug(LTag.CORE, "Sending broadcast " + intent.action + " to: " + it) + } + } } } \ No newline at end of file From 51c6237d022c0a7a937cc51a1329e065e50a8e66 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 17:26:19 +0100 Subject: [PATCH 14/34] limit logging --- .../storage/StorageConstraintPlugin.kt | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.kt index 3e1bb68d85..cb78c7882e 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/constraints/storage/StorageConstraintPlugin.kt @@ -28,20 +28,22 @@ class StorageConstraintPlugin @Inject constructor( aapsLogger: AAPSLogger, rh: ResourceHelper, private val rxBus: RxBus -) : PluginBase(PluginDescription() - .mainType(PluginType.CONSTRAINTS) - .neverVisible(true) - .alwaysEnabled(true) - .showInList(false) - .pluginName(R.string.storage), +) : PluginBase( + PluginDescription() + .mainType(PluginType.CONSTRAINTS) + .neverVisible(true) + .alwaysEnabled(true) + .showInList(false) + .pluginName(R.string.storage), aapsLogger, rh, injector ), Constraints { + @Suppress("ReplaceGetOrSet") override fun isClosedLoopAllowed(value: Constraint): Constraint { val diskFree = availableInternalMemorySize() - aapsLogger.debug(LTag.CONSTRAINTS, "Internal storage free (Mb):$diskFree") if (diskFree < Constants.MINIMUM_FREE_SPACE) { - value[aapsLogger, false, rh.gs(R.string.diskfull, Constants.MINIMUM_FREE_SPACE)] = this + aapsLogger.debug(LTag.CONSTRAINTS, "Internal storage free (Mb):$diskFree") + value.set(aapsLogger, false, rh.gs(R.string.diskfull, Constants.MINIMUM_FREE_SPACE), this) val notification = Notification(Notification.DISK_FULL, rh.gs(R.string.diskfull, Constants.MINIMUM_FREE_SPACE), Notification.NORMAL) rxBus.send(EventNewNotification(notification)) } else { From 5e466279a4f540a7335b91dacf401943937e9c02 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 17:32:09 +0100 Subject: [PATCH 15/34] improve logging --- .../plugins/general/automation/elements/InputDuration.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.kt b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.kt index a20e509b19..6e275190e9 100644 --- a/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.kt +++ b/automation/src/main/java/info/nightscout/androidaps/plugins/general/automation/elements/InputDuration.kt @@ -46,4 +46,6 @@ class InputDuration( this.value = value / 60 return this } + + override fun toString(): String = "InputDuration: $value $unit" } \ No newline at end of file From 6ab2a7bb7ee19f9ec55f676e938c1867bb30a72d Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 11 Nov 2021 17:41:19 +0100 Subject: [PATCH 16/34] display the performed operation --- .../info/nightscout/androidaps/queue/QueueThread.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt index df3ce83881..c285b9d338 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt @@ -111,14 +111,18 @@ class QueueThread internal constructor( // Pickup 1st command and set performing variable if (queue.size() > 0) { queue.pickup() - if (queue.performing() != null) { - aapsLogger.debug(LTag.PUMPQUEUE, "performing " + queue.performing()?.status()) + val cont = queue.performing()?.let { + aapsLogger.debug(LTag.PUMPQUEUE, "performing " + it.status()) rxBus.send(EventQueueChanged()) - queue.performing()?.execute() + rxBus.send(EventPumpStatusChanged(it.status())) + it.execute() queue.resetPerforming() rxBus.send(EventQueueChanged()) lastCommandTime = System.currentTimeMillis() SystemClock.sleep(100) + true + } ?: false + if (cont) { continue } } From 7826c4183432996ee67fca075015490c7e6ecdb7 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 11 Nov 2021 17:41:37 +0100 Subject: [PATCH 17/34] delay observing for EventPumpStatusChanged --- .../plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 3f87aad83d..0a77ac2d14 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -50,6 +50,7 @@ import org.apache.commons.lang3.StringUtils import java.time.Duration import java.time.ZonedDateTime import java.util.* +import java.util.concurrent.TimeUnit import javax.inject.Inject import kotlin.collections.ArrayList @@ -213,6 +214,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() { disposables += rxBus .toObservable(EventPumpStatusChanged::class.java) .observeOn(aapsSchedulers.main) + .delay(30, TimeUnit.MILLISECONDS, aapsSchedulers.main) .subscribe( { updateBluetoothConnectionStatus(it) From 59c7955126659aa98ae67881fbb34422a6a02a7f Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 11 Nov 2021 19:04:28 +0100 Subject: [PATCH 18/34] connection quality: count connections after retries --- .../pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 4 +++- .../driver/pod/state/OmnipodDashPodStateManager.kt | 4 ++-- .../pod/state/OmnipodDashPodStateManagerImpl.kt | 14 +++++++------- .../omnipod/dash/ui/OmnipodDashOverviewFragment.kt | 7 ++++--- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 3e8d4920bb..405e7da295 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -243,7 +243,6 @@ class OmnipodDashPumpPlugin @Inject constructor( val stop = CountDownLatch(1) stopConnecting = stop } - podStateManager.incrementConnectionAttemptsWithRetries() thread( start = true, name = "ConnectionThread", @@ -252,6 +251,9 @@ class OmnipodDashPumpPlugin @Inject constructor( stopConnecting?.let { val error = omnipodManager.connect(it).ignoreElements().blockingGet() aapsLogger.info(LTag.PUMPCOMM, "connect error=$error") + if (error == null) { + podStateManager.incrementSuccessfulConnectionAttemptsAfterRetries() + } } } finally { synchronized(this) { diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index 652819fa11..6927e63195 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -33,7 +33,7 @@ interface OmnipodDashPodStateManager { var bluetoothConnectionState: BluetoothConnectionState var connectionAttempts: Int var successfulConnections: Int - val connectionAttemptsWithRetries: Int + val successfulConnectionAttemptsAfterRetries: Int val failedConnectionsAfterRetries: Int var timeZone: TimeZone @@ -87,7 +87,7 @@ interface OmnipodDashPodStateManager { fun updateFromPairing(uniqueId: Id, pairResult: PairResult) fun reset() fun connectionSuccessRatio(): Float - fun incrementConnectionAttemptsWithRetries() + fun incrementSuccessfulConnectionAttemptsAfterRetries() fun incrementFailedConnectionsAfterRetries() fun createActiveCommand( diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index 9ab82212c1..fe63757d17 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -114,13 +114,13 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.successfulConnections = value } - override val connectionAttemptsWithRetries: Int + override val successfulConnectionAttemptsAfterRetries: Int @Synchronized - get() = podState.connectionAttemptsWithRetries + get() = podState.successfulConnectionAttemptsAfterRetries @Synchronized - override fun incrementConnectionAttemptsWithRetries() { - podState.connectionAttemptsWithRetries++ + override fun incrementSuccessfulConnectionAttemptsAfterRetries() { + podState.successfulConnectionAttemptsAfterRetries++ } override val failedConnectionsAfterRetries: Int @@ -646,10 +646,10 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( } override fun connectionSuccessRatio(): Float { - if (connectionAttemptsWithRetries == 0) { + if (failedConnectionsAfterRetries + successfulConnectionAttemptsAfterRetries == 0) { return 0.0F } - return 1 - (failedConnectionsAfterRetries.toFloat() / connectionAttemptsWithRetries) + return successfulConnectionAttemptsAfterRetries.toFloat() / (successfulConnectionAttemptsAfterRetries + failedConnectionsAfterRetries) } override fun reset() { @@ -691,7 +691,7 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( OmnipodDashPodStateManager.BluetoothConnectionState.DISCONNECTED var connectionAttempts = 0 var successfulConnections = 0 - var connectionAttemptsWithRetries = 0 + var successfulConnectionAttemptsAfterRetries = 0 var failedConnectionsAfterRetries = 0 var messageSequenceNumber: Short = 0 var sequenceNumberOfLastProgrammingCommand: Short? = null diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 0a77ac2d14..698381365e 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -256,14 +256,15 @@ class OmnipodDashOverviewFragment : DaggerFragment() { ?: PLACEHOLDER val connectionSuccessPercentage = podStateManager.connectionSuccessRatio() * 100 + val connectionAttempts = podStateManager.failedConnectionsAfterRetries + podStateManager.successfulConnectionAttemptsAfterRetries val successPercentageString = String.format("%.2f %%", connectionSuccessPercentage) val quality = - "${podStateManager.connectionAttemptsWithRetries - podStateManager.failedConnectionsAfterRetries}/${podStateManager.connectionAttemptsWithRetries} :: $successPercentageString" + "${podStateManager.successfulConnectionAttemptsAfterRetries}/$connectionAttempts :: $successPercentageString" bluetoothStatusBinding.omnipodDashBluetoothConnectionQuality.text = quality val connectionStatsColor = when { - connectionSuccessPercentage < 70 && podStateManager.connectionAttemptsWithRetries > 50 -> + connectionSuccessPercentage < 70 && podStateManager.successfulConnectionAttemptsAfterRetries > 50 -> Color.RED - connectionSuccessPercentage < 90 && podStateManager.connectionAttemptsWithRetries > 50 -> + connectionSuccessPercentage < 90 && podStateManager.successfulConnectionAttemptsAfterRetries > 50 -> Color.YELLOW else -> Color.WHITE From 229285ed4d94df14e4edef52074add994093230c Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 11 Nov 2021 17:41:19 +0100 Subject: [PATCH 19/34] display the performed operation --- .../info/nightscout/androidaps/queue/QueueThread.kt | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt index df3ce83881..c285b9d338 100644 --- a/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt +++ b/app/src/main/java/info/nightscout/androidaps/queue/QueueThread.kt @@ -111,14 +111,18 @@ class QueueThread internal constructor( // Pickup 1st command and set performing variable if (queue.size() > 0) { queue.pickup() - if (queue.performing() != null) { - aapsLogger.debug(LTag.PUMPQUEUE, "performing " + queue.performing()?.status()) + val cont = queue.performing()?.let { + aapsLogger.debug(LTag.PUMPQUEUE, "performing " + it.status()) rxBus.send(EventQueueChanged()) - queue.performing()?.execute() + rxBus.send(EventPumpStatusChanged(it.status())) + it.execute() queue.resetPerforming() rxBus.send(EventQueueChanged()) lastCommandTime = System.currentTimeMillis() SystemClock.sleep(100) + true + } ?: false + if (cont) { continue } } From 774beb2cb3cc6fb69c4a45eadbe176e5622aed53 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 20:39:17 +0100 Subject: [PATCH 20/34] Glunovo process calibrations --- .../plugins/source/GlunovoPlugin.kt | 30 +++++++++++++------ 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index f8af965921..d2b6900836 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -9,6 +9,7 @@ import info.nightscout.androidaps.Constants import info.nightscout.androidaps.R import info.nightscout.androidaps.database.AppRepository import info.nightscout.androidaps.database.entities.GlucoseValue +import info.nightscout.androidaps.database.entities.TherapyEvent import info.nightscout.androidaps.database.transactions.CgmSourceTransaction import info.nightscout.androidaps.interfaces.BgSource import info.nightscout.androidaps.interfaces.PluginBase @@ -86,11 +87,13 @@ class GlunovoPlugin @Inject constructor( context.contentResolver.query(contentUri, null, null, null, null)?.let { cr -> val glucoseValues = mutableListOf() + val calibrations = mutableListOf() cr.moveToFirst() while (!cr.isAfterLast) { val timestamp = cr.getLong(0) val value = cr.getDouble(1) //value in mmol/l... + val curr = cr.getDouble(2) if (timestamp > dateUtil.now() || timestamp == 0L) { aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $timestamp") cr.moveToNext() @@ -109,21 +112,30 @@ class GlunovoPlugin @Inject constructor( continue } - glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( - timestamp = timestamp, - value = value * Constants.MMOLL_TO_MGDL, - raw = 0.0, - noise = null, - trendArrow = GlucoseValue.TrendArrow.NONE, - sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE - ) + if (curr != 0.0) + glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( + timestamp = timestamp, + value = value * Constants.MMOLL_TO_MGDL, + raw = 0.0, + noise = null, + trendArrow = GlucoseValue.TrendArrow.NONE, + sourceSensor = GlucoseValue.SourceSensor.GLUNOVO_NATIVE + ) + else + calibrations.add( + CgmSourceTransaction.Calibration( + timestamp = timestamp, + value = value, + glucoseUnit = TherapyEvent.GlucoseUnit.MMOL + ) + ) sp.putLong(R.string.key_last_processed_glunovo_timestamp, timestamp) cr.moveToNext() } cr.close() if (glucoseValues.isNotEmpty()) - repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, emptyList(), null)) + repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, null)) .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) } From 579c9dac7c4de41b36a4fed67494e0038d2196c7 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 20:41:32 +0100 Subject: [PATCH 21/34] Glunovo rearrange --- .../androidaps/plugins/source/GlunovoPlugin.kt | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index d2b6900836..b541389895 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -94,6 +94,13 @@ class GlunovoPlugin @Inject constructor( val timestamp = cr.getLong(0) val value = cr.getDouble(1) //value in mmol/l... val curr = cr.getDouble(2) + + // bypass already processed + if (timestamp < sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L)) { + cr.moveToNext() + continue + } + if (timestamp > dateUtil.now() || timestamp == 0L) { aapsLogger.error(LTag.BGSOURCE, "Error in received data date/time $timestamp") cr.moveToNext() @@ -106,12 +113,6 @@ class GlunovoPlugin @Inject constructor( continue } - // bypass already processed - if (timestamp < sp.getLong(R.string.key_last_processed_glunovo_timestamp, 0L)) { - cr.moveToNext() - continue - } - if (curr != 0.0) glucoseValues += CgmSourceTransaction.TransactionGlucoseValue( timestamp = timestamp, @@ -134,7 +135,7 @@ class GlunovoPlugin @Inject constructor( } cr.close() - if (glucoseValues.isNotEmpty()) + if (glucoseValues.isNotEmpty() || calibrations.isNotEmpty()) repository.runTransactionForResult(CgmSourceTransaction(glucoseValues, calibrations, null)) .doOnError { aapsLogger.error(LTag.DATABASE, "Error while saving values from Glunovo App", it) From 041f1a962e931f22f54f5b418ed239810163d3a8 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Thu, 11 Nov 2021 20:49:52 +0100 Subject: [PATCH 22/34] do not stop the fake tbr on pod activation --- .../viewmodel/action/DashInsertCannulaViewModel.kt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 743e96adbf..3bea03140f 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -21,7 +21,6 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BasalValuesRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult -import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Constants import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.I8n import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram import info.nightscout.androidaps.utils.FabricPrivacy @@ -95,15 +94,6 @@ class DashInsertCannulaViewModel @Inject constructor( onComplete = { logger.debug("Pod activation part 2 completed") podStateManager.basalProgram = basalProgram - - pumpSync.syncStopTemporaryBasalWithPumpId( - timestamp = System.currentTimeMillis(), - endPumpId = System.currentTimeMillis(), - pumpType = PumpType.OMNIPOD_DASH, - pumpSerial = Constants.PUMP_SERIAL_FOR_FAKE_TBR // cancel the fake TBR with the same pump - // serial that it was created with - ) - pumpSync.connectNewPump() pumpSync.insertTherapyEventIfNewWithTimestamp( From 52e343213249c0abff26aab4756b5c9edf8755c3 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 20:50:53 +0100 Subject: [PATCH 23/34] Eros: try to fix blocking UI --- .../activation/viewmodel/action/ErosInitializePodViewModel.kt | 2 +- .../activation/viewmodel/action/ErosInsertCannulaViewModel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInitializePodViewModel.kt b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInitializePodViewModel.kt index a6f3c69799..b2a76ed05e 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInitializePodViewModel.kt +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInitializePodViewModel.kt @@ -27,7 +27,7 @@ class ErosInitializePodViewModel @Inject constructor( override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED) - override fun doExecuteAction(): Single = Single.just(aapsOmnipodManager.initializePod()) + override fun doExecuteAction(): Single = Single.fromCallable { aapsOmnipodManager.initializePod() } @StringRes override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_initialize_pod_title diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInsertCannulaViewModel.kt b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInsertCannulaViewModel.kt index b3c071b294..9c556a7fe8 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInsertCannulaViewModel.kt +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/ui/wizard/activation/viewmodel/action/ErosInsertCannulaViewModel.kt @@ -29,7 +29,7 @@ class ErosInsertCannulaViewModel @Inject constructor( override fun isPodDeactivatable(): Boolean = podStateManager.activationProgress.isAtLeast(ActivationProgress.PAIRING_COMPLETED) - override fun doExecuteAction(): Single = Single.just(aapsOmnipodManager.insertCannula(profileFunction.getProfile())) + override fun doExecuteAction(): Single = Single.fromCallable { aapsOmnipodManager.insertCannula(profileFunction.getProfile()) } @StringRes override fun getTitleId(): Int = R.string.omnipod_common_pod_activation_wizard_insert_cannula_title From 8bac46830641a36934813d16b98d5413723baff3 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Thu, 11 Nov 2021 22:40:52 +0100 Subject: [PATCH 24/34] IOB: fix calculation for EB --- .../wearintegration/WatchUpdaterService.java | 1 - .../iobCobCalculator/IobCobCalculatorPlugin.kt | 18 +++++++++++++++--- .../extensions/ExtendedBolusExtension.kt | 4 ++-- .../extensions/TemporaryBasalExtension.kt | 8 ++++---- 4 files changed, 21 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java index 2583996995..72e63f1faf 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java +++ b/app/src/main/java/info/nightscout/androidaps/plugins/general/wear/wearintegration/WatchUpdaterService.java @@ -42,7 +42,6 @@ import info.nightscout.androidaps.interfaces.ActivePlugin; import info.nightscout.androidaps.interfaces.Config; import info.nightscout.androidaps.interfaces.GlucoseUnit; import info.nightscout.androidaps.interfaces.IobCobCalculator; -import info.nightscout.androidaps.interfaces.PluginType; import info.nightscout.androidaps.interfaces.Profile; import info.nightscout.androidaps.interfaces.ProfileFunction; import info.nightscout.androidaps.logging.AAPSLogger; diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt index fec67d9e5f..5efd0af7e8 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/iob/iobCobCalculator/IobCobCalculatorPlugin.kt @@ -537,7 +537,11 @@ class IobCobCalculatorPlugin @Inject constructor( for (pos in extendedBoluses.indices) { val e = extendedBoluses[pos] if (e.timestamp > toTime) continue - if (e.end > now) e.duration = now - e.timestamp + if (e.end > now) { + val newDuration = now - e.timestamp + e.amount *= newDuration.toDouble() / e.duration + e.duration = newDuration + } val profile = profileFunction.getProfile(e.timestamp) ?: return total val calc = e.iobCalc(toTime, profile, activePlugin.activeInsulin) total.plus(calc) @@ -632,7 +636,11 @@ class IobCobCalculatorPlugin @Inject constructor( val e = extendedBoluses[pos] if (e.timestamp > toTime) continue val profile = profileFunction.getProfile(e.timestamp) ?: continue - if (e.end > now) e.duration = now - e.timestamp + if (e.end > now) { + val newDuration = now - e.timestamp + e.amount *= newDuration.toDouble() / e.duration + e.duration = newDuration + } val calc = e.iobCalc(toTime, profile, activePlugin.activeInsulin) totalExt.plus(calc) } @@ -667,7 +675,11 @@ class IobCobCalculatorPlugin @Inject constructor( val e = extendedBoluses[pos] if (e.timestamp > toTime) continue val profile = profileFunction.getProfile(e.timestamp) ?: continue - if (e.end > now) e.duration = now - e.timestamp + if (e.end > now) { + val newDuration = now - e.timestamp + e.amount *= newDuration.toDouble() / e.duration + e.duration = newDuration + } val calc = e.iobCalc(toTime, profile, lastAutosensResult, exercise_mode, half_basal_exercise_target, isTempTarget, activePlugin.activeInsulin) totalExt.plus(calc) } diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt index 339dd0b797..a09163585c 100644 --- a/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/ExtendedBolusExtension.kt @@ -110,7 +110,7 @@ fun extendedBolusFromJson(jsonObject: JSONObject): ExtendedBolus? { val pumpSerial = JsonHelper.safeGetStringAllowNull(jsonObject, "pumpSerial", null) if (timestamp == 0L) return null - if (duration == 0L) return null + if (duration == 0L && durationInMilliseconds == 0L) return null if (amount == 0.0) return null return ExtendedBolus( @@ -135,7 +135,7 @@ fun ExtendedBolus.iobCalc(time: Long, profile: Profile, insulinInterface: Insuli val dia = profile.dia val diaAgo = time - dia * 60 * 60 * 1000 val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() - val spacing = realDuration / aboutFiveMinIntervals + val spacing = realDuration / aboutFiveMinIntervals.toDouble() for (j in 0L until aboutFiveMinIntervals) { // find middle of the interval val calcDate = (timestamp + j * spacing * 60 * 1000 + 0.5 * spacing * 60 * 1000).toLong() diff --git a/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt b/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt index b80ca45c65..1e2ba381a7 100644 --- a/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt +++ b/core/src/main/java/info/nightscout/androidaps/extensions/TemporaryBasalExtension.kt @@ -134,14 +134,14 @@ fun TemporaryBasal.toStringShort(): String = fun TemporaryBasal.iobCalc(time: Long, profile: Profile, insulinInterface: Insulin): IobTotal { val result = IobTotal(time) - val realDuration: Int = getPassedDurationToTimeInMinutes(time) + val realDuration = getPassedDurationToTimeInMinutes(time) var netBasalAmount = 0.0 if (realDuration > 0) { var netBasalRate: Double val dia = profile.dia val diaAgo = time - dia * 60 * 60 * 1000 val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() - val tempBolusSpacing = (realDuration / aboutFiveMinIntervals).toDouble() + val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble() for (j in 0L until aboutFiveMinIntervals) { // find middle of the interval val calcDate = (timestamp + j * tempBolusSpacing * 60 * 1000 + 0.5 * tempBolusSpacing * 60 * 1000).toLong() @@ -175,7 +175,7 @@ fun TemporaryBasal.iobCalc(time: Long, profile: Profile, insulinInterface: Insul fun TemporaryBasal.iobCalc(time: Long, profile: Profile, lastAutosensResult: AutosensResult, exercise_mode: Boolean, half_basal_exercise_target: Int, isTempTarget: Boolean, insulinInterface: Insulin): IobTotal { val result = IobTotal(time) - val realDuration: Double = getPassedDurationToTimeInMinutes(time).toDouble() + val realDuration = getPassedDurationToTimeInMinutes(time) var netBasalAmount = 0.0 var sensitivityRatio = lastAutosensResult.ratio val normalTarget = 100.0 @@ -190,7 +190,7 @@ fun TemporaryBasal.iobCalc(time: Long, profile: Profile, lastAutosensResult: Aut val dia = profile.dia val diaAgo = time - dia * 60 * 60 * 1000 val aboutFiveMinIntervals = ceil(realDuration / 5.0).toInt() - val tempBolusSpacing = realDuration / aboutFiveMinIntervals + val tempBolusSpacing = realDuration / aboutFiveMinIntervals.toDouble() for (j in 0L until aboutFiveMinIntervals) { // find middle of the interval val calcDate = (timestamp + j * tempBolusSpacing * 60 * 1000 + 0.5 * tempBolusSpacing * 60 * 1000).toLong() From 2dbcb6de5d0c66aa6ac78fbfdf80bc1269425ccd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 12 Nov 2021 08:06:32 +0000 Subject: [PATCH 25/34] Bump dagger_version from 2.40 to 2.40.1 Bumps `dagger_version` from 2.40 to 2.40.1. Updates `dagger-compiler` from 2.40 to 2.40.1 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.40...dagger-2.40.1) Updates `dagger-android-processor` from 2.40 to 2.40.1 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.40...dagger-2.40.1) Updates `dagger-android` from 2.40 to 2.40.1 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.40...dagger-2.40.1) Updates `dagger-android-support` from 2.40 to 2.40.1 - [Release notes](https://github.com/google/dagger/releases) - [Changelog](https://github.com/google/dagger/blob/master/CHANGELOG.md) - [Commits](https://github.com/google/dagger/compare/dagger-2.40...dagger-2.40.1) --- updated-dependencies: - dependency-name: com.google.dagger:dagger-compiler dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.google.dagger:dagger-android-processor dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.google.dagger:dagger-android dependency-type: direct:production update-type: version-update:semver-patch - dependency-name: com.google.dagger:dagger-android-support dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 4a59385c49..9a9fc16d67 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript { rxkotlin_version = '2.4.0' room_version = '2.3.0' lifecycle_version = '2.3.1' - dagger_version = '2.40' + dagger_version = '2.40.1' coroutinesVersion = '1.4.1' activityVersion = '1.3.1' fragmentktx_version = '1.3.6' From 00fb5bd6cef1d160602997307b7fde470a901001 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 12 Nov 2021 10:29:17 +0100 Subject: [PATCH 26/34] assert nscliet is running in RunningConfiguration --- .../androidaps/plugins/configBuilder/RunningConfiguration.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt b/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt index b255a7e327..5ce9eb1fda 100644 --- a/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt +++ b/core/src/main/java/info/nightscout/androidaps/plugins/configBuilder/RunningConfiguration.kt @@ -61,6 +61,8 @@ class RunningConfiguration @Inject constructor( // called in NSClient mode only fun apply(configuration: JSONObject) { + assert(config.NSCLIENT) + if (configuration.has("version")) { rxBus.send(EventNSClientNewLog("VERSION", "Received AndroidAPS version ${configuration.getString("version")}")) if (config.VERSION_NAME.startsWith(configuration.getString("version")).not()) { From 01e70d978f9ed1f76e7ed8004f6f980e0badc7c1 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 12 Nov 2021 10:29:57 +0100 Subject: [PATCH 27/34] key not translatable --- app/src/main/res/values/strings.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1beca8f6d9..b622714e15 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1134,6 +1134,6 @@ BG data status Recalculated data used BG too close:\n%1$s\n%2$s - last_processed_glunovo_timestamp + last_processed_glunovo_timestamp From 54b8d0613cf78b6f1da63ad02e53c4181d462d16 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Fri, 12 Nov 2021 16:53:03 +0100 Subject: [PATCH 28/34] fix build --- .../nightscout/androidaps/plugins/source/GlunovoPlugin.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt index b541389895..906c9094ec 100644 --- a/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt +++ b/app/src/main/java/info/nightscout/androidaps/plugins/source/GlunovoPlugin.kt @@ -35,7 +35,7 @@ class GlunovoPlugin @Inject constructor( private val sp: SP, private val context: Context, private val repository: AppRepository, - private val broadcastToXDrip: XDripBroadcast, + private val xDripBroadcast: XDripBroadcast, private val dateUtil: DateUtil, private val fabricPrivacy: FabricPrivacy ) : PluginBase( @@ -143,7 +143,7 @@ class GlunovoPlugin @Inject constructor( .blockingGet() .also { savedValues -> savedValues.inserted.forEach { - broadcastToXDrip(it) + xDripBroadcast.send(it) aapsLogger.debug(LTag.DATABASE, "Inserted bg $it") } } From 90b8b8ed00df3887264bd38ee1acac1edfe9270d Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 12 Nov 2021 18:15:03 +0100 Subject: [PATCH 29/34] create new string for "Delivering .." --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 2 +- omnipod-dash/src/main/res/values/strings.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index ce3a4a3e7b..02158e0aa5 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -694,7 +694,7 @@ class OmnipodDashPumpPlugin @Inject constructor( } val percent = (waited.toFloat() / estimatedDeliveryTimeSeconds) * 100 updateBolusProgressDialog( - rh.gs(R.string.bolusdelivering, requestedBolusAmount), + rh.gs(R.string.dash_bolusdelivering, requestedBolusAmount), percent.toInt() ) } diff --git a/omnipod-dash/src/main/res/values/strings.xml b/omnipod-dash/src/main/res/values/strings.xml index 1b6f4dbb45..607f6ebdc5 100644 --- a/omnipod-dash/src/main/res/values/strings.xml +++ b/omnipod-dash/src/main/res/values/strings.xml @@ -46,4 +46,5 @@ Unknown state for the command Rate: %1$.2f U, duration: %2$d minutes %1$.2f U + Delivering %1$.2f U From b0b287303afb68b178603527fa0da25f7c1db6a3 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Fri, 12 Nov 2021 18:15:52 +0100 Subject: [PATCH 30/34] Revert "do not stop the fake tbr on pod activation" This reverts commit 041f1a962e931f22f54f5b418ed239810163d3a8. --- .../viewmodel/action/DashInsertCannulaViewModel.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt index 3bea03140f..743e96adbf 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/wizard/activation/viewmodel/action/DashInsertCannulaViewModel.kt @@ -21,6 +21,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.DashHistory import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.BasalValuesRecord import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.InitialResult import info.nightscout.androidaps.plugins.pump.omnipod.dash.history.data.ResolvedResult +import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Constants import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.I8n import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.mapProfileToBasalProgram import info.nightscout.androidaps.utils.FabricPrivacy @@ -94,6 +95,15 @@ class DashInsertCannulaViewModel @Inject constructor( onComplete = { logger.debug("Pod activation part 2 completed") podStateManager.basalProgram = basalProgram + + pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = System.currentTimeMillis(), + endPumpId = System.currentTimeMillis(), + pumpType = PumpType.OMNIPOD_DASH, + pumpSerial = Constants.PUMP_SERIAL_FOR_FAKE_TBR // cancel the fake TBR with the same pump + // serial that it was created with + ) + pumpSync.connectNewPump() pumpSync.insertTherapyEventIfNewWithTimestamp( From 88b4830a0cccb074a05e0724d5d4364e4eea33ef Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sat, 13 Nov 2021 12:41:53 +0100 Subject: [PATCH 31/34] show notification only once and if there is no CommandDeactivatePod in progress --- .../omnipod/dash/OmnipodDashPumpPlugin.kt | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 405e7da295..8a4a7cf5d9 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -342,15 +342,16 @@ class OmnipodDashPumpPlugin @Inject constructor( aapsLogger.info(LTag.PUMP, "syncBolusWithPumpId on CANCEL_BOLUS returned: $sync") } } - - podStateManager.alarmType?.let { - showNotification( - Notification.OMNIPOD_POD_FAULT, - it.toString(), - Notification.URGENT, - R.raw.boluserror - ) - if (!podStateManager.alarmSynced) { + if (!podStateManager.alarmSynced) { + podStateManager.alarmType?.let { + if (!commandQueue.isCustomCommandInQueue(CommandDeactivatePod::class.java)) { + showNotification( + Notification.OMNIPOD_POD_FAULT, + it.toString(), + Notification.URGENT, + R.raw.boluserror + ) + } pumpSync.insertAnnouncement( error = it.toString(), pumpId = Random.Default.nextLong(), From f68134801a514f1cd062ed7e135bcd8d08cbb6b1 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 14 Nov 2021 00:43:30 +0100 Subject: [PATCH 32/34] fix DST --- .../omnipod/dash/driver/OmnipodDashManager.kt | 2 - .../dash/driver/OmnipodDashManagerImpl.kt | 8 +--- .../pod/state/OmnipodDashPodStateManager.kt | 4 +- .../state/OmnipodDashPodStateManagerImpl.kt | 46 ++++++++++++------- .../dash/ui/OmnipodDashOverviewFragment.kt | 12 ++++- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt index 718df1597b..4f3f682892 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManager.kt @@ -23,8 +23,6 @@ interface OmnipodDashManager { fun suspendDelivery(hasBasalBeepEnabled: Boolean): Observable - fun setTime(): Observable - fun setTempBasal(rate: Double, durationInMinutes: Short, tempBasalBeeps: Boolean): Observable fun stopTempBasal(hasTempBasalBeepEnabled: Boolean): Observable diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt index 2a88cc2d0d..0d62eb9a68 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/OmnipodDashManagerImpl.kt @@ -196,7 +196,7 @@ class OmnipodDashManagerImpl @Inject constructor( DefaultStatusResponse::class ) }.doOnComplete { - podStateManager.timeZone = TimeZone.getDefault() + podStateManager.updateTimeZone() } } @@ -506,12 +506,6 @@ class OmnipodDashManagerImpl @Inject constructor( ).interceptPodEvents() } - override fun setTime(): Observable { - // TODO - logger.error(LTag.PUMPCOMM, "NOT IMPLEMENTED: setTime()") - return Observable.empty() - } - private fun observeSendProgramTempBasalCommand(rate: Double, durationInMinutes: Short, tempBasalBeeps: Boolean): Observable { return Observable.defer { bleManager.sendCommand( diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt index 6927e63195..fa38444317 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManager.kt @@ -36,7 +36,8 @@ interface OmnipodDashPodStateManager { val successfulConnectionAttemptsAfterRetries: Int val failedConnectionsAfterRetries: Int - var timeZone: TimeZone + val timeZoneId: String? + val timeZoneUpdated: Long? val sameTimeZone: Boolean // The TimeZone is the same on the phone and on the pod val lastUpdatedSystem: Long // System.currentTimeMillis() val lastStatusResponseReceived: Long @@ -89,6 +90,7 @@ interface OmnipodDashPodStateManager { fun connectionSuccessRatio(): Float fun incrementSuccessfulConnectionAttemptsAfterRetries() fun incrementFailedConnectionsAfterRetries() + fun updateTimeZone() fun createActiveCommand( historyId: String, diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt index fe63757d17..2c79549a0d 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/driver/pod/state/OmnipodDashPodStateManagerImpl.kt @@ -23,6 +23,8 @@ import io.reactivex.Single import java.io.Serializable import java.time.Duration import java.time.Instant +import java.time.ZoneId +import java.time.ZoneOffset import java.time.ZonedDateTime import java.util.* import javax.inject.Inject @@ -131,27 +133,18 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( podState.failedConnectionsAfterRetries++ } - override var timeZone: TimeZone - get() = TimeZone.getTimeZone(podState.timeZone) - set(tz) { - podState.timeZone = tz.toZoneId().normalized().id - store() - } + override val timeZoneId: String? + get() = podState.timeZone override val sameTimeZone: Boolean get() { val now = System.currentTimeMillis() val currentTimezone = TimeZone.getDefault() val currentOffset = currentTimezone.getOffset(now) - val podOffset = timeZone.getOffset(now) + val podOffset = podState.timeZoneOffset logger.debug( LTag.PUMPCOMM, - "sameTimeZone currentTimezone=${ - currentTimezone.getDisplayName( - true, - TimeZone.SHORT - ) - } " + + "sameTimeZone " + "currentOffset=$currentOffset " + "podOffset=$podOffset" ) @@ -238,8 +231,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( get() { val minutesSinceActivation = podState.minutesSinceActivation val activationTime = podState.activationTime - if ((activationTime != null) && (minutesSinceActivation != null)) { - return ZonedDateTime.ofInstant(Instant.ofEpochMilli(activationTime), timeZone.toZoneId()) + val timeZoneOffset = podState.timeZoneOffset + if ((activationTime != null) && (minutesSinceActivation != null) && (timeZoneOffset != null)) { + return ZonedDateTime.ofInstant(Instant.ofEpochMilli(activationTime), ZoneId.ofOffset("", ZoneOffset.ofTotalSeconds(timeZoneOffset / 1000))) .plusMinutes(minutesSinceActivation.toLong()) .plus(Duration.ofMillis(System.currentTimeMillis() - lastUpdatedSystem)) } @@ -248,9 +242,25 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( override val timeDrift: Duration? get() { - return Duration.between(ZonedDateTime.now(), time) + return time?.let { + return Duration.between(ZonedDateTime.now(), it) + } ?: null } + override val timeZoneUpdated: Long? + get() { + return podState.timeZoneUpdated + } + + override fun updateTimeZone() { + val timeZone = TimeZone.getDefault() + val now = System.currentTimeMillis() + + podState.timeZoneOffset = timeZone.getOffset(now) + podState.timeZone = timeZone.id + podState.timeZoneUpdated = now + } + override val expiry: ZonedDateTime? get() { val podLifeInHours = podLifeInHours @@ -700,7 +710,9 @@ class OmnipodDashPodStateManagerImpl @Inject constructor( var bluetoothAddress: String? = null var ltk: ByteArray? = null var eapAkaSequenceNumber: Long = 1 - var timeZone: String = "" // TimeZone ID (e.g. "Europe/Amsterdam") + var timeZone: String? = null // TimeZone ID (e.g. "Europe/Amsterdam") + var timeZoneOffset: Int? = null + var timeZoneUpdated: Long? = null var alarmSynced: Boolean = false var bleVersion: SoftwareVersion? = null diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt index 698381365e..5c2902ab91 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/ui/OmnipodDashOverviewFragment.kt @@ -306,12 +306,20 @@ class OmnipodDashOverviewFragment : DaggerFragment() { podStateManager.bluetoothVersion.toString() ) - // Update time on Pod + val timeZone = podStateManager.timeZoneId?.let { timeZoneId -> + podStateManager.timeZoneUpdated?.let { timeZoneUpdated -> + val tz = TimeZone.getTimeZone(timeZoneId) + val inDST = tz.inDaylightTime(Date(timeZoneUpdated)) + val locale = resources.configuration.locales.get(0) + tz.getDisplayName(inDST, TimeZone.SHORT, locale) + } ?: PLACEHOLDER + } ?: PLACEHOLDER + podInfoBinding.timeOnPod.text = podStateManager.time?.let { rh.gs( R.string.omnipod_common_time_with_timezone, dateUtil.dateAndTimeString(it.toEpochSecond() * 1000), - podStateManager.timeZone.getDisplayName(true, TimeZone.SHORT) + timeZone ) } ?: PLACEHOLDER From eb6944370913d942f453349be6c281993aaaa084 Mon Sep 17 00:00:00 2001 From: Andrei Vereha Date: Sun, 14 Nov 2021 11:14:10 +0100 Subject: [PATCH 33/34] handleTimeChange: fail if there is no active profile --- .../plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt index 405e7da295..124923d042 100644 --- a/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt +++ b/omnipod-dash/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/dash/OmnipodDashPumpPlugin.kt @@ -1193,7 +1193,7 @@ class OmnipodDashPumpPlugin @Inject constructor( private fun handleTimeChange(): PumpEnactResult { return profileFunction.getProfile()?.let { setNewBasalProfile(it, OmnipodCommandType.SET_TIME) - } ?: PumpEnactResult(injector).success(true).enacted(false).comment("No profile active") + } ?: PumpEnactResult(injector).success(false).enacted(false).comment("No profile active") } private fun updateAlertConfiguration(): PumpEnactResult { From 4cea57acf6d74baffef83e1f04376b10bb5c1978 Mon Sep 17 00:00:00 2001 From: Milos Kozak Date: Sun, 14 Nov 2021 22:26:18 +0100 Subject: [PATCH 34/34] Eros: try to resolve fake TBR alert --- .../pump/omnipod/eros/driver/manager/ErosPodStateManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/driver/manager/ErosPodStateManager.java b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/driver/manager/ErosPodStateManager.java index e066f5e1a9..1394c2f8b4 100644 --- a/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/driver/manager/ErosPodStateManager.java +++ b/omnipod-eros/src/main/java/info/nightscout/androidaps/plugins/pump/omnipod/eros/driver/manager/ErosPodStateManager.java @@ -50,7 +50,7 @@ public abstract class ErosPodStateManager { } public final void discardState() { - this.podState = null; + this.podState = new PodState(this.podState.address); storePodState(); }