Medtrum: Refactor setBolus()

Reconnect when connection is lost during bolus.
After crash/restart of AAPS during bolus wait for bolus progress and show Bolus is running.
This commit is contained in:
jbr7rr 2023-09-14 17:36:28 +02:00
parent de3f24a8fb
commit 18893dfe63
3 changed files with 111 additions and 56 deletions

View file

@ -225,9 +225,21 @@ class MedtrumPump @Inject constructor(
var patchAge = 0L // Time in seconds?! // As reported by pump, not used (yet) var patchAge = 0L // Time in seconds?! // As reported by pump, not used (yet)
// bolus status // bolus status
var bolusStartTime = 0L // Time in ms! private var _bolusStartTime = 0L // Time in ms!
var bolusStartTime: Long
get() = _bolusStartTime
set(value) {
_bolusStartTime = value
sp.putLong(R.string.key_bolus_start_time, value)
}
private var _bolusAmountToBeDelivered = 0.0 // amount to be delivered
var bolusAmountToBeDelivered: Double
get() = _bolusAmountToBeDelivered
set(value) {
_bolusAmountToBeDelivered = value
sp.putDouble(R.string.key_bolus_amount_to_be_delivered, value)
}
var bolusingTreatment: EventOverviewBolusProgress.Treatment? = null // actually delivered treatment var bolusingTreatment: EventOverviewBolusProgress.Treatment? = null // actually delivered treatment
var bolusAmountToBeDelivered = 0.0 // amount to be delivered
var bolusProgressLastTimeStamp: Long = 0 // timestamp of last bolus progress message var bolusProgressLastTimeStamp: Long = 0 // timestamp of last bolus progress message
var bolusStopped = false // bolus stopped by user var bolusStopped = false // bolus stopped by user
var bolusDone = false // Bolus completed or stopped on pump var bolusDone = false // Bolus completed or stopped on pump
@ -281,6 +293,8 @@ class MedtrumPump @Inject constructor(
_swVersion = sp.getString(R.string.key_sw_version, "") _swVersion = sp.getString(R.string.key_sw_version, "")
_patchStartTime = sp.getLong(R.string.key_patch_start_time, 0L) _patchStartTime = sp.getLong(R.string.key_patch_start_time, 0L)
_pumpTimeZoneOffset = sp.getInt(R.string.key_pump_time_zone_offset, 0) _pumpTimeZoneOffset = sp.getInt(R.string.key_pump_time_zone_offset, 0)
_bolusStartTime = sp.getLong(R.string.key_bolus_start_time, 0L)
_bolusAmountToBeDelivered = sp.getDouble(R.string.key_bolus_amount_to_be_delivered, 0.0)
loadActiveAlarms() loadActiveAlarms()

View file

@ -157,10 +157,10 @@ class MedtrumService : DaggerService(), BLECommCallback {
fun connect(from: String): Boolean { fun connect(from: String): Boolean {
aapsLogger.debug(LTag.PUMP, "connect: called from: $from") aapsLogger.debug(LTag.PUMP, "connect: called from: $from")
when (currentState) { return when (currentState) {
is IdleState -> { is IdleState -> {
medtrumPump.connectionState = ConnectionState.CONNECTING medtrumPump.connectionState = ConnectionState.CONNECTING
return bleComm.connect(from, medtrumPump.pumpSN) bleComm.connect(from, medtrumPump.pumpSN)
} }
is ReadyState -> { is ReadyState -> {
@ -178,7 +178,7 @@ class MedtrumService : DaggerService(), BLECommCallback {
else -> { else -> {
aapsLogger.error(LTag.PUMPCOMM, "Connect attempt when in state: $currentState from: $from") aapsLogger.error(LTag.PUMPCOMM, "Connect attempt when in state: $currentState from: $from")
return false false
} }
} }
} }
@ -216,6 +216,21 @@ class MedtrumService : DaggerService(), BLECommCallback {
fun readPumpStatus() { fun readPumpStatus() {
rxBus.send(EventPumpStatusChanged(rh.gs(R.string.getting_pump_status))) rxBus.send(EventPumpStatusChanged(rh.gs(R.string.getting_pump_status)))
updateTimeIfNeeded(false) updateTimeIfNeeded(false)
// Check if there is active bolus but it is not being monitored
// if so wait for bolus and show progress
if (!medtrumPump.bolusDone && medtrumPump.bolusingTreatment == null) {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(medtrumPump.bolusStartTime, medtrumPump.bolusAmountToBeDelivered)
if (detailedBolusInfo != null) {
detailedBolusInfoStorage.add(detailedBolusInfo) // Reinsert
}
medtrumPump.bolusingTreatment = EventOverviewBolusProgress.Treatment(0.0, 0, detailedBolusInfo?.bolusType == DetailedBolusInfo.BolusType.SMB, detailedBolusInfo?.id ?: 0)
if (detailedBolusInfo?.bolusType == DetailedBolusInfo.BolusType.SMB) {
rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.core.ui.R.string.smb_bolus_u, detailedBolusInfo.insulin)))
} else {
rxBus.send(EventPumpStatusChanged(rh.gs(info.nightscout.core.ui.R.string.bolus_u_min, detailedBolusInfo?.insulin ?: 0.0)))
}
waitForBolusProgress()
}
loadEvents() loadEvents()
} }
@ -300,29 +315,13 @@ class MedtrumService : DaggerService(), BLECommCallback {
} }
fun setBolus(detailedBolusInfo: DetailedBolusInfo, t: EventOverviewBolusProgress.Treatment): Boolean { fun setBolus(detailedBolusInfo: DetailedBolusInfo, t: EventOverviewBolusProgress.Treatment): Boolean {
if (!isConnected) { if (!canSetBolus()) return false
aapsLogger.warn(LTag.PUMPCOMM, "Pump not connected, not setting bolus")
return false
}
if (BolusProgressData.stopPressed) {
aapsLogger.warn(LTag.PUMPCOMM, "Bolus stop pressed, not setting bolus")
return false
}
if (!medtrumPump.bolusDone) {
aapsLogger.warn(LTag.PUMPCOMM, "Bolus already in progress, not setting new one")
return false
}
val insulin = detailedBolusInfo.insulin val insulin = detailedBolusInfo.insulin
if (insulin > 0) {
if (!sendPacketAndGetResponse(SetBolusPacket(injector, insulin))) { if (!sendBolusCommand(insulin)) {
aapsLogger.error(LTag.PUMPCOMM, "Failed to set bolus") aapsLogger.error(LTag.PUMPCOMM, "Failed to set bolus")
commandQueue.loadEvents(null) // make sure if anything is delivered (which is highly unlikely at this point) we get it commandQueue.loadEvents(null) // make sure if anything is delivered (which is highly unlikely at this point) we get it
t.insulin = 0.0
return false
}
} else {
aapsLogger.debug(LTag.PUMPCOMM, "Bolus not set, insulin: $insulin")
t.insulin = 0.0 t.insulin = 0.0
return false return false
} }
@ -355,35 +354,7 @@ class MedtrumService : DaggerService(), BLECommCallback {
aapsLogger.error(LTag.PUMPCOMM, "Bolus with tempId ${detailedBolusInfo.timestamp} already exists") aapsLogger.error(LTag.PUMPCOMM, "Bolus with tempId ${detailedBolusInfo.timestamp} already exists")
} }
val bolusingEvent = EventOverviewBolusProgress waitForBolusProgress()
var communicationLost = false
while (!medtrumPump.bolusStopped && !medtrumPump.bolusDone && !communicationLost) {
SystemClock.sleep(100)
if (System.currentTimeMillis() - medtrumPump.bolusProgressLastTimeStamp > T.secs(20).msecs()) {
communicationLost = true
aapsLogger.warn(LTag.PUMPCOMM, "Communication stopped")
disconnect("Communication stopped")
} else {
bolusingEvent.t = medtrumPump.bolusingTreatment
bolusingEvent.status = rh.gs(info.nightscout.pump.common.R.string.bolus_delivered_so_far, medtrumPump.bolusingTreatment?.insulin, medtrumPump.bolusAmountToBeDelivered)
bolusingEvent.percent = round((medtrumPump.bolusingTreatment?.insulin?.div(medtrumPump.bolusAmountToBeDelivered) ?: 0.0) * 100).toInt() - 1
rxBus.send(bolusingEvent)
}
}
bolusingEvent.percent = 99
val bolusDurationInMSec = (insulin * 60 * 1000)
val expectedEnd = bolusStart + bolusDurationInMSec + 1000
while (System.currentTimeMillis() < expectedEnd && !medtrumPump.bolusDone) {
SystemClock.sleep(1000)
}
// Allow time for notification packet with new sequnce number to arrive
SystemClock.sleep(2000)
bolusingEvent.t = medtrumPump.bolusingTreatment
medtrumPump.bolusingTreatment = null
if (medtrumPump.bolusStopped && t.insulin == 0.0) { if (medtrumPump.bolusStopped && t.insulin == 0.0) {
// In this case we don't get a bolus end event, so need to remove all the stuff added previously // In this case we don't get a bolus end event, so need to remove all the stuff added previously
@ -404,6 +375,75 @@ class MedtrumService : DaggerService(), BLECommCallback {
detailedBolusInfoStorage.findDetailedBolusInfo(bolusStart, detailedBolusInfo.insulin) detailedBolusInfoStorage.findDetailedBolusInfo(bolusStart, detailedBolusInfo.insulin)
} }
return true
}
private fun canSetBolus(): Boolean {
if (!isConnected) {
aapsLogger.warn(LTag.PUMPCOMM, "Pump not connected, not setting bolus")
return false
}
if (BolusProgressData.stopPressed) {
aapsLogger.warn(LTag.PUMPCOMM, "Bolus stop pressed, not setting bolus")
return false
}
if (!medtrumPump.bolusDone) {
aapsLogger.warn(LTag.PUMPCOMM, "Bolus already in progress, not setting new one")
return false
}
return true
}
private fun sendBolusCommand(insulin: Double): Boolean {
return if (insulin > 0) {
sendPacketAndGetResponse(SetBolusPacket(injector, insulin))
} else {
aapsLogger.debug(LTag.PUMPCOMM, "Bolus not set, insulin: $insulin")
false
}
}
private fun waitForBolusProgress() {
val bolusingEvent = EventOverviewBolusProgress
var communicationLost = false
var connectionRetryCounter = 0
var checkTime = medtrumPump.bolusProgressLastTimeStamp
while (!medtrumPump.bolusStopped && !medtrumPump.bolusDone && !communicationLost) {
SystemClock.sleep(100)
if (medtrumPump.bolusProgressLastTimeStamp > checkTime) checkTime = medtrumPump.bolusProgressLastTimeStamp
if (System.currentTimeMillis() - checkTime > T.secs(20).msecs()) {
if (connectionRetryCounter < 3) {
aapsLogger.warn(LTag.PUMPCOMM, "No bolus progress for 20 seconds, retrying connection")
connect("retrying connection")
checkTime = System.currentTimeMillis()
connectionRetryCounter++
} else {
communicationLost = true
aapsLogger.warn(LTag.PUMPCOMM, "Retry connection faled, communication stopped")
disconnect("Communication stopped")
}
} else {
bolusingEvent.t = medtrumPump.bolusingTreatment
bolusingEvent.status = rh.gs(info.nightscout.pump.common.R.string.bolus_delivered_so_far, medtrumPump.bolusingTreatment?.insulin, medtrumPump.bolusAmountToBeDelivered)
bolusingEvent.percent = round((medtrumPump.bolusingTreatment?.insulin?.div(medtrumPump.bolusAmountToBeDelivered) ?: 0.0) * 100).toInt() - 1
rxBus.send(bolusingEvent)
}
}
bolusingEvent.percent = 99
val bolusDurationInMSec = (medtrumPump.bolusAmountToBeDelivered * 60 * 1000)
val expectedEnd = medtrumPump.bolusStartTime + bolusDurationInMSec + 1000
while (System.currentTimeMillis() < expectedEnd && !medtrumPump.bolusDone) {
SystemClock.sleep(1000)
}
// Allow time for notification packet with new sequnce number to arrive
SystemClock.sleep(2000)
bolusingEvent.t = medtrumPump.bolusingTreatment
medtrumPump.bolusingTreatment = null
// Do not call update status directly, reconnection may be needed // Do not call update status directly, reconnection may be needed
commandQueue.loadEvents(object : Callback() { commandQueue.loadEvents(object : Callback() {
override fun run() { override fun run() {
@ -411,7 +451,6 @@ class MedtrumService : DaggerService(), BLECommCallback {
bolusingEvent.percent = 100 bolusingEvent.percent = 100
} }
}) })
return true
} }
fun stopBolus() { fun stopBolus() {

View file

@ -11,6 +11,8 @@
<string name="key_pump_state" translatable="false">pump_state</string> <string name="key_pump_state" translatable="false">pump_state</string>
<string name="key_active_alarms" translatable="false">active_alarms</string> <string name="key_active_alarms" translatable="false">active_alarms</string>
<string name="key_last_connection" translatable="false">last_connection</string> <string name="key_last_connection" translatable="false">last_connection</string>
<string name="key_bolus_start_time" translatable="false">bolus_start_time</string>
<string name="key_bolus_amount_to_be_delivered" translatable = "false">bolus_amount_to_be_delivered</string>
<string name="key_last_bolus_time" translatable="false">last_bolus_time</string> <string name="key_last_bolus_time" translatable="false">last_bolus_time</string>
<string name="key_last_bolus_amount" translatable="false">last_bolus_amount</string> <string name="key_last_bolus_amount" translatable="false">last_bolus_amount</string>
<string name="key_session_token" translatable="false">medtrum_session_token</string> <string name="key_session_token" translatable="false">medtrum_session_token</string>