diff --git a/core/interfaces/src/main/java/info/nightscout/interfaces/pump/Medtrum.kt b/core/interfaces/src/main/java/info/nightscout/interfaces/pump/Medtrum.kt new file mode 100644 index 0000000000..d17e58d45f --- /dev/null +++ b/core/interfaces/src/main/java/info/nightscout/interfaces/pump/Medtrum.kt @@ -0,0 +1,9 @@ +package info.nightscout.interfaces.pump + +/** + * Functionality supported by Medtrum* pumps only + */ +interface Medtrum { + + fun loadEvents(): PumpEnactResult // events history to build treatments from +} \ No newline at end of file diff --git a/implementation/src/main/java/info/nightscout/implementation/queue/commands/CommandLoadEvents.kt b/implementation/src/main/java/info/nightscout/implementation/queue/commands/CommandLoadEvents.kt index df6fb48cef..16475adf4f 100644 --- a/implementation/src/main/java/info/nightscout/implementation/queue/commands/CommandLoadEvents.kt +++ b/implementation/src/main/java/info/nightscout/implementation/queue/commands/CommandLoadEvents.kt @@ -4,6 +4,7 @@ import dagger.android.HasAndroidInjector import info.nightscout.interfaces.plugin.ActivePlugin import info.nightscout.interfaces.pump.Dana import info.nightscout.interfaces.pump.Diaconn +import info.nightscout.interfaces.pump.Medtrum import info.nightscout.interfaces.pump.PumpEnactResult import info.nightscout.interfaces.queue.Callback import info.nightscout.interfaces.queue.Command @@ -32,6 +33,13 @@ class CommandLoadEvents( aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}") callback?.result(r)?.run() } + + if (pump is Medtrum) { + val medtrumPump = pump as Medtrum + val r = medtrumPump.loadEvents() + aapsLogger.debug(LTag.PUMPQUEUE, "Result success: ${r.success} enacted: ${r.enacted}") + callback?.result(r)?.run() + } } override fun status(): String = rh.gs(info.nightscout.core.ui.R.string.load_events) diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPlugin.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPlugin.kt index 5cbdbd4f4a..bfef4fa928 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPlugin.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPlugin.kt @@ -17,6 +17,7 @@ import info.nightscout.interfaces.profile.Profile import info.nightscout.interfaces.profile.ProfileFunction import info.nightscout.interfaces.pump.DetailedBolusInfo import info.nightscout.interfaces.pump.DetailedBolusInfoStorage +import info.nightscout.interfaces.pump.Medtrum import info.nightscout.interfaces.pump.Pump import info.nightscout.interfaces.pump.PumpEnactResult import info.nightscout.interfaces.pump.PumpPluginBase @@ -85,7 +86,7 @@ import kotlin.math.round .shortName(R.string.medtrum_pump_shortname) .preferencesId(R.xml.pref_medtrum_pump) .description(R.string.medtrum_pump_description), injector, aapsLogger, rh, commandQueue -), Pump { +), Pump, Medtrum { private val disposable = CompositeDisposable() private var medtrumService: MedtrumService? = null @@ -270,16 +271,20 @@ import kotlin.math.round // round rate to pump rate val pumpRate = constraintChecker.applyBasalConstraints(Constraint(absoluteRate), profile).value() temporaryBasalStorage.add(PumpSync.PumpState.TemporaryBasal(dateUtil.now(), T.mins(durationInMinutes.toLong()).msecs(), pumpRate, true, tbrType, 0L, 0L)) - val connectionOk = medtrumService?.setTempBasal(pumpRate, durationInMinutes) ?: false - if (connectionOk - && medtrumPump.tempBasalInProgress + val connectionOK = medtrumService?.setTempBasal(pumpRate, durationInMinutes) ?: false + if (connectionOK + && medtrumPump.tempBasalInProgress && Math.abs(medtrumPump.tempBasalAbsoluteRate - pumpRate) <= 0.05 - /*&& Math.abs(medtrumPump.tempBasalRemainingMinutes - durationInMinutes) <= 5*/) { - - return PumpEnactResult(injector).success(true).enacted(true).duration(/*medtrumPump.tempBasalRemainingMinutes*/durationInMinutes).absolute(medtrumPump.tempBasalAbsoluteRate).isPercent(false) + /*&& Math.abs(medtrumPump.tempBasalRemainingMinutes - durationInMinutes) <= 5*/) { + + return PumpEnactResult(injector).success(true).enacted(true).duration(/*medtrumPump.tempBasalRemainingMinutes*/durationInMinutes).absolute(medtrumPump.tempBasalAbsoluteRate) + .isPercent(false) .isTempCancel(false) } else { - aapsLogger.error(LTag.PUMP, "setTempBasalAbsolute failed, connectionOk: $connectionOk, tempBasalInProgress: ${medtrumPump.tempBasalInProgress}, tempBasalAbsoluteRate: ${medtrumPump.tempBasalAbsoluteRate}") //, tempBasalRemainingMinutes: ${medtrumPump.tempBasalRemainingMinutes}") + aapsLogger.error( + LTag.PUMP, + "setTempBasalAbsolute failed, connectionOK: $connectionOK, tempBasalInProgress: ${medtrumPump.tempBasalInProgress}, tempBasalAbsoluteRate: ${medtrumPump.tempBasalAbsoluteRate}" + ) //, tempBasalRemainingMinutes: ${medtrumPump.tempBasalRemainingMinutes}") return PumpEnactResult(injector).success(false).enacted(false).comment("Medtrum setTempBasalAbsolute failed") } } @@ -298,11 +303,11 @@ import kotlin.math.round if (!isInitialized()) return PumpEnactResult(injector).success(false).enacted(false) aapsLogger.info(LTag.PUMP, "cancelTempBasal - enforceNew: $enforceNew") - val connectionOk = medtrumService?.cancelTempBasal() ?: false - if (connectionOk && !medtrumPump.tempBasalInProgress) { + val connectionOK = medtrumService?.cancelTempBasal() ?: false + if (connectionOK && !medtrumPump.tempBasalInProgress) { return PumpEnactResult(injector).success(true).enacted(true).isTempCancel(true) } else { - aapsLogger.error(LTag.PUMP, "cancelTempBasal failed, connectionOk: $connectionOk, tempBasalInProgress: ${medtrumPump.tempBasalInProgress}") + aapsLogger.error(LTag.PUMP, "cancelTempBasal failed, connectionOK: $connectionOK, tempBasalInProgress: ${medtrumPump.tempBasalInProgress}") return PumpEnactResult(injector).success(false).enacted(false).comment("Medtrum cancelTempBasal failed") } } @@ -357,4 +362,15 @@ import kotlin.math.round override fun timezoneOrDSTChanged(timeChangeType: TimeChangeType) { } + + // Medtrum interface + override fun loadEvents(): PumpEnactResult { + if (!isInitialized()) { + val result = PumpEnactResult(injector).success(false) + result.comment = "pump not initialized" + return result + } + val connectionOK = medtrumService?.loadEvents() ?: false + return PumpEnactResult(injector).success(connectionOK) + } } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/CancelTempBasalPacket.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/CancelTempBasalPacket.kt index 3503c4a0fe..c3067ed501 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/CancelTempBasalPacket.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/CancelTempBasalPacket.kt @@ -48,16 +48,19 @@ class CancelTempBasalPacket(injector: HasAndroidInjector) : MedtrumPacket(inject medtrumPump.handleBasalStatusUpdate(basalType, basalRate, basalSequence, basalPatchId, basalStartTime) - pumpSync.syncStopTemporaryBasalWithPumpId( - timestamp = basalStartTime, // Time of normal basal start = time of tbr end - endPumpId = basalStartTime, - pumpType = medtrumPump.pumpType, - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - aapsLogger.warn( - LTag.PUMPCOMM, - "CancelTempBasalPacket: EVENT TEMP_END ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " - ) + if (basalType == BasalType.STANDARD) { + // If we have standard here, means TBR is cancelled successfully + pumpSync.syncStopTemporaryBasalWithPumpId( + timestamp = basalStartTime, // Time of normal basal start = time of tbr end + endPumpId = basalStartTime, + pumpType = medtrumPump.pumpType, + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + aapsLogger.debug( + LTag.PUMPCOMM, + "CancelTempBasalPacket: EVENT TEMP_END ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + ) + } } return success } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/SynchronizePacket.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/SynchronizePacket.kt index e2c80fe7dc..4df32dafe7 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/SynchronizePacket.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/SynchronizePacket.kt @@ -55,12 +55,12 @@ class SynchronizePacket(injector: HasAndroidInjector) : MedtrumPacket(injector) offset += 4 // If field is present, skip 4 bytes } if (fieldMask and MASK_NORMAL_BOLUS != 0) { - aapsLogger.warn(LTag.PUMPCOMM, "SynchronizePacket: Normal bolus present removing from fieldMask") + aapsLogger.debug(LTag.PUMPCOMM, "SynchronizePacket: Normal bolus present removing from fieldMask") fieldMask = fieldMask and MASK_NORMAL_BOLUS.inv() syncData = syncData.copyOfRange(0, offset) + syncData.copyOfRange(offset + 3, syncData.size) } if (fieldMask and MASK_EXTENDED_BOLUS != 0) { - aapsLogger.warn(LTag.PUMPCOMM, "SynchronizePacket: Extended bolus present removing from fieldMask") + aapsLogger.debug(LTag.PUMPCOMM, "SynchronizePacket: Extended bolus present removing from fieldMask") fieldMask = fieldMask and MASK_EXTENDED_BOLUS.inv() syncData = syncData.copyOfRange(0, offset) + syncData.copyOfRange(offset + 3, syncData.size) } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/BLEComm.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/BLEComm.kt index c934a84ccf..fe62dfe767 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/BLEComm.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/BLEComm.kt @@ -72,7 +72,7 @@ class BLEComm @Inject internal constructor( companion object { - private const val WRITE_DELAY_MILLIS: Long = 50 + private const val WRITE_DELAY_MILLIS: Long = 100 private const val SERVICE_UUID = "669A9001-0008-968F-E311-6050405558B3" private const val READ_UUID = "669a9120-0008-968f-e311-6050405558b3" private const val WRITE_UUID = "669a9101-0008-968f-e311-6050405558b3" diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/MedtrumService.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/MedtrumService.kt index 3742448a25..2bf9de608b 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/MedtrumService.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/services/MedtrumService.kt @@ -72,7 +72,6 @@ class MedtrumService : DaggerService(), BLECommCallback { companion object { - // TODO: Test and further increase? private const val COMMAND_DEFAULT_TIMEOUT_SEC: Long = 60 private const val COMMAND_SYNC_TIMEOUT_SEC: Long = 120 private const val COMMAND_CONNECTING_TIMEOUT_SEC: Long = 30 @@ -198,9 +197,12 @@ class MedtrumService : DaggerService(), BLECommCallback { bleComm.disconnect(from) } - fun readPumpStatus() { - // Most of these things are already done when a connection is setup, but wo dont know how long the pump was connected for? + fun readPumpStatus() { + // Update pump events + loadEvents() + } + fun loadEvents(): Boolean { // Send a poll patch, to workaround connection losses? var result = sendPacketAndGetResponse(PollPatchPacket(injector)) // So just do a syncronize to make sure we have the latest data @@ -210,9 +212,11 @@ class MedtrumService : DaggerService(), BLECommCallback { if (result) result = syncRecords() if (!result) { aapsLogger.error(LTag.PUMPCOMM, "Failed to sync records") - return } if (result) medtrumPump.lastConnection = System.currentTimeMillis() + aapsLogger.debug(LTag.PUMPCOMM, "Events loaded") + rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.medtrum.R.string.gettingpumpstatus))) + return result } fun setBolus(insulin: Double, t: EventOverviewBolusProgress.Treatment): Boolean { @@ -250,13 +254,19 @@ class MedtrumService : DaggerService(), BLECommCallback { val bolusDurationInMSec = (insulin * 60 * 1000) val expectedEnd = bolusStart + bolusDurationInMSec + 2000 - while (System.currentTimeMillis() < expectedEnd && result == true) { + while (System.currentTimeMillis() < expectedEnd && result == true && medtrumPump.bolusDone == false) { SystemClock.sleep(1000) } // Do not call update status directly, reconnection may be needed - commandQueue.readStatus(rh.gs(info.nightscout.pump.medtrum.R.string.gettingbolusstatus), object : Callback() { + commandQueue.loadEvents(object : Callback() { override fun run() { + if (this.result.success == false && isConnected == false) { + // Reschedule loadEvents when we lost connection during the command + aapsLogger.warn(LTag.PUMP, "loadEvents failed due to connection loss, rescheduling") + commandQueue.loadEvents(this) + return + } rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.medtrum.R.string.gettingbolusstatus))) bolusingEvent.percent = 100 } @@ -278,7 +288,7 @@ class MedtrumService : DaggerService(), BLECommCallback { // Get history records, this will update the prevoius basals // Do not call update status directly, reconnection may be needed - commandQueue.readStatus(rh.gs(info.nightscout.pump.medtrum.R.string.gettingtempbasalstatus), object : Callback() { + commandQueue.loadEvents(object : Callback() { override fun run() { rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.medtrum.R.string.gettingtempbasalstatus))) } @@ -292,7 +302,7 @@ class MedtrumService : DaggerService(), BLECommCallback { // Get history records, this will update the prevoius basals // Do not call update status directly, reconnection may be needed - commandQueue.readStatus(rh.gs(info.nightscout.pump.medtrum.R.string.gettingtempbasalstatus), object : Callback() { + commandQueue.loadEvents(object : Callback() { override fun run() { rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.pump.medtrum.R.string.gettingtempbasalstatus))) } @@ -312,7 +322,7 @@ class MedtrumService : DaggerService(), BLECommCallback { if (result) result = packet?.let { sendPacketAndGetResponse(it) } == true // Get history records, this will update the pump state and add changes in TBR to AAPS history - if (result) result = syncRecords() + commandQueue.loadEvents(null) return result } @@ -690,9 +700,11 @@ class MedtrumService : DaggerService(), BLECommCallback { override fun onEnter() { aapsLogger.debug(LTag.PUMPCOMM, "Medtrum Service reached ReadyState!") // Now we are fully connected and authenticated and we can start sending commands. Let AAPS know - medtrumPump.connectionState = ConnectionState.CONNECTED - if (medtrumPlugin.isInitialized()) { - rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED)) + if (isConnected == false) { + medtrumPump.connectionState = ConnectionState.CONNECTED + if (medtrumPlugin.isInitialized()) { + rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED)) + } } } } diff --git a/pump/medtrum/src/main/res/values/strings.xml b/pump/medtrum/src/main/res/values/strings.xml index f665fc5dfe..2e0e041f14 100644 --- a/pump/medtrum/src/main/res/values/strings.xml +++ b/pump/medtrum/src/main/res/values/strings.xml @@ -46,7 +46,9 @@ SN Serial number pump base + Waiting for bolus end. Remaining %1$d sec. + Getting pump status Getting bolus status Getting temporary basal status