Notifications and fake TBR on state changes

This commit is contained in:
jbr7rr 2023-06-13 13:35:08 +02:00
parent 8caeb4a3e0
commit 419def7f6b
6 changed files with 86 additions and 44 deletions

View file

@ -131,9 +131,10 @@ open class Notification {
const val IDENTIFICATION_NOT_SET = 77 const val IDENTIFICATION_NOT_SET = 77
const val PERMISSION_BT = 78 const val PERMISSION_BT = 78
const val EOELOW_PATCH_ALERTS = 79 const val EOELOW_PATCH_ALERTS = 79
const val COMBO_PUMP_SUSPENDED = 80 const val PUMP_SUSPENDED = 80
const val COMBO_UNKNOWN_TBR = 81 const val COMBO_UNKNOWN_TBR = 81
const val BLUETOOTH_NOT_ENABLED = 82 const val BLUETOOTH_NOT_ENABLED = 82
const val PATCH_NOT_ACTIVE = 83
const val USER_MESSAGE = 1000 const val USER_MESSAGE = 1000

View file

@ -2216,7 +2216,7 @@ class ComboV2Plugin @Inject constructor (
// only shows up in the Combo fragment. // only shows up in the Combo fragment.
if (newState == DriverState.Suspended) { if (newState == DriverState.Suspended) {
uiInteraction.addNotification( uiInteraction.addNotification(
Notification.COMBO_PUMP_SUSPENDED, Notification.PUMP_SUSPENDED,
text = rh.gs(R.string.combov2_pump_is_suspended), text = rh.gs(R.string.combov2_pump_is_suspended),
level = Notification.NORMAL level = Notification.NORMAL
) )

View file

@ -33,6 +33,11 @@ class MedtrumPump @Inject constructor(
private val temporaryBasalStorage: TemporaryBasalStorage private val temporaryBasalStorage: TemporaryBasalStorage
) { ) {
companion object {
const val FAKE_TBR_LENGTH = 4800L
}
// Connection state flow // Connection state flow
private val _connectionState = MutableStateFlow(ConnectionState.DISCONNECTED) private val _connectionState = MutableStateFlow(ConnectionState.DISCONNECTED)
val connectionStateFlow: StateFlow<ConnectionState> = _connectionState val connectionStateFlow: StateFlow<ConnectionState> = _connectionState
@ -42,7 +47,6 @@ class MedtrumPump @Inject constructor(
_connectionState.value = value _connectionState.value = value
} }
// Pump state flow // Pump state flow
private val _pumpState = MutableStateFlow(MedtrumPumpState.NONE) private val _pumpState = MutableStateFlow(MedtrumPumpState.NONE)
val pumpStateFlow: StateFlow<MedtrumPumpState> = _pumpState val pumpStateFlow: StateFlow<MedtrumPumpState> = _pumpState
@ -61,15 +65,15 @@ class MedtrumPump @Inject constructor(
set(value) { set(value) {
_primeProgress.value = value _primeProgress.value = value
} }
private var _lastBasalType: MutableStateFlow<BasalType> = MutableStateFlow(BasalType.NONE) private var _lastBasalType: MutableStateFlow<BasalType> = MutableStateFlow(BasalType.NONE)
val lastBasalTypeFlow: StateFlow<BasalType> = _lastBasalType val lastBasalTypeFlow: StateFlow<BasalType> = _lastBasalType
var lastBasalType: BasalType var lastBasalType: BasalType
get() = _lastBasalType.value get() = _lastBasalType.value
set(value) { set(value) {
_lastBasalType.value = value _lastBasalType.value = value
} }
private val _lastBasalRate = MutableStateFlow(0.0) private val _lastBasalRate = MutableStateFlow(0.0)
val lastBasalRateFlow: StateFlow<Double> = _lastBasalRate val lastBasalRateFlow: StateFlow<Double> = _lastBasalRate
var lastBasalRate: Double var lastBasalRate: Double
@ -85,7 +89,7 @@ class MedtrumPump @Inject constructor(
set(value) { set(value) {
_reservoir.value = value _reservoir.value = value
} }
/** Stuff stored in SP */ /** Stuff stored in SP */
private var _patchSessionToken = 0L private var _patchSessionToken = 0L
var patchSessionToken: Long var patchSessionToken: Long
@ -125,7 +129,7 @@ class MedtrumPump @Inject constructor(
set(value) { set(value) {
_actualBasalProfile = value _actualBasalProfile = value
val encodedString = Base64.encodeToString(value, Base64.DEFAULT) val encodedString = Base64.encodeToString(value, Base64.DEFAULT)
sp.putString(R.string.key_actual_basal_profile, encodedString?: "") sp.putString(R.string.key_actual_basal_profile, encodedString ?: "")
} }
private var _pumpSN = 0L private var _pumpSN = 0L
@ -140,7 +144,6 @@ class MedtrumPump @Inject constructor(
var patchStartTime = 0L // Time in ms! var patchStartTime = 0L // Time in ms!
var patchAge = 0L // Time in seconds?! // TODO: Not used var patchAge = 0L // Time in seconds?! // TODO: Not used
var batteryVoltage_A = 0.0 var batteryVoltage_A = 0.0
var batteryVoltage_B = 0.0 var batteryVoltage_B = 0.0
@ -276,7 +279,7 @@ class MedtrumPump @Inject constructor(
bolusDone = true bolusDone = true
bolusingTreatment?.insulin = amountDelivered bolusingTreatment?.insulin = amountDelivered
} else { } else {
bolusingTreatment?.insulin = amountDelivered bolusingTreatment?.insulin = amountDelivered
} }
} }
@ -292,7 +295,7 @@ class MedtrumPump @Inject constructor(
val temporaryBasalInfo = temporaryBasalStorage.findTemporaryBasal(basalStartTime, basalRate) val temporaryBasalInfo = temporaryBasalStorage.findTemporaryBasal(basalStartTime, basalRate)
// If duration is unknown, no way to get it now, set patch lifetime as duration // If duration is unknown, no way to get it now, set patch lifetime as duration
val duration = temporaryBasalInfo?.duration ?: T.mins(4800).msecs() val duration = temporaryBasalInfo?.duration ?: T.mins(FAKE_TBR_LENGTH).msecs()
val newRecord = pumpSync.syncTemporaryBasalWithPumpId( val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = basalStartTime, timestamp = basalStartTime,
rate = basalRate, // TODO: Support percent here, this will break things? Check if this is correct rate = basalRate, // TODO: Support percent here, this will break things? Check if this is correct
@ -311,7 +314,7 @@ class MedtrumPump @Inject constructor(
val newRecord = pumpSync.syncTemporaryBasalWithPumpId( val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = basalStartTime, timestamp = basalStartTime,
rate = 0.0, rate = 0.0,
duration = T.mins(4800).msecs(), // TODO MAGIC NUMBER duration = T.mins(FAKE_TBR_LENGTH).msecs(),
isAbsolute = true, isAbsolute = true,
type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, type = PumpSync.TemporaryBasalType.PUMP_SUSPEND,
pumpId = basalStartTime, pumpId = basalStartTime,
@ -322,23 +325,9 @@ class MedtrumPump @Inject constructor(
LTag.PUMPCOMM, LTag.PUMPCOMM,
"handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) expectedTemporaryBasal: $expectedTemporaryBasal" "handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) expectedTemporaryBasal: $expectedTemporaryBasal"
) )
} else if (basalType == BasalType.NONE && expectedTemporaryBasal?.rate != basalRate && expectedTemporaryBasal?.duration != T.mins(4800).msecs()) { } else if (basalType == BasalType.NONE && expectedTemporaryBasal?.rate != basalRate && expectedTemporaryBasal?.duration != T.mins(FAKE_TBR_LENGTH).msecs()) {
// Pump suspended, set fake TBR // Pump suspended, set fake TBR
// TODO: Maybe move this to separate function? setFakeTBR()
val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = dateUtil.now(),
rate = basalRate,
duration = T.mins(4800).msecs(), // TODO MAGIC NUMBER
isAbsolute = true,
type = PumpSync.TemporaryBasalType.PUMP_SUSPEND,
pumpId = dateUtil.now(),
pumpType = pumpType,
pumpSerial = pumpSN.toString(radix = 16)
)
aapsLogger.debug(
LTag.PUMPCOMM,
"handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) expectedTemporaryBasal: $expectedTemporaryBasal"
)
} }
// Update medtrum pump state // Update medtrum pump state
@ -366,4 +355,28 @@ class MedtrumPump @Inject constructor(
aapsLogger.error(LTag.PUMP, "handleStopStatusUpdate: WTF? PatchId in status update does not match current patchId!") aapsLogger.error(LTag.PUMP, "handleStopStatusUpdate: WTF? PatchId in status update does not match current patchId!")
} }
} }
fun setFakeTBRIfNeeded() {
val expectedTemporaryBasal = pumpSync.expectedPumpState().temporaryBasal
if (expectedTemporaryBasal?.rate != 0.0 && expectedTemporaryBasal?.duration != T.mins(FAKE_TBR_LENGTH).msecs()) {
setFakeTBR()
}
}
private fun setFakeTBR() {
val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = dateUtil.now(),
rate = 0.0,
duration = T.mins(FAKE_TBR_LENGTH).msecs(),
isAbsolute = true,
type = PumpSync.TemporaryBasalType.PUMP_SUSPEND,
pumpId = dateUtil.now(),
pumpType = pumpType,
pumpSerial = pumpSN.toString(radix = 16)
)
aapsLogger.debug(
LTag.PUMPCOMM,
"handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START (FAKE)"
)
}
} }

View file

@ -177,8 +177,7 @@ class BLEComm @Inject internal constructor(
// Reset sequence counter // Reset sequence counter
mWriteSequenceNumber = 0 mWriteSequenceNumber = 0
if (mBluetoothGatt == null) { if (mBluetoothGatt == null) {
mBluetoothGatt = mBluetoothGatt = device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
device.connectGatt(context, false, mGattCallback, BluetoothDevice.TRANSPORT_LE)
} else { } else {
// Already connected?, this should not happen force disconnect // Already connected?, this should not happen force disconnect
aapsLogger.error(LTag.PUMPBTCOMM, "connectGatt, mBluetoothGatt is not null") aapsLogger.error(LTag.PUMPBTCOMM, "connectGatt, mBluetoothGatt is not null")
@ -200,7 +199,7 @@ class BLEComm @Inject internal constructor(
isConnecting = false isConnecting = false
stopScan() stopScan()
SystemClock.sleep(100) SystemClock.sleep(100)
} }
if (isConnected) { if (isConnected) {
aapsLogger.debug(LTag.PUMPBTCOMM, "Connected, disconnecting") aapsLogger.debug(LTag.PUMPBTCOMM, "Connected, disconnecting")
mBluetoothGatt?.disconnect() mBluetoothGatt?.disconnect()
@ -402,7 +401,7 @@ class BLEComm @Inject internal constructor(
aapsLogger.warn(LTag.PUMPBTCOMM, "Disconnected while connecting! Reset device address") aapsLogger.warn(LTag.PUMPBTCOMM, "Disconnected while connecting! Reset device address")
mDevice = null mDevice = null
// Wait a bit before retrying // Wait a bit before retrying
SystemClock.sleep(2000) SystemClock.sleep(2000)
} }
close() close()
isConnected = false isConnected = false

View file

@ -110,13 +110,46 @@ class MedtrumService : DaggerService(), BLECommCallback {
scope.launch { scope.launch {
medtrumPump.pumpStateFlow.collect { state -> medtrumPump.pumpStateFlow.collect { state ->
when (state) { when (state) {
MedtrumPumpState.NONE,
MedtrumPumpState.IDLE,
MedtrumPumpState.FILLED,
MedtrumPumpState.PRIMING,
MedtrumPumpState.PRIMED,
MedtrumPumpState.EJECTING,
MedtrumPumpState.EJECTED,
MedtrumPumpState.STOPPED -> {
rxBus.send(EventDismissNotification(Notification.PUMP_ERROR))
rxBus.send(EventDismissNotification(Notification.PUMP_SUSPENDED))
uiInteraction.addNotification(
Notification.PATCH_NOT_ACTIVE,
rh.gs(R.string.patch_not_active),
Notification.URGENT,
)
medtrumPump.setFakeTBRIfNeeded()
}
MedtrumPumpState.ACTIVE,
MedtrumPumpState.ACTIVE_ALT -> {
rxBus.send(EventDismissNotification(Notification.PATCH_NOT_ACTIVE))
rxBus.send(EventDismissNotification(Notification.PUMP_SUSPENDED))
}
MedtrumPumpState.LOWBG_SUSPENDED, MedtrumPumpState.LOWBG_SUSPENDED,
MedtrumPumpState.LOWBG_SUSPENDED2, MedtrumPumpState.LOWBG_SUSPENDED2,
MedtrumPumpState.AUTO_SUSPENDED, MedtrumPumpState.AUTO_SUSPENDED,
MedtrumPumpState.HMAX_SUSPENDED, MedtrumPumpState.HMAX_SUSPENDED,
MedtrumPumpState.DMAX_SUSPENDED, MedtrumPumpState.DMAX_SUSPENDED,
MedtrumPumpState.SUSPENDED, MedtrumPumpState.SUSPENDED,
MedtrumPumpState.PAUSED, MedtrumPumpState.PAUSED -> {
// TODO: Message with reason
uiInteraction.addNotification(
Notification.PUMP_SUSPENDED,
rh.gs(R.string.pump_is_suspended),
Notification.NORMAL,
)
// Pump will report proper TBR for this
}
MedtrumPumpState.OCCLUSION, MedtrumPumpState.OCCLUSION,
MedtrumPumpState.EXPIRED, MedtrumPumpState.EXPIRED,
MedtrumPumpState.RESERVOIR_EMPTY, MedtrumPumpState.RESERVOIR_EMPTY,
@ -125,21 +158,16 @@ class MedtrumService : DaggerService(), BLECommCallback {
MedtrumPumpState.BASE_FAULT, MedtrumPumpState.BASE_FAULT,
MedtrumPumpState.BATTERY_OUT, MedtrumPumpState.BATTERY_OUT,
MedtrumPumpState.NO_CALIBRATION -> { MedtrumPumpState.NO_CALIBRATION -> {
// Pump suspended show error! rxBus.send(EventDismissNotification(Notification.PATCH_NOT_ACTIVE))
rxBus.send(EventDismissNotification(Notification.PUMP_SUSPENDED))
// Pump suspended due to error, show error!
uiInteraction.addNotificationWithSound( uiInteraction.addNotificationWithSound(
Notification.PUMP_ERROR, Notification.PUMP_ERROR,
rh.gs(R.string.pump_error, state.toString()), rh.gs(R.string.pump_error, state.toString()),
Notification.URGENT, Notification.URGENT,
info.nightscout.core.ui.R.raw.alarm info.nightscout.core.ui.R.raw.alarm
) )
} medtrumPump.setFakeTBRIfNeeded()
MedtrumPumpState.STOPPED -> {
rxBus.send(EventDismissNotification(Notification.PUMP_ERROR))
}
else -> {
// Do nothing
} }
} }
} }
@ -197,7 +225,7 @@ class MedtrumService : DaggerService(), BLECommCallback {
bleComm.disconnect(from) bleComm.disconnect(from)
} }
fun readPumpStatus() { fun readPumpStatus() {
// Update pump events // Update pump events
loadEvents() loadEvents()
} }

View file

@ -15,6 +15,8 @@
<string name="medtrum_pump_description">Medtrum Nano</string> <string name="medtrum_pump_description">Medtrum Nano</string>
<string name="medtrumpump_settings">Medtrum pump settings</string> <string name="medtrumpump_settings">Medtrum pump settings</string>
<string name="pump_error">Pump error: %1$s !! </string> <string name="pump_error">Pump error: %1$s !! </string>
<string name="pump_is_suspended">Pump is suspended</string>
<string name="patch_not_active">Patch not activated</string>
<!-- overview fragment --> <!-- overview fragment -->
<string name="medtrum_ble_status">BLE Status</string> <string name="medtrum_ble_status">BLE Status</string>
@ -52,5 +54,4 @@
<string name="gettingbolusstatus">Getting bolus status</string> <string name="gettingbolusstatus">Getting bolus status</string>
<string name="gettingtempbasalstatus">Getting temporary basal status</string> <string name="gettingtempbasalstatus">Getting temporary basal status</string>
</resources> </resources>