From 9dee9139776bb6770e88e193d0657a3b076ada37 Mon Sep 17 00:00:00 2001 From: jbr7rr <> Date: Sun, 17 Sep 2023 17:29:34 +0200 Subject: [PATCH 1/4] Medtrum: Fix Suspended not syncing, fix duration in extended bolus --- .../pump/medtrum/comm/enums/BasalEndReason.kt | 34 +++++++++++++++++++ .../pump/medtrum/comm/enums/BasalType.kt | 15 ++++++++ .../medtrum/comm/packets/GetRecordPacket.kt | 23 +++++++++---- 3 files changed, 66 insertions(+), 6 deletions(-) create mode 100644 pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt new file mode 100644 index 0000000000..70594a49ba --- /dev/null +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt @@ -0,0 +1,34 @@ +package info.nightscout.pump.medtrum.comm.enums + +enum class BasalEndReason { + SUCCESS, + SUSPEND_LOW_GLUCOSE, + SUSPEND_PREDICT_LOW_GLUCOSE, + SUSPEND_AUTO, + SUSPEND_MORE_THAN_MAX_PER_HOUR, + SUSPEND_MORE_THAN_MAX_PER_DAY, + SUSPEND_MANUAL, + STOP_OCCLUSION, + STOP_EXPIRED, + STOP_EMPTY, + STOP_PATCH_FAULT, + STOP_PATCH_FAULT2, + STOP_BASE_FAULT, + STOP_PATCH_BATTERY_EXAUSTED, + STOP_MAG_SENSOR_NO_CALIBRATION, + STOP, + STOP_LOW_BATTERY, + STOP_AUTO_EXIT, + STOP_CANCEL, + STOP_LOW_SUPER_CAPACITOR, + STOP_DISCARD, + PAUSE_INTERRUPT, + AUTO_MODE_EXIT, + AUTO_MODE_EXIT_MIN_DELIVERY_TOO_LONG, + AUTO_MODE_EXIT_NO_GLUCOSE_3_HOUR, + AUTO_MODE_EXIT_MAX_DELIVERY_TOO_LONG; + + fun isSuspendedByPump(): Boolean { + return this in SUSPEND_LOW_GLUCOSE..SUSPEND_MANUAL + } +} \ No newline at end of file diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalType.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalType.kt index f35ff3b4ba..3490f0531f 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalType.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalType.kt @@ -51,4 +51,19 @@ enum class BasalType { fun isSuspendedByPump(): Boolean { return this in SUSPEND_LOW_GLUCOSE..STOP } + + companion object { + + fun fromBasalEndReason(endReason: BasalEndReason): BasalType { + return when (endReason) { + BasalEndReason.SUSPEND_LOW_GLUCOSE -> SUSPEND_LOW_GLUCOSE + BasalEndReason.SUSPEND_PREDICT_LOW_GLUCOSE -> SUSPEND_PREDICT_LOW_GLUCOSE + BasalEndReason.SUSPEND_AUTO -> SUSPEND_AUTO + BasalEndReason.SUSPEND_MORE_THAN_MAX_PER_HOUR -> SUSPEND_MORE_THAN_MAX_PER_HOUR + BasalEndReason.SUSPEND_MORE_THAN_MAX_PER_DAY -> SUSPEND_MORE_THAN_MAX_PER_DAY + BasalEndReason.SUSPEND_MANUAL -> SUSPEND_MANUAL + else -> NONE + } + } + } } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt index 669e512ee9..03d3eb19f2 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt @@ -5,6 +5,7 @@ import info.nightscout.interfaces.pump.DetailedBolusInfoStorage import info.nightscout.interfaces.pump.PumpSync import info.nightscout.interfaces.pump.TemporaryBasalStorage import info.nightscout.pump.medtrum.MedtrumPump +import info.nightscout.pump.medtrum.comm.enums.BasalEndReason import info.nightscout.pump.medtrum.comm.enums.CommandType.GET_RECORD import info.nightscout.pump.medtrum.comm.enums.BasalType import info.nightscout.pump.medtrum.comm.enums.BolusType @@ -15,6 +16,7 @@ import info.nightscout.pump.medtrum.extension.toLong import info.nightscout.pump.medtrum.util.MedtrumTimeUtil import info.nightscout.rx.logging.LTag import info.nightscout.shared.utils.DateUtil +import info.nightscout.shared.utils.T import javax.inject.Inject class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int) : MedtrumPacket(injector) { @@ -74,7 +76,7 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int val recordUnknown = data.copyOfRange(RESP_RECORD_UNKNOWN_START, RESP_RECORD_UNKNOWN_END).toInt() val recordType = data.copyOfRange(RESP_RECORD_TYPE_START, RESP_RECORD_TYPE_END).toInt() val recordSerial = data.copyOfRange(RESP_RECORD_SERIAL_START, RESP_RECORD_SERIAL_END).toLong() - val recordPatchId = data.copyOfRange(RESP_RECORD_PATCH_ID_START, RESP_RECORD_PATCH_ID_END).toInt() + val recordPatchId = data.copyOfRange(RESP_RECORD_PATCH_ID_START, RESP_RECORD_PATCH_ID_END).toLong() val recordSequence = data.copyOfRange(RESP_RECORD_SEQUENCE_START, RESP_RECORD_SEQUENCE_END).toInt() aapsLogger.debug( @@ -82,8 +84,6 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int "GetRecordPacket HandleResponse: Record header: $recordHeader, unknown: $recordUnknown, type: $recordType, serial: $recordSerial, patchId: $recordPatchId, " + "sequence: $recordSequence" ) - medtrumPump.syncedSequenceNumber = recordSequence // Assume sync upwards - if (recordHeader == VALID_HEADER) { when (recordType) { BOLUS_RECORD, BOLUS_RECORD_ALT -> { @@ -95,7 +95,7 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int val bolusNormalAmount = data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 10).toInt() * 0.05 val bolusNormalDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 10, RESP_RECORD_DATA_START + 12).toInt() * 0.05 val bolusExtendedAmount = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 14).toInt() * 0.05 - val bolusExtendedDuration = data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toLong() * 1000 + val bolusExtendedDuration = T.mins(data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toLong()).msecs() val bolusExtendedDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 16, RESP_RECORD_DATA_START + 18).toInt() * 0.05 val bolusCarb = data.copyOfRange(RESP_RECORD_DATA_START + 18, RESP_RECORD_DATA_START + 20).toInt() val bolusGlucose = data.copyOfRange(RESP_RECORD_DATA_START + 20, RESP_RECORD_DATA_START + 22).toInt() @@ -213,7 +213,7 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int val basalStartTime = medtrumTimeUtil.convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 4).toLong()) val basalEndTime = medtrumTimeUtil.convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 8).toLong()) val basalType = enumValues()[data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 9).toInt()] - val basalEndReason = data.copyOfRange(RESP_RECORD_DATA_START + 9, RESP_RECORD_DATA_START + 10).toInt() + val basalEndReason = enumValues()[data.copyOfRange(RESP_RECORD_DATA_START + 9, RESP_RECORD_DATA_START + 10).toInt()] val basalRate = data.copyOfRange(RESP_RECORD_DATA_START + 10, RESP_RECORD_DATA_START + 12).toInt() * 0.05 val basalDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 14).toInt() * 0.05 val basalPercent = data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toInt() @@ -230,7 +230,7 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int } BasalType.ABSOLUTE_TEMP, BasalType.RELATIVE_TEMP -> { - aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Absolute temp basal") + aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: temp basal") var duration = (basalEndTime - basalStartTime) // Work around for pumpSync not accepting 0 duration. // sometimes we get 0 duration for very short basal because the pump only reports time in seconds @@ -255,6 +255,7 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int in BasalType.SUSPEND_LOW_GLUCOSE..BasalType.STOP -> { aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Suspend basal") + // Never seen a packet like this from a pump, even when suspended by app, but leave it in just in case val duration = (basalEndTime - basalStartTime) val newRecord = pumpSync.syncTemporaryBasalWithPumpId( timestamp = basalEndTime, @@ -277,6 +278,13 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Unknown basal type: $basalType") } } + + if (basalEndReason.isSuspendedByPump()) { + // Pump doesn't seem to sync suspend explicitly, so we need to do it here + // Sync suspend using handleBasalStatusUpdate to make sure other variables are updated as well + aapsLogger.warn(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: Got suspended end reason, syncing suspend") + medtrumPump.handleBasalStatusUpdate(BasalType.fromBasalEndReason(basalEndReason), 0.0, recordSequence, recordPatchId, basalEndTime) + } } ALARM_RECORD -> { @@ -355,6 +363,9 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int } else { aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: Invalid record header") } + + // Update sequence number + medtrumPump.syncedSequenceNumber = recordSequence // Assume sync upwards } return success From 7627fcce7db62bda10d46211a9d50921259bd660 Mon Sep 17 00:00:00 2001 From: jbr7rr <> Date: Sun, 17 Sep 2023 17:59:59 +0200 Subject: [PATCH 2/4] Medtrum: Allow reset of all suspended states --- .../pump/medtrum/comm/enums/MedtrumPumpState.kt | 4 ++++ .../nightscout/pump/medtrum/services/MedtrumService.kt | 9 ++------- .../medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt | 4 +--- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/MedtrumPumpState.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/MedtrumPumpState.kt index c17caa6ad9..99451d4cc1 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/MedtrumPumpState.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/MedtrumPumpState.kt @@ -27,6 +27,10 @@ enum class MedtrumPumpState(val state: Byte) { NO_CALIBRATION(103), STOPPED(128.toByte()); + fun isSuspendedByPump(): Boolean { + return this in LOW_BG_SUSPENDED..SUSPENDED + } + companion object { fun fromByte(state: Byte) = values().find { it.state == state } 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 7581b8fa9c..569ed1b587 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 @@ -281,13 +281,8 @@ class MedtrumService : DaggerService(), BLECommCallback { } fun clearAlarms(): Boolean { - var result = true - if (medtrumPump.pumpState in listOf( - MedtrumPumpState.PAUSED, - MedtrumPumpState.HOURLY_MAX_SUSPENDED, - MedtrumPumpState.DAILY_MAX_SUSPENDED - ) - ) { + var result = loadEvents() // Make sure we have all events before clearing alarms + if (result && medtrumPump.pumpState.isSuspendedByPump()) { when (medtrumPump.pumpState) { MedtrumPumpState.HOURLY_MAX_SUSPENDED -> { result = sendPacketAndGetResponse(ClearPumpAlarmPacket(injector, ALARM_HOURLY_MAX_CLEAR_CODE)) diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt index a3c6e15620..13392125bf 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/ui/viewmodel/MedtrumOverviewViewModel.kt @@ -119,9 +119,7 @@ class MedtrumOverviewViewModel @Inject constructor( medtrumPump.pumpStateFlow.collect { state -> aapsLogger.debug(LTag.PUMP, "MedtrumViewModel pumpStateFlow: $state") _canDoResetAlarms.postValue( - medtrumPump.pumpState in listOf( - MedtrumPumpState.PAUSED, MedtrumPumpState.HOURLY_MAX_SUSPENDED, MedtrumPumpState.DAILY_MAX_SUSPENDED - ) + medtrumPump.pumpState.isSuspendedByPump() ) updateGUI() From 5074195315927cd5fd7947587044c096738a773b Mon Sep 17 00:00:00 2001 From: jbr7rr <> Date: Sun, 17 Sep 2023 19:38:13 +0200 Subject: [PATCH 3/4] Medtrum: Add more tests to GetRecordPacketTest --- .../pump/medtrum/comm/enums/BasalEndReason.kt | 2 +- .../medtrum/comm/packets/GetRecordPacket.kt | 2 +- .../comm/packets/GetRecordPacketTest.kt | 304 ++++++++++++++++++ 3 files changed, 306 insertions(+), 2 deletions(-) diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt index 70594a49ba..632f49608e 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/enums/BasalEndReason.kt @@ -31,4 +31,4 @@ enum class BasalEndReason { fun isSuspendedByPump(): Boolean { return this in SUSPEND_LOW_GLUCOSE..SUSPEND_MANUAL } -} \ No newline at end of file +} diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt index 03d3eb19f2..0f375b056f 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt @@ -258,7 +258,7 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int // Never seen a packet like this from a pump, even when suspended by app, but leave it in just in case val duration = (basalEndTime - basalStartTime) val newRecord = pumpSync.syncTemporaryBasalWithPumpId( - timestamp = basalEndTime, + timestamp = basalStartTime, rate = 0.0, duration = duration, isAbsolute = true, diff --git a/pump/medtrum/src/test/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacketTest.kt b/pump/medtrum/src/test/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacketTest.kt index 1e69dff73b..ab2d3dd871 100644 --- a/pump/medtrum/src/test/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacketTest.kt +++ b/pump/medtrum/src/test/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacketTest.kt @@ -2,19 +2,31 @@ package info.nightscout.pump.medtrum.comm.packets import dagger.android.AndroidInjector import dagger.android.HasAndroidInjector +import info.nightscout.interfaces.pump.DetailedBolusInfo +import info.nightscout.interfaces.pump.DetailedBolusInfoStorage +import info.nightscout.interfaces.pump.PumpSync import info.nightscout.pump.medtrum.MedtrumTestBase +import info.nightscout.shared.utils.T import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.Test +import org.mockito.Mock +import org.mockito.Mockito +import org.mockito.Mockito.mock class GetRecordPacketTest : MedtrumTestBase() { /** Test packet specific behavior */ + @Mock private lateinit var detailedBolusInfoStorage: DetailedBolusInfoStorage + private val packetInjector = HasAndroidInjector { AndroidInjector { if (it is GetRecordPacket) { it.aapsLogger = aapsLogger it.medtrumPump = medtrumPump + it.pumpSync = pumpSync + it.detailedBolusInfoStorage = detailedBolusInfoStorage + it.dateUtil = dateUtil } } } @@ -58,4 +70,296 @@ class GetRecordPacketTest : MedtrumTestBase() { Assertions.assertEquals(false, result) Assertions.assertEquals(true, packet.failed) } + + @Test fun handleResponseGivenBolusRecordWhenAndDetailedBolusInfoPresentThenExpectPumpSyncWithTempId() { + val data = byteArrayOf(47, 99, 10, 1, 0, 0, -86, 40, 1, -1, 38, 105, -77, 57, 56, 0, 29, 0, 1, 0, 0, 0, -82, -85, 62, 18, 22, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76) + + val timestamp = 1694631470000L + val bolusType = DetailedBolusInfo.BolusType.SMB + val amount = 1.1 + + // Mocks + val detailedBolusInfo: DetailedBolusInfo = mock(DetailedBolusInfo::class.java) + detailedBolusInfo.timestamp = timestamp // Wierd way to mock but this is a @JvmField + Mockito.`when`(detailedBolusInfo.bolusType).thenReturn(bolusType) + + Mockito.`when`(detailedBolusInfoStorage.findDetailedBolusInfo(timestamp, amount)).thenReturn(detailedBolusInfo) + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncBolusWithTempId( + timestamp = timestamp, + amount = amount, + temporaryId = timestamp, + type = bolusType, + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + Assertions.assertEquals(timestamp, medtrumPump.lastBolusTime) + Assertions.assertEquals(amount, medtrumPump.lastBolusAmount, 0.01) + } + + @Test fun handleResponseGivenBolusRecordWhenAndNoDetailedBolusInfoPresentThenExpectPumpSyncWithPumpId() { + val data = byteArrayOf(47, 99, 10, 1, 0, 0, -86, 40, 1, -1, 38, 105, -77, 57, 56, 0, 29, 0, 1, 0, 0, 0, -82, -85, 62, 18, 22, 0, 22, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76) + + val timestamp = 1694631470000L + val amount = 1.1 + + // Mocks + Mockito.`when`(detailedBolusInfoStorage.findDetailedBolusInfo(timestamp, amount)).thenReturn(null) + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncBolusWithPumpId( + timestamp = timestamp, + amount = amount, + type = null, + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + Assertions.assertEquals(timestamp, medtrumPump.lastBolusTime) + Assertions.assertEquals(amount, medtrumPump.lastBolusAmount, 0.01) + } + + @Test fun handleResponseGivenExtendedBolusRecordThenExpectPumpSyncWithPumpId() { + val data = byteArrayOf(47, 99, 5, 1, 0, 0, -86, 40, 1, -1, 38, 105, -77, 57, 63, 0, 6, 0, 2, 0, 0, 0, -22, -123, 67, 18, 0, 0, 0, 0, 25, 0, 30, 0, 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -124) + + val timestamp = 1694949482000 + val amount = 1.25 + val duration = T.mins(30).msecs() + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncExtendedBolusWithPumpId( + timestamp = timestamp, + amount = amount, + duration = duration, + isEmulatingTB = false, + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenComboBolusRecordWhenAndNoDetailedBolusInfoPresentThenExpectPumpSyncWithPumpId() { + val data = byteArrayOf(47, 99, 5, 1, 0, 0, -86, 40, 1, -1, 38, 105, -77, 57, 63, 0, 8, 0, 3, 0, 0, 0, 111, -110, 67, 18, 40, 0, 40, 0, 20, 0, 30, 0, 20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -122) + + val timestamp = 1694952687000L + val amountDirect = 2.0 + val amountExtended = 1.0 + val duration = T.mins(30).msecs() + + // Mocks + Mockito.`when`(detailedBolusInfoStorage.findDetailedBolusInfo(timestamp, amountDirect)).thenReturn(null) + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncBolusWithPumpId( + timestamp = timestamp, + amount = amountDirect, + type = null, + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + Mockito.verify(pumpSync).syncExtendedBolusWithPumpId( + timestamp = timestamp, + amount = amountExtended, + duration = duration, + isEmulatingTB = false, + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenBasalRecordWhenAbsoluteTempThenExpectPumpSync() { + val data = byteArrayOf(35, 99, 7, 1, 0, 0, -86, 28, 2, -1, 38, 105, -77, 57, 56, 0, 30, 0, -85, -85, 62, 18, -34, -84, 62, 18, 6, 0, 69, 0, 6, 0, 69, 0, -125) + + val startTime = 1694631467000 + val endTime = 1694631774000 + val rate = 3.45 + val duration = endTime - startTime + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncTemporaryBasalWithPumpId( + timestamp = startTime, + rate = rate, + duration = duration, + isAbsolute = true, + type = PumpSync.TemporaryBasalType.NORMAL, + pumpId = startTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenBasalRecordWhenRelativeTempThenExpectPumpSync() { + val data = byteArrayOf(35, 99, 7, 1, 0, 0, -86, 28, 2, -1, 38, 105, -77, 57, 63, 0, 4, 0, -116, -123, 67, 18, 81, -119, 67, 18, 7, 0, 4, 0, 1, 0, -56, 0, 1) + + val startTime = 1694949388000 + val endTime = 1694950353000 + val rate = 200.0 + val duration = endTime - startTime + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncTemporaryBasalWithPumpId( + timestamp = startTime, + rate = rate, + duration = duration, + isAbsolute = false, + type = PumpSync.TemporaryBasalType.NORMAL, + pumpId = startTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenBasalRecordWhenSuspendThenExpectPumpSync() { + // Note: This is not a real response as I was unable to get this response from any of my pumpbases, but it can theoretically happen + val data = byteArrayOf(35, 99, 7, 1, 0, 0, -86, 28, 2, -1, -39, -7, 118, -86, -85, 1, 8, 0, -4, 116, -16, 17, 21, 125, -16, 17, 18, 0, 0, 0, 0, 0, 0, 0, 125) + val startTime = 1689505660000 + val endTime = 1689507733000 + val rate = 0.0 + val duration = endTime - startTime + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).syncTemporaryBasalWithPumpId( + timestamp = startTime, + rate = rate, + duration = duration, + isAbsolute = true, + type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, + pumpId = startTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenBasalRecordWhenStandardAndSuspendEndReasonThenExpectPumpSync() { + val data = byteArrayOf(35, 99, 8, 1, 0, 0, -86, 28, 2, -1, -39, -7, 118, -86, -85, 1, 4, 0, -117, 113, -16, 17, 9, 116, -16, 17, 1, 4, 10, 0, 2, 0, 0, 0, 57) + val endTime = 1689505417000 + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Just check the pumpSync here, rest of the behavoir of medtrumPump is tested in MedtrumPumpTest + // Expected values + Mockito.verify(pumpSync).syncTemporaryBasalWithPumpId( + timestamp = endTime, + rate = 0.0, + duration = T.mins(4800L).msecs(), + isAbsolute = true, + type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, + pumpId = endTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenBasalRecordWhenTempAndSuspendEndReasonThenExpectPumpSync() { + val data = byteArrayOf(35, 99, 8, 1, 0, 0, -86, 28, 2, -1, -39, -7, 118, -86, -82, 1, 5, 0, 75, 24, -14, 17, 44, 27, -14, 17, 6, 4, 16, 0, 3, 0, 16, 0, -73) + val endTime = 1689613740000 + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Just check the pumpSync here, rest of the behavoir of medtrumPump is tested in MedtrumPumpTest + // Expected values + Mockito.verify(pumpSync).syncTemporaryBasalWithPumpId( + timestamp = endTime, + rate = 0.0, + duration = T.mins(4800L).msecs(), + isAbsolute = true, + type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, + pumpId = endTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } + + @Test fun handleResponseGivenTDDRecordThenExpectPumpSync() { + val data = byteArrayOf( + 87, 99, 8, 1, 0, 0, -86, 80, 9, -1, 38, 105, -77, 57, 56, 0, 82, 0, -32, -124, 61, 18, 120, 0, -120, 5, 0, 0, 0, 0, -102, -103, 84, 66, 0, 0, + -120, 65, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 102, -26, -128, 66, 58, -52, -75, 63, 0, 0, -16, 66, -49, -9, -13, 63, -103, -103, 121, 66, 55, + -75, -84, 63, 0, 0, -16, 66, -49, -9, -13, 63, 0, 0, 0, 0, -128 + ) + val timestamp = 1694556000000L + val tdd = 53.150001525878906 + val basalTdd = 17.0 + val bolusTdd = tdd - basalTdd + + // Call + val packet = GetRecordPacket(packetInjector, 0) + val result = packet.handleResponse(data) + + // Expected values + Mockito.verify(pumpSync).createOrUpdateTotalDailyDose( + timestamp = timestamp, + bolusAmount = bolusTdd, + basalAmount = basalTdd, + totalAmount = tdd, + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + Assertions.assertEquals(true, result) + Assertions.assertEquals(false, packet.failed) + } } From ae5c4ddeeb49763af17c24b8351708210544b825 Mon Sep 17 00:00:00 2001 From: jbr7rr <> Date: Sun, 17 Sep 2023 20:22:13 +0200 Subject: [PATCH 4/4] Medtrum: Lints --- .../nightscout/pump/medtrum/MedtrumPlugin.kt | 30 +- .../nightscout/pump/medtrum/MedtrumPump.kt | 12 +- .../medtrum/comm/packets/GetRecordPacket.kt | 491 +++++++++--------- .../comm/packets/NotificationPacket.kt | 1 - 4 files changed, 271 insertions(+), 263 deletions(-) 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 ed0cff7dcf..efcda22669 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 @@ -255,7 +255,11 @@ import kotlin.math.abs override fun isConnected(): Boolean { // This is a workaround to prevent AAPS to trigger connects when we have no patch activated - return if (!isInitialized()) true else medtrumService?.isConnected ?: false + return if (!isInitialized()) { + true + } else { + medtrumService?.isConnected ?: false + } } override fun isConnecting(): Boolean = medtrumService?.isConnecting ?: false @@ -544,31 +548,19 @@ import kotlin.math.abs // Medtrum interface override fun loadEvents(): PumpEnactResult { - if (!isInitialized()) { - val result = PumpEnactResult(injector).success(false) - result.comment = "pump not initialized" - return result - } + if (!isInitialized()) return PumpEnactResult(injector).success(false).enacted(false) val connectionOK = medtrumService?.loadEvents() ?: false return PumpEnactResult(injector).success(connectionOK) } override fun setUserOptions(): PumpEnactResult { - if (!isInitialized()) { - val result = PumpEnactResult(injector).success(false) - result.comment = "pump not initialized" - return result - } + if (!isInitialized()) return PumpEnactResult(injector).success(false).enacted(false) val connectionOK = medtrumService?.setUserSettings() ?: false return PumpEnactResult(injector).success(connectionOK) } override fun clearAlarms(): PumpEnactResult { - if (!isInitialized()) { - val result = PumpEnactResult(injector).success(false) - result.comment = "pump not initialized" - return result - } + if (!isInitialized()) return PumpEnactResult(injector).success(false).enacted(false) val connectionOK = medtrumService?.clearAlarms() ?: false return PumpEnactResult(injector).success(connectionOK) } @@ -579,11 +571,7 @@ import kotlin.math.abs } override fun updateTime(): PumpEnactResult { - if (!isInitialized()) { - val result = PumpEnactResult(injector).success(false) - result.comment = "pump not initialized" - return result - } + if (!isInitialized()) return PumpEnactResult(injector).success(false).enacted(false) val connectionOK = medtrumService?.updateTimeIfNeeded() ?: false return PumpEnactResult(injector).success(connectionOK) } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPump.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPump.kt index 8480282e6f..ad537792a5 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPump.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/MedtrumPump.kt @@ -315,7 +315,7 @@ class MedtrumPump @Inject constructor( } loadUserSettingsFromSP() - } + } fun loadUserSettingsFromSP() { desiredPatchExpiration = sp.getBoolean(R.string.key_patch_expiration, false) @@ -421,7 +421,7 @@ class MedtrumPump @Inject constructor( ) aapsLogger.debug( LTag.PUMPCOMM, - "handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + "Rate: $basalRate Duration: ${duration} temporaryBasalInfo: $temporaryBasalInfo, expectedTemporaryBasal: $expectedTemporaryBasal" + "handleBasalStatusUpdate: ${newRecordInfo(newRecord)}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + "Rate: $basalRate Duration: ${duration} temporaryBasalInfo: $temporaryBasalInfo, expectedTemporaryBasal: $expectedTemporaryBasal" ) } @@ -438,7 +438,7 @@ class MedtrumPump @Inject constructor( ) aapsLogger.debug( LTag.PUMPCOMM, - "handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) expectedTemporaryBasal: $expectedTemporaryBasal" + "handleBasalStatusUpdate: ${newRecordInfo(newRecord)}EVENT TEMP_START ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) expectedTemporaryBasal: $expectedTemporaryBasal" ) } @@ -507,7 +507,7 @@ class MedtrumPump @Inject constructor( ) aapsLogger.debug( LTag.PUMPCOMM, - "handleBasalStatusUpdate: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_START (FAKE)" + "handleBasalStatusUpdate: ${newRecordInfo(newRecord)}EVENT TEMP_START (FAKE)" ) } @@ -597,4 +597,8 @@ class MedtrumPump @Inject constructor( .let { EnumSet.copyOf(it) } } } + + private fun newRecordInfo(newRecord: Boolean): String { + return "${if (newRecord) "**NEW** " else ""}" + } } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt index 0f375b056f..5aa1f12843 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/GetRecordPacket.kt @@ -87,204 +87,11 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int if (recordHeader == VALID_HEADER) { when (recordType) { BOLUS_RECORD, BOLUS_RECORD_ALT -> { - aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD") - val typeAndWizard = data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 1).toInt() - val bolusCause = data.copyOfRange(RESP_RECORD_DATA_START + 1, RESP_RECORD_DATA_START + 2).toInt() - val unknown = data.copyOfRange(RESP_RECORD_DATA_START + 2, RESP_RECORD_DATA_START + 4).toInt() - val bolusStartTime = MedtrumTimeUtil().convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 8).toLong()) - val bolusNormalAmount = data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 10).toInt() * 0.05 - val bolusNormalDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 10, RESP_RECORD_DATA_START + 12).toInt() * 0.05 - val bolusExtendedAmount = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 14).toInt() * 0.05 - val bolusExtendedDuration = T.mins(data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toLong()).msecs() - val bolusExtendedDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 16, RESP_RECORD_DATA_START + 18).toInt() * 0.05 - val bolusCarb = data.copyOfRange(RESP_RECORD_DATA_START + 18, RESP_RECORD_DATA_START + 20).toInt() - val bolusGlucose = data.copyOfRange(RESP_RECORD_DATA_START + 20, RESP_RECORD_DATA_START + 22).toInt() - val bolusIOB = data.copyOfRange(RESP_RECORD_DATA_START + 22, RESP_RECORD_DATA_START + 24).toInt() - val unknown1 = data.copyOfRange(RESP_RECORD_DATA_START + 24, RESP_RECORD_DATA_START + 26).toInt() - val unknown2 = data.copyOfRange(RESP_RECORD_DATA_START + 26, RESP_RECORD_DATA_START + 28).toInt() - val bolusType = enumValues()[typeAndWizard and 0x0F] - val bolusWizard = (typeAndWizard and 0xF0) != 0 - aapsLogger.debug( - LTag.PUMPCOMM, - "GetRecordPacket HandleResponse: BOLUS_RECORD: typeAndWizard: $typeAndWizard, bolusCause: $bolusCause, unknown: $unknown, bolusStartTime: $bolusStartTime, " + - "bolusNormalAmount: $bolusNormalAmount, bolusNormalDelivered: $bolusNormalDelivered, bolusExtendedAmount: $bolusExtendedAmount, bolusExtendedDuration: " + - "$bolusExtendedDuration, " + "bolusExtendedDelivered: $bolusExtendedDelivered, bolusCarb: $bolusCarb, bolusGlucose: $bolusGlucose, bolusIOB: $bolusIOB, unknown1: $unknown1, unknown2: $unknown2, " + "bolusType: $bolusType, bolusWizard: $bolusWizard" - ) - - when (bolusType) { - BolusType.NORMAL -> { - val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered) - var newRecord = false - if (detailedBolusInfo != null) { - val syncOk = pumpSync.syncBolusWithTempId( - timestamp = bolusStartTime, - amount = bolusNormalDelivered, - temporaryId = detailedBolusInfo.timestamp, - type = detailedBolusInfo.bolusType, - pumpId = bolusStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - if (!syncOk) { - aapsLogger.warn(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD: Failed to sync bolus with tempId: ${detailedBolusInfo.timestamp}") - // detailedInfo can be from another similar record. Reinsert - detailedBolusInfoStorage.add(detailedBolusInfo) - } - } else { - newRecord = pumpSync.syncBolusWithPumpId( - timestamp = bolusStartTime, - amount = bolusNormalDelivered, - type = null, - pumpId = bolusStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - } - - aapsLogger.debug( - LTag.PUMPCOMM, - "from record: ${if (newRecord) "**NEW** " else ""}EVENT BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U " - ) - if (bolusStartTime > medtrumPump.lastBolusTime) { - medtrumPump.lastBolusTime = bolusStartTime - medtrumPump.lastBolusAmount = bolusNormalDelivered - } - } - - BolusType.EXTENDED -> { - val newRecord = pumpSync.syncExtendedBolusWithPumpId( - timestamp = bolusStartTime, - amount = bolusExtendedDelivered, - duration = bolusExtendedDuration, - isEmulatingTB = false, - pumpId = bolusStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - aapsLogger.debug( - LTag.PUMPCOMM, - "from record: ${if (newRecord) "**NEW** " else ""}EVENT EXTENDED BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U " - ) - } - - BolusType.COMBI -> { - // Note, this should never happen, as we don't use combo bolus - val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered) - val newRecord = pumpSync.syncBolusWithPumpId( - timestamp = bolusStartTime, - amount = bolusNormalDelivered, - type = detailedBolusInfo?.bolusType, - pumpId = bolusStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - pumpSync.syncExtendedBolusWithPumpId( - timestamp = bolusStartTime, - amount = bolusExtendedDelivered, - duration = bolusExtendedDuration, - isEmulatingTB = false, - pumpId = bolusStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - aapsLogger.error( - LTag.PUMPCOMM, - "from record: ${if (newRecord) "**NEW** " else ""}EVENT COMBI BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U Extended: ${bolusExtendedDelivered} THIS SHOULD NOT HAPPEN!!!" - ) - if (!newRecord && detailedBolusInfo != null) { - // detailedInfo can be from another similar record. Reinsert - detailedBolusInfoStorage.add(detailedBolusInfo) - } - if (bolusStartTime > medtrumPump.lastBolusTime) { - medtrumPump.lastBolusTime = bolusStartTime - medtrumPump.lastBolusAmount = bolusNormalDelivered - } - } - - else -> { - aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD: Unknown bolus type: $bolusType") - } - } - + handleBolusRecord(data) } BASAL_RECORD, BASAL_RECORD_ALT -> { - val medtrumTimeUtil = MedtrumTimeUtil() - val basalStartTime = medtrumTimeUtil.convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 4).toLong()) - val basalEndTime = medtrumTimeUtil.convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 8).toLong()) - val basalType = enumValues()[data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 9).toInt()] - val basalEndReason = enumValues()[data.copyOfRange(RESP_RECORD_DATA_START + 9, RESP_RECORD_DATA_START + 10).toInt()] - val basalRate = data.copyOfRange(RESP_RECORD_DATA_START + 10, RESP_RECORD_DATA_START + 12).toInt() * 0.05 - val basalDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 14).toInt() * 0.05 - val basalPercent = data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toInt() - - aapsLogger.debug( - LTag.PUMPCOMM, - "GetRecordPacket HandleResponse: BASAL_RECORD: Start: $basalStartTime, End: $basalEndTime, Type: $basalType, EndReason: $basalEndReason, Rate: $basalRate, Delivered: $basalDelivered, Percent: $basalPercent" - ) - - when (basalType) { - BasalType.STANDARD -> { - aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Standard basal") - // If we are here it means the basal has ended - } - - BasalType.ABSOLUTE_TEMP, BasalType.RELATIVE_TEMP -> { - aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: temp basal") - var duration = (basalEndTime - basalStartTime) - // Work around for pumpSync not accepting 0 duration. - // sometimes we get 0 duration for very short basal because the pump only reports time in seconds - if (duration < 250) duration = 250 // 250ms to make sure AAPS accepts it - - val newRecord = pumpSync.syncTemporaryBasalWithPumpId( - timestamp = basalStartTime, - rate = if (basalType == BasalType.ABSOLUTE_TEMP) basalRate else basalPercent.toDouble(), - duration = duration, - isAbsolute = (basalType == BasalType.ABSOLUTE_TEMP), - type = PumpSync.TemporaryBasalType.NORMAL, - pumpId = basalStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - aapsLogger.debug( - LTag.PUMPCOMM, - "handleBasalStatusUpdate from record: ${if (newRecord) "**NEW** " else ""}EVENT TEMP_SYNC: ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + - "Rate: $basalRate Duration: ${duration}" - ) - } - - in BasalType.SUSPEND_LOW_GLUCOSE..BasalType.STOP -> { - aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Suspend basal") - // Never seen a packet like this from a pump, even when suspended by app, but leave it in just in case - val duration = (basalEndTime - basalStartTime) - val newRecord = pumpSync.syncTemporaryBasalWithPumpId( - timestamp = basalStartTime, - rate = 0.0, - duration = duration, - isAbsolute = true, - type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, - pumpId = basalStartTime, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - aapsLogger.debug( - LTag.PUMPCOMM, - "handleBasalStatusUpdate from record: ${if (newRecord) "**NEW** " else ""}EVENT SUSPEND: ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + - "Rate: $basalRate Duration: ${duration}" - ) - } - - else -> { - aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Unknown basal type: $basalType") - } - } - - if (basalEndReason.isSuspendedByPump()) { - // Pump doesn't seem to sync suspend explicitly, so we need to do it here - // Sync suspend using handleBasalStatusUpdate to make sure other variables are updated as well - aapsLogger.warn(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: Got suspended end reason, syncing suspend") - medtrumPump.handleBasalStatusUpdate(BasalType.fromBasalEndReason(basalEndReason), 0.0, recordSequence, recordPatchId, basalEndTime) - } + handleBasalRecord(data) } ALARM_RECORD -> { @@ -312,54 +119,13 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int } TDD_RECORD -> { - aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: TDD_RECORD") - val timestamp = MedtrumTimeUtil().convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 4).toLong()) - val timeZoneOffset = data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 6).toInt() - val tddMinutes = data.copyOfRange(RESP_RECORD_DATA_START + 6, RESP_RECORD_DATA_START + 8).toInt() - val glucoseRecordTime = data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 12).toLong() - val tdd = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 16).toFloat() - val basalTdd = data.copyOfRange(RESP_RECORD_DATA_START + 16, RESP_RECORD_DATA_START + 20).toFloat() - val glucose = data.copyOfRange(RESP_RECORD_DATA_START + 20, RESP_RECORD_DATA_START + 24).toFloat() - val unknown = data.copyOfRange(RESP_RECORD_DATA_START + 24, RESP_RECORD_DATA_START + 28).toFloat() - val meanSomething = data.copyOfRange(RESP_RECORD_DATA_START + 28, RESP_RECORD_DATA_START + 32).toFloat() - val usedTdd = data.copyOfRange(RESP_RECORD_DATA_START + 32, RESP_RECORD_DATA_START + 36).toFloat() - val usedIBasal = data.copyOfRange(RESP_RECORD_DATA_START + 36, RESP_RECORD_DATA_START + 40).toFloat() - val usedSgBasal = data.copyOfRange(RESP_RECORD_DATA_START + 40, RESP_RECORD_DATA_START + 44).toFloat() - val usedUMax = data.copyOfRange(RESP_RECORD_DATA_START + 44, RESP_RECORD_DATA_START + 48).toFloat() - val newTdd = data.copyOfRange(RESP_RECORD_DATA_START + 48, RESP_RECORD_DATA_START + 52).toFloat() - val newIBasal = data.copyOfRange(RESP_RECORD_DATA_START + 52, RESP_RECORD_DATA_START + 56).toFloat() - val newSgBasal = data.copyOfRange(RESP_RECORD_DATA_START + 56, RESP_RECORD_DATA_START + 60).toFloat() - val newUMax = data.copyOfRange(RESP_RECORD_DATA_START + 60, RESP_RECORD_DATA_START + 64).toFloat() - - aapsLogger.debug( - LTag.PUMPCOMM, "TDD_RECORD: timestamp: $timestamp, timeZoneOffset: $timeZoneOffset, tddMinutes: $tddMinutes, glucoseRecordTime: $glucoseRecordTime, tdd: " + - "$tdd, basalTdd: $basalTdd, glucose: $glucose, unknown: $unknown, meanSomething: $meanSomething, usedTdd: $usedTdd, usedIBasal: $usedIBasal, usedSgBasal: " + - "$usedSgBasal, usedUMax: $usedUMax, newTdd: $newTdd, newIBasal: $newIBasal, newSgBasal: $newSgBasal, newUMax: $newUMax" - ) - - val newRecord = pumpSync.createOrUpdateTotalDailyDose( - timestamp = timestamp, - bolusAmount = (tdd - basalTdd).toDouble(), - basalAmount = basalTdd.toDouble(), - totalAmount = tdd.toDouble(), - pumpId = timestamp, - pumpType = medtrumPump.pumpType(), - pumpSerial = medtrumPump.pumpSN.toString(radix = 16) - ) - - aapsLogger.debug( - LTag.PUMPCOMM, - "handleBasalStatusUpdate from record: ${if (newRecord) "**NEW** " else ""}EVENT TDD: ${dateUtil.dateAndTimeString(timestamp)} ($timestamp) " + - "TDD: $tdd, BasalTDD: $basalTdd, BolusTDD: ${tdd - basalTdd}" - ) - + handleTddRecord(data) } else -> { aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: Unknown record type: $recordType") } } - } else { aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: Invalid record header") } @@ -370,4 +136,255 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int return success } + + private fun handleBolusRecord(data: ByteArray) { + aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD") + val typeAndWizard = data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 1).toInt() + val bolusCause = data.copyOfRange(RESP_RECORD_DATA_START + 1, RESP_RECORD_DATA_START + 2).toInt() + val unknown = data.copyOfRange(RESP_RECORD_DATA_START + 2, RESP_RECORD_DATA_START + 4).toInt() + val bolusStartTime = MedtrumTimeUtil().convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 8).toLong()) + val bolusNormalAmount = data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 10).toInt() * 0.05 + val bolusNormalDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 10, RESP_RECORD_DATA_START + 12).toInt() * 0.05 + val bolusExtendedAmount = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 14).toInt() * 0.05 + val bolusExtendedDuration = T.mins(data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toLong()).msecs() + val bolusExtendedDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 16, RESP_RECORD_DATA_START + 18).toInt() * 0.05 + val bolusCarb = data.copyOfRange(RESP_RECORD_DATA_START + 18, RESP_RECORD_DATA_START + 20).toInt() + val bolusGlucose = data.copyOfRange(RESP_RECORD_DATA_START + 20, RESP_RECORD_DATA_START + 22).toInt() + val bolusIOB = data.copyOfRange(RESP_RECORD_DATA_START + 22, RESP_RECORD_DATA_START + 24).toInt() + val unknown1 = data.copyOfRange(RESP_RECORD_DATA_START + 24, RESP_RECORD_DATA_START + 26).toInt() + val unknown2 = data.copyOfRange(RESP_RECORD_DATA_START + 26, RESP_RECORD_DATA_START + 28).toInt() + val bolusType = enumValues()[typeAndWizard and 0x0F] + val bolusWizard = (typeAndWizard and 0xF0) != 0 + aapsLogger.debug( + LTag.PUMPCOMM, + "GetRecordPacket HandleResponse: BOLUS_RECORD: typeAndWizard: $typeAndWizard, bolusCause: $bolusCause, unknown: $unknown, bolusStartTime: $bolusStartTime, " + + "bolusNormalAmount: $bolusNormalAmount, bolusNormalDelivered: $bolusNormalDelivered, bolusExtendedAmount: $bolusExtendedAmount, bolusExtendedDuration: " + + "$bolusExtendedDuration, " + "bolusExtendedDelivered: $bolusExtendedDelivered, bolusCarb: $bolusCarb, bolusGlucose: $bolusGlucose, bolusIOB: $bolusIOB, unknown1: $unknown1, unknown2: $unknown2, " + "bolusType: $bolusType, bolusWizard: $bolusWizard" + ) + + when (bolusType) { + BolusType.NORMAL -> { + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered) + var newRecord = false + if (detailedBolusInfo != null) { + val syncOk = pumpSync.syncBolusWithTempId( + timestamp = bolusStartTime, + amount = bolusNormalDelivered, + temporaryId = detailedBolusInfo.timestamp, + type = detailedBolusInfo.bolusType, + pumpId = bolusStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + if (!syncOk) { + aapsLogger.warn(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD: Failed to sync bolus with tempId: ${detailedBolusInfo.timestamp}") + // detailedInfo can be from another similar record. Reinsert + detailedBolusInfoStorage.add(detailedBolusInfo) + } + } else { + newRecord = pumpSync.syncBolusWithPumpId( + timestamp = bolusStartTime, + amount = bolusNormalDelivered, + type = null, + pumpId = bolusStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + } + + aapsLogger.debug( + LTag.PUMPCOMM, + "from record: ${newRecordInfo(newRecord)}EVENT BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U " + ) + if (bolusStartTime > medtrumPump.lastBolusTime) { + medtrumPump.lastBolusTime = bolusStartTime + medtrumPump.lastBolusAmount = bolusNormalDelivered + } + } + + BolusType.EXTENDED -> { + val newRecord = pumpSync.syncExtendedBolusWithPumpId( + timestamp = bolusStartTime, + amount = bolusExtendedDelivered, + duration = bolusExtendedDuration, + isEmulatingTB = false, + pumpId = bolusStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + aapsLogger.debug( + LTag.PUMPCOMM, + "from record: ${newRecordInfo(newRecord)}EVENT EXTENDED BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U " + ) + } + + BolusType.COMBI -> { + // Note, this should never happen, as we don't use combo bolus + val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered) + val newRecord = pumpSync.syncBolusWithPumpId( + timestamp = bolusStartTime, + amount = bolusNormalDelivered, + type = detailedBolusInfo?.bolusType, + pumpId = bolusStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + pumpSync.syncExtendedBolusWithPumpId( + timestamp = bolusStartTime, + amount = bolusExtendedDelivered, + duration = bolusExtendedDuration, + isEmulatingTB = false, + pumpId = bolusStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + aapsLogger.error( + LTag.PUMPCOMM, + "from record: ${newRecordInfo(newRecord)}EVENT COMBI BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U Extended: ${bolusExtendedDelivered} THIS SHOULD NOT HAPPEN!!!" + ) + if (!newRecord && detailedBolusInfo != null) { + // detailedInfo can be from another similar record. Reinsert + detailedBolusInfoStorage.add(detailedBolusInfo) + } + if (bolusStartTime > medtrumPump.lastBolusTime) { + medtrumPump.lastBolusTime = bolusStartTime + medtrumPump.lastBolusAmount = bolusNormalDelivered + } + } + + else -> { + aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD: Unknown bolus type: $bolusType") + } + } + } + + private fun handleBasalRecord(data: ByteArray) { + val medtrumTimeUtil = MedtrumTimeUtil() + + val recordPatchId = data.copyOfRange(RESP_RECORD_PATCH_ID_START, RESP_RECORD_PATCH_ID_END).toLong() + val recordSequence = data.copyOfRange(RESP_RECORD_SEQUENCE_START, RESP_RECORD_SEQUENCE_END).toInt() + + val basalStartTime = medtrumTimeUtil.convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 4).toLong()) + val basalEndTime = medtrumTimeUtil.convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 8).toLong()) + val basalType = enumValues()[data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 9).toInt()] + val basalEndReason = enumValues()[data.copyOfRange(RESP_RECORD_DATA_START + 9, RESP_RECORD_DATA_START + 10).toInt()] + val basalRate = data.copyOfRange(RESP_RECORD_DATA_START + 10, RESP_RECORD_DATA_START + 12).toInt() * 0.05 + val basalDelivered = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 14).toInt() * 0.05 + val basalPercent = data.copyOfRange(RESP_RECORD_DATA_START + 14, RESP_RECORD_DATA_START + 16).toInt() + + aapsLogger.debug( + LTag.PUMPCOMM, + "GetRecordPacket HandleResponse: BASAL_RECORD: Start: $basalStartTime, End: $basalEndTime, Type: $basalType, EndReason: $basalEndReason, Rate: $basalRate, Delivered: $basalDelivered, Percent: $basalPercent" + ) + + when (basalType) { + BasalType.STANDARD -> { + aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Standard basal") + // If we are here it means the basal has ended + } + + BasalType.ABSOLUTE_TEMP, BasalType.RELATIVE_TEMP -> { + aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: temp basal") + var duration = (basalEndTime - basalStartTime) + // Work around for pumpSync not accepting 0 duration. + // sometimes we get 0 duration for very short basal because the pump only reports time in seconds + if (duration < 250) duration = 250 // 250ms to make sure AAPS accepts it + + val newRecord = pumpSync.syncTemporaryBasalWithPumpId( + timestamp = basalStartTime, + rate = if (basalType == BasalType.ABSOLUTE_TEMP) basalRate else basalPercent.toDouble(), + duration = duration, + isAbsolute = (basalType == BasalType.ABSOLUTE_TEMP), + type = PumpSync.TemporaryBasalType.NORMAL, + pumpId = basalStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + aapsLogger.debug( + LTag.PUMPCOMM, + "handleBasalStatusUpdate from record: ${newRecordInfo(newRecord)}EVENT TEMP_SYNC: ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + + "Rate: $basalRate Duration: ${duration}" + ) + } + + in BasalType.SUSPEND_LOW_GLUCOSE..BasalType.STOP -> { + aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Suspend basal") + // Never seen a packet like this from a pump, even when suspended by app, but leave it in just in case + val duration = (basalEndTime - basalStartTime) + val newRecord = pumpSync.syncTemporaryBasalWithPumpId( + timestamp = basalStartTime, + rate = 0.0, + duration = duration, + isAbsolute = true, + type = PumpSync.TemporaryBasalType.PUMP_SUSPEND, + pumpId = basalStartTime, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + aapsLogger.debug( + LTag.PUMPCOMM, + "handleBasalStatusUpdate from record: ${newRecordInfo(newRecord)}EVENT SUSPEND: ($basalType) ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) " + + "Rate: $basalRate Duration: ${duration}" + ) + } + + else -> { + aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BASAL_RECORD: Unknown basal type: $basalType") + } + } + + if (basalEndReason.isSuspendedByPump()) { + // Pump doesn't seem to sync suspend explicitly, so we need to do it here + // Sync suspend using handleBasalStatusUpdate to make sure other variables are updated as well + aapsLogger.warn(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: Got suspended end reason, syncing suspend") + medtrumPump.handleBasalStatusUpdate(BasalType.fromBasalEndReason(basalEndReason), 0.0, recordSequence, recordPatchId, basalEndTime) + } + } + + private fun handleTddRecord(data: ByteArray) { + aapsLogger.debug(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: TDD_RECORD") + val timestamp = MedtrumTimeUtil().convertPumpTimeToSystemTimeMillis(data.copyOfRange(RESP_RECORD_DATA_START, RESP_RECORD_DATA_START + 4).toLong()) + val timeZoneOffset = data.copyOfRange(RESP_RECORD_DATA_START + 4, RESP_RECORD_DATA_START + 6).toInt() + val tddMinutes = data.copyOfRange(RESP_RECORD_DATA_START + 6, RESP_RECORD_DATA_START + 8).toInt() + val glucoseRecordTime = data.copyOfRange(RESP_RECORD_DATA_START + 8, RESP_RECORD_DATA_START + 12).toLong() + val tdd = data.copyOfRange(RESP_RECORD_DATA_START + 12, RESP_RECORD_DATA_START + 16).toFloat() + val basalTdd = data.copyOfRange(RESP_RECORD_DATA_START + 16, RESP_RECORD_DATA_START + 20).toFloat() + val glucose = data.copyOfRange(RESP_RECORD_DATA_START + 20, RESP_RECORD_DATA_START + 24).toFloat() + val unknown = data.copyOfRange(RESP_RECORD_DATA_START + 24, RESP_RECORD_DATA_START + 28).toFloat() + val meanSomething = data.copyOfRange(RESP_RECORD_DATA_START + 28, RESP_RECORD_DATA_START + 32).toFloat() + val usedTdd = data.copyOfRange(RESP_RECORD_DATA_START + 32, RESP_RECORD_DATA_START + 36).toFloat() + val usedIBasal = data.copyOfRange(RESP_RECORD_DATA_START + 36, RESP_RECORD_DATA_START + 40).toFloat() + val usedSgBasal = data.copyOfRange(RESP_RECORD_DATA_START + 40, RESP_RECORD_DATA_START + 44).toFloat() + val usedUMax = data.copyOfRange(RESP_RECORD_DATA_START + 44, RESP_RECORD_DATA_START + 48).toFloat() + val newTdd = data.copyOfRange(RESP_RECORD_DATA_START + 48, RESP_RECORD_DATA_START + 52).toFloat() + val newIBasal = data.copyOfRange(RESP_RECORD_DATA_START + 52, RESP_RECORD_DATA_START + 56).toFloat() + val newSgBasal = data.copyOfRange(RESP_RECORD_DATA_START + 56, RESP_RECORD_DATA_START + 60).toFloat() + val newUMax = data.copyOfRange(RESP_RECORD_DATA_START + 60, RESP_RECORD_DATA_START + 64).toFloat() + + aapsLogger.debug( + LTag.PUMPCOMM, "TDD_RECORD: timestamp: $timestamp, timeZoneOffset: $timeZoneOffset, tddMinutes: $tddMinutes, glucoseRecordTime: $glucoseRecordTime, tdd: " + + "$tdd, basalTdd: $basalTdd, glucose: $glucose, unknown: $unknown, meanSomething: $meanSomething, usedTdd: $usedTdd, usedIBasal: $usedIBasal, usedSgBasal: " + + "$usedSgBasal, usedUMax: $usedUMax, newTdd: $newTdd, newIBasal: $newIBasal, newSgBasal: $newSgBasal, newUMax: $newUMax" + ) + + val newRecord = pumpSync.createOrUpdateTotalDailyDose( + timestamp = timestamp, + bolusAmount = (tdd - basalTdd).toDouble(), + basalAmount = basalTdd.toDouble(), + totalAmount = tdd.toDouble(), + pumpId = timestamp, + pumpType = medtrumPump.pumpType(), + pumpSerial = medtrumPump.pumpSN.toString(radix = 16) + ) + + aapsLogger.debug( + LTag.PUMPCOMM, + "handleBasalStatusUpdate from record: ${newRecordInfo(newRecord)}EVENT TDD: ${dateUtil.dateAndTimeString(timestamp)} ($timestamp) " + + "TDD: $tdd, BasalTDD: $basalTdd, BolusTDD: ${tdd - basalTdd}" + ) + } + + private fun newRecordInfo(newRecord: Boolean): String { + return "${if (newRecord) "**NEW** " else ""}" + } } diff --git a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/NotificationPacket.kt b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/NotificationPacket.kt index 0657319396..f867adce1a 100644 --- a/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/NotificationPacket.kt +++ b/pump/medtrum/src/main/java/info/nightscout/pump/medtrum/comm/packets/NotificationPacket.kt @@ -109,7 +109,6 @@ class NotificationPacket(val injector: HasAndroidInjector) { if (fieldMask and MASK_EXTENDED_BOLUS != 0) { aapsLogger.error(LTag.PUMPCOMM, "Extended bolus notification received, extended bolus not supported!") - // TODO Handle error and stop pump if this happens? offset += 3 }