Medtrum: Fix tests, lints

This commit is contained in:
jbr7rr 2023-08-31 13:42:44 +02:00
parent b87f41a363
commit 3fae634cd1
9 changed files with 725 additions and 184 deletions

View file

@ -97,6 +97,7 @@ class UserEntryPresentationHelperImpl @Inject constructor(
Sources.OmnipodEros -> R.drawable.ic_patch_pump_outline Sources.OmnipodEros -> R.drawable.ic_patch_pump_outline
Sources.OmnipodDash -> R.drawable.ic_patch_pump_outline Sources.OmnipodDash -> R.drawable.ic_patch_pump_outline
Sources.EOPatch2 -> info.nightscout.core.ui.R.drawable.ic_eopatch2_128 Sources.EOPatch2 -> info.nightscout.core.ui.R.drawable.ic_eopatch2_128
Sources.Medtrum -> info.nightscout.core.ui.R.drawable.ic_medtrum_128
Sources.MDI -> R.drawable.ic_ict Sources.MDI -> R.drawable.ic_ict
Sources.VirtualPump -> R.drawable.ic_virtual_pump Sources.VirtualPump -> R.drawable.ic_virtual_pump
Sources.SMS -> R.drawable.ic_sms Sources.SMS -> R.drawable.ic_sms

View file

@ -192,9 +192,7 @@ import kotlin.math.abs
} }
else -> { else -> {
// Use Nano settings for unknown pumps // Use default
alarmSetting?.entries = arrayOf(allAlarmEntries[6], allAlarmEntries[7]) // "Beep", "Silent"
alarmSetting?.entryValues = arrayOf(allAlarmValues[6], allAlarmValues[7]) // "6", "7"
} }
} }
} }
@ -220,6 +218,7 @@ import kotlin.math.abs
override fun isHandshakeInProgress(): Boolean = false override fun isHandshakeInProgress(): Boolean = false
override fun finishHandshaking() { override fun finishHandshaking() {
// Unused
} }
override fun connect(reason: String) { override fun connect(reason: String) {
@ -417,6 +416,7 @@ import kotlin.math.abs
try { try {
extended.put("ActiveProfile", profileName) extended.put("ActiveProfile", profileName)
} catch (ignored: Exception) { } catch (ignored: Exception) {
// Ignore
} }
pumpJson.put("status", status) pumpJson.put("status", status)
pumpJson.put("extended", extended) pumpJson.put("extended", extended)
@ -472,6 +472,7 @@ import kotlin.math.abs
} }
override fun executeCustomAction(customActionType: CustomActionType) { override fun executeCustomAction(customActionType: CustomActionType) {
// Unused
} }
override fun executeCustomCommand(customCommand: CustomCommand): PumpEnactResult? { override fun executeCustomCommand(customCommand: CustomCommand): PumpEnactResult? {

View file

@ -334,7 +334,7 @@ class MedtrumPump @Inject constructor(
val date = GregorianCalendar() val date = GregorianCalendar()
date.timeInMillis = timestamp date.timeInMillis = timestamp
val hourOfDayMinutes = date.get(GregorianCalendar.HOUR_OF_DAY) * 60 + date.get(GregorianCalendar.MINUTE) val hourOfDayMinutes = date[GregorianCalendar.HOUR_OF_DAY] * 60 + date[GregorianCalendar.MINUTE]
for (index in 0 until basalCount) { for (index in 0 until basalCount) {
val currentIndex = 1 + (index * 3) val currentIndex = 1 + (index * 3)
@ -355,7 +355,6 @@ class MedtrumPump @Inject constructor(
aapsLogger.debug(LTag.PUMP, "getHourlyBasalFromMedtrumProfileArray: basal: $basal") aapsLogger.debug(LTag.PUMP, "getHourlyBasalFromMedtrumProfileArray: basal: $basal")
break break
} }
// aapsLogger.debug(LTag.PUMP, "getHourlyBasalFromMedtrumProfileArray: rate: $rate, startMinutes: $startMinutes, endMinutes: $endMinutes")
} }
return basal return basal
} }
@ -379,59 +378,67 @@ class MedtrumPump @Inject constructor(
) )
@Suppress("UNNECESSARY_SAFE_CALL") // Safe call to allow mocks to return null @Suppress("UNNECESSARY_SAFE_CALL") // Safe call to allow mocks to return null
val expectedTemporaryBasal = pumpSync.expectedPumpState()?.temporaryBasal val expectedTemporaryBasal = pumpSync.expectedPumpState()?.temporaryBasal
if (basalType.isTempBasal() && expectedTemporaryBasal?.pumpId != basalStartTime) { when {
// Note: temporaryBasalInfo will be removed from temporaryBasalStorage after this call basalType.isTempBasal() && expectedTemporaryBasal?.pumpId != basalStartTime -> {
val temporaryBasalInfo = temporaryBasalStorage.findTemporaryBasal(basalStartTime, basalRate) // Note: temporaryBasalInfo will be removed from temporaryBasalStorage after this call
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(FAKE_TBR_LENGTH).msecs() val duration = temporaryBasalInfo?.duration ?: T.mins(FAKE_TBR_LENGTH).msecs()
val adjustedBasalRate = if (basalType == BasalType.ABSOLUTE_TEMP) { val adjustedBasalRate = if (basalType == BasalType.ABSOLUTE_TEMP) {
basalRate basalRate
} else { } else {
(basalRate / baseBasalRate) * 100 // calculate the percentage of the original basal rate (basalRate / baseBasalRate) * 100 // calculate the percentage of the original basal rate
} }
val newRecord = pumpSync.syncTemporaryBasalWithPumpId( val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = basalStartTime, timestamp = basalStartTime,
rate = adjustedBasalRate, rate = adjustedBasalRate,
duration = duration, duration = duration,
isAbsolute = (basalType == BasalType.ABSOLUTE_TEMP), isAbsolute = (basalType == BasalType.ABSOLUTE_TEMP),
type = temporaryBasalInfo?.type, type = temporaryBasalInfo?.type,
pumpId = basalStartTime, pumpId = basalStartTime,
pumpType = pumpType(),
pumpSerial = pumpSN.toString(radix = 16)
)
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"
)
} else if (basalType.isSuspendedByPump() && expectedTemporaryBasal?.pumpId != basalStartTime) {
val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = basalStartTime,
rate = 0.0,
duration = T.mins(FAKE_TBR_LENGTH).msecs(),
isAbsolute = true,
type = PumpSync.TemporaryBasalType.PUMP_SUSPEND,
pumpId = basalStartTime,
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"
)
} else if (basalType == BasalType.NONE && expectedTemporaryBasal?.rate != basalRate && expectedTemporaryBasal?.duration != T.mins(FAKE_TBR_LENGTH).msecs()) {
// Pump suspended, set fake TBR
setFakeTBR()
} else if (basalType == BasalType.STANDARD) {
if (expectedTemporaryBasal != null) {
// Pump resumed, sync end
val success = pumpSync.syncStopTemporaryBasalWithPumpId(
timestamp = basalStartTime + 250, // Time of normal basal start = time of tbr end
endPumpId = basalStartTime + 250, // +250ms Make sure there is time between start and stop of TBR
pumpType = pumpType(), pumpType = pumpType(),
pumpSerial = pumpSN.toString(radix = 16) pumpSerial = pumpSN.toString(radix = 16)
) )
aapsLogger.debug(LTag.PUMPCOMM, "handleBasalStatusUpdate: EVENT TEMP_END ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) success: $success") 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"
)
}
basalType.isSuspendedByPump() && expectedTemporaryBasal?.pumpId != basalStartTime -> {
val newRecord = pumpSync.syncTemporaryBasalWithPumpId(
timestamp = basalStartTime,
rate = 0.0,
duration = T.mins(FAKE_TBR_LENGTH).msecs(),
isAbsolute = true,
type = PumpSync.TemporaryBasalType.PUMP_SUSPEND,
pumpId = basalStartTime,
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"
)
}
basalType == BasalType.NONE && expectedTemporaryBasal?.rate != basalRate && expectedTemporaryBasal?.duration != T.mins(FAKE_TBR_LENGTH).msecs() -> {
// Pump suspended, set fake TBR
setFakeTBR()
}
basalType == BasalType.STANDARD -> {
if (expectedTemporaryBasal != null) {
// Pump resumed, sync end
val success = pumpSync.syncStopTemporaryBasalWithPumpId(
timestamp = basalStartTime + 250, // Time of normal basal start = time of tbr end
endPumpId = basalStartTime + 250, // +250ms Make sure there is time between start and stop of TBR
pumpType = pumpType(),
pumpSerial = pumpSN.toString(radix = 16)
)
aapsLogger.debug(LTag.PUMPCOMM, "handleBasalStatusUpdate: EVENT TEMP_END ${dateUtil.dateAndTimeString(basalStartTime)} ($basalStartTime) success: $success")
}
} }
} }

View file

@ -111,91 +111,99 @@ class GetRecordPacket(injector: HasAndroidInjector, private val recordIndex: Int
"$bolusExtendedDuration, " + "bolusExtendedDelivered: $bolusExtendedDelivered, bolusCarb: $bolusCarb, bolusGlucose: $bolusGlucose, bolusIOB: $bolusIOB, unknown1: $unknown1, unknown2: $unknown2, " + "bolusType: $bolusType, bolusWizard: $bolusWizard" "$bolusExtendedDuration, " + "bolusExtendedDelivered: $bolusExtendedDelivered, bolusCarb: $bolusCarb, bolusGlucose: $bolusGlucose, bolusIOB: $bolusIOB, unknown1: $unknown1, unknown2: $unknown2, " + "bolusType: $bolusType, bolusWizard: $bolusWizard"
) )
if (bolusType == BolusType.NORMAL) { when (bolusType) {
val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered) BolusType.NORMAL -> {
var newRecord = false val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered)
if (detailedBolusInfo != null) { var newRecord = false
val syncOk = pumpSync.syncBolusWithTempId( 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, timestamp = bolusStartTime,
amount = bolusNormalDelivered, amount = bolusExtendedDelivered,
temporaryId = detailedBolusInfo.timestamp, duration = bolusExtendedDuration,
type = detailedBolusInfo.bolusType, isEmulatingTB = false,
pumpId = bolusStartTime, pumpId = bolusStartTime,
pumpType = medtrumPump.pumpType(), pumpType = medtrumPump.pumpType(),
pumpSerial = medtrumPump.pumpSN.toString(radix = 16) pumpSerial = medtrumPump.pumpSN.toString(radix = 16)
) )
if (!syncOk) { aapsLogger.debug(
aapsLogger.warn(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD: Failed to sync bolus with tempId: ${detailedBolusInfo.timestamp}") LTag.PUMPCOMM,
// detailedInfo can be from another similar record. Reinsert "from record: ${if (newRecord) "**NEW** " else ""}EVENT EXTENDED BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U "
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( BolusType.COMBI -> {
LTag.PUMPCOMM, // Note, this should never happen, as we don't use combo bolus
"from record: ${if (newRecord) "**NEW** " else ""}EVENT BOLUS ${dateUtil.dateAndTimeString(bolusStartTime)} ($bolusStartTime) Bolus: ${bolusNormalDelivered}U " val detailedBolusInfo = detailedBolusInfoStorage.findDetailedBolusInfo(bolusStartTime, bolusNormalDelivered)
) val newRecord = pumpSync.syncBolusWithPumpId(
if (bolusStartTime > medtrumPump.lastBolusTime) { timestamp = bolusStartTime,
medtrumPump.lastBolusTime = bolusStartTime amount = bolusNormalDelivered,
medtrumPump.lastBolusAmount = 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 if (bolusType == BolusType.EXTENDED) {
val newRecord = pumpSync.syncExtendedBolusWithPumpId( else -> {
timestamp = bolusStartTime, aapsLogger.error(LTag.PUMPCOMM, "GetRecordPacket HandleResponse: BOLUS_RECORD: Unknown bolus type: $bolusType")
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 "
)
} else if (bolusType == 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")
} }
} }

View file

@ -5,8 +5,522 @@ import info.nightscout.pump.medtrum.extension.toLong
class Crypt { class Crypt {
private val RIJNDEAL_S_BOX: IntArray = intArrayOf(99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, 176, 84, 187, 22) private val RIJNDEAL_S_BOX: IntArray = intArrayOf(
private val RIJNDEAL_INVERSE_S_BOX: IntArray = intArrayOf(82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, 85, 33, 12, 125) 99,
124,
119,
123,
242,
107,
111,
197,
48,
1,
103,
43,
254,
215,
171,
118,
202,
130,
201,
125,
250,
89,
71,
240,
173,
212,
162,
175,
156,
164,
114,
192,
183,
253,
147,
38,
54,
63,
247,
204,
52,
165,
229,
241,
113,
216,
49,
21,
4,
199,
35,
195,
24,
150,
5,
154,
7,
18,
128,
226,
235,
39,
178,
117,
9,
131,
44,
26,
27,
110,
90,
160,
82,
59,
214,
179,
41,
227,
47,
132,
83,
209,
0,
237,
32,
252,
177,
91,
106,
203,
190,
57,
74,
76,
88,
207,
208,
239,
170,
251,
67,
77,
51,
133,
69,
249,
2,
127,
80,
60,
159,
168,
81,
163,
64,
143,
146,
157,
56,
245,
188,
182,
218,
33,
16,
255,
243,
210,
205,
12,
19,
236,
95,
151,
68,
23,
196,
167,
126,
61,
100,
93,
25,
115,
96,
129,
79,
220,
34,
42,
144,
136,
70,
238,
184,
20,
222,
94,
11,
219,
224,
50,
58,
10,
73,
6,
36,
92,
194,
211,
172,
98,
145,
149,
228,
121,
231,
200,
55,
109,
141,
213,
78,
169,
108,
86,
244,
234,
101,
122,
174,
8,
186,
120,
37,
46,
28,
166,
180,
198,
232,
221,
116,
31,
75,
189,
139,
138,
112,
62,
181,
102,
72,
3,
246,
14,
97,
53,
87,
185,
134,
193,
29,
158,
225,
248,
152,
17,
105,
217,
142,
148,
155,
30,
135,
233,
206,
85,
40,
223,
140,
161,
137,
13,
191,
230,
66,
104,
65,
153,
45,
15,
176,
84,
187,
22
)
private val RIJNDEAL_INVERSE_S_BOX: IntArray = intArrayOf(
82,
9,
106,
213,
48,
54,
165,
56,
191,
64,
163,
158,
129,
243,
215,
251,
124,
227,
57,
130,
155,
47,
255,
135,
52,
142,
67,
68,
196,
222,
233,
203,
84,
123,
148,
50,
166,
194,
35,
61,
238,
76,
149,
11,
66,
250,
195,
78,
8,
46,
161,
102,
40,
217,
36,
178,
118,
91,
162,
73,
109,
139,
209,
37,
114,
248,
246,
100,
134,
104,
152,
22,
212,
164,
92,
204,
93,
101,
182,
146,
108,
112,
72,
80,
253,
237,
185,
218,
94,
21,
70,
87,
167,
141,
157,
132,
144,
216,
171,
0,
140,
188,
211,
10,
247,
228,
88,
5,
184,
179,
69,
6,
208,
44,
30,
143,
202,
63,
15,
2,
193,
175,
189,
3,
1,
19,
138,
107,
58,
145,
17,
65,
79,
103,
220,
234,
151,
242,
207,
206,
240,
180,
230,
115,
150,
172,
116,
34,
231,
173,
53,
133,
226,
249,
55,
232,
28,
117,
223,
110,
71,
241,
26,
113,
29,
41,
197,
137,
111,
183,
98,
14,
170,
24,
190,
27,
252,
86,
62,
75,
198,
210,
121,
32,
154,
219,
192,
254,
120,
205,
90,
244,
31,
221,
168,
51,
136,
7,
199,
49,
177,
18,
16,
89,
39,
128,
236,
95,
96,
81,
127,
169,
25,
181,
74,
13,
45,
229,
122,
159,
147,
201,
156,
239,
160,
224,
59,
77,
174,
42,
245,
176,
200,
235,
187,
60,
131,
83,
153,
97,
23,
43,
4,
126,
186,
119,
214,
38,
225,
105,
20,
99,
85,
33,
12,
125
)
private val MED_CIPHER: Long = 1344751489 private val MED_CIPHER: Long = 1344751489
@ -39,11 +553,11 @@ class Crypt {
} }
private fun randomGen(input: Long): Long { private fun randomGen(input: Long): Long {
val A = 16807 val a = 16807
val Q = 127773 val q = 127773
val R = 2836 val r = 2836
val tmp1 = input / Q val tmp1 = input / q
var ret = (input - (tmp1 * Q)) * A - (tmp1 * R) var ret = (input - (tmp1 * q)) * a - (tmp1 * r)
if (ret < 0) { if (ret < 0) {
ret += 2147483647L ret += 2147483647L
} }

View file

@ -310,9 +310,7 @@ class BLEComm @Inject internal constructor(
private fun readDescriptor(descriptor: BluetoothGattDescriptor?) { private fun readDescriptor(descriptor: BluetoothGattDescriptor?) {
aapsLogger.debug(LTag.PUMPBTCOMM, "readDescriptor") aapsLogger.debug(LTag.PUMPBTCOMM, "readDescriptor")
if (mBluetoothAdapter == null || mBluetoothGatt == null || descriptor == null) { if (mBluetoothAdapter == null || mBluetoothGatt == null || descriptor == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR") handleNotInitialized()
isConnecting = false
isConnected = false
return return
} }
mBluetoothGatt?.readDescriptor(descriptor) mBluetoothGatt?.readDescriptor(descriptor)
@ -323,9 +321,7 @@ class BLEComm @Inject internal constructor(
aapsLogger.debug(LTag.PUMPBTCOMM, "checkDescriptor") aapsLogger.debug(LTag.PUMPBTCOMM, "checkDescriptor")
val service = getGattService() val service = getGattService()
if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) { if (mBluetoothAdapter == null || mBluetoothGatt == null || service == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR") handleNotInitialized()
isConnecting = false
isConnected = false
return return
} }
if (descriptor.value.toInt() > 0) { if (descriptor.value.toInt() > 0) {
@ -352,9 +348,7 @@ class BLEComm @Inject internal constructor(
private fun setCharacteristicNotification(characteristic: BluetoothGattCharacteristic?, enabled: Boolean) { private fun setCharacteristicNotification(characteristic: BluetoothGattCharacteristic?, enabled: Boolean) {
aapsLogger.debug(LTag.PUMPBTCOMM, "setCharacteristicNotification") aapsLogger.debug(LTag.PUMPBTCOMM, "setCharacteristicNotification")
if (mBluetoothAdapter == null || mBluetoothGatt == null) { if (mBluetoothAdapter == null || mBluetoothGatt == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR") handleNotInitialized()
isConnecting = false
isConnected = false
return return
} }
mBluetoothGatt?.setCharacteristicNotification(characteristic, enabled) mBluetoothGatt?.setCharacteristicNotification(characteristic, enabled)
@ -366,7 +360,7 @@ class BLEComm @Inject internal constructor(
it.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE it.value = BluetoothGattDescriptor.ENABLE_INDICATION_VALUE
mBluetoothGatt?.writeDescriptor(it) mBluetoothGatt?.writeDescriptor(it)
} else { } else {
// Do nothing
} }
} }
} }
@ -417,9 +411,7 @@ class BLEComm @Inject internal constructor(
private fun getGattService(): BluetoothGattService? { private fun getGattService(): BluetoothGattService? {
aapsLogger.debug(LTag.PUMPBTCOMM, "getGattService") aapsLogger.debug(LTag.PUMPBTCOMM, "getGattService")
if (mBluetoothAdapter == null || mBluetoothGatt == null) { if (mBluetoothAdapter == null || mBluetoothGatt == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR") handleNotInitialized()
isConnecting = false
isConnected = false
return null return null
} }
return mBluetoothGatt?.getService(UUID.fromString(SERVICE_UUID)) return mBluetoothGatt?.getService(UUID.fromString(SERVICE_UUID))
@ -431,9 +423,7 @@ class BLEComm @Inject internal constructor(
private fun writeCharacteristic(characteristic: BluetoothGattCharacteristic, data: ByteArray?) { private fun writeCharacteristic(characteristic: BluetoothGattCharacteristic, data: ByteArray?) {
handler.postDelayed({ handler.postDelayed({
if (mBluetoothAdapter == null || mBluetoothGatt == null) { if (mBluetoothAdapter == null || mBluetoothGatt == null) {
aapsLogger.error("BluetoothAdapter not initialized_ERROR") handleNotInitialized()
isConnecting = false
isConnected = false
} else { } else {
characteristic.value = data characteristic.value = data
characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT characteristic.writeType = BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT
@ -456,7 +446,7 @@ class BLEComm @Inject internal constructor(
var uuid: String var uuid: String
val gattCharacteristics = gattService.characteristics val gattCharacteristics = gattService.characteristics
for (i in 0 until gattCharacteristics.size) { for (i in 0 until gattCharacteristics.size) {
val gattCharacteristic = gattCharacteristics.get(i) val gattCharacteristic = gattCharacteristics[i]
// Check whether read or write properties is set, the pump needs us to enable notifications on all characteristics that have these properties // Check whether read or write properties is set, the pump needs us to enable notifications on all characteristics that have these properties
if (gattCharacteristic.properties and NEEDS_ENABLE > 0) { if (gattCharacteristic.properties and NEEDS_ENABLE > 0) {
handler.postDelayed({ handler.postDelayed({
@ -472,4 +462,11 @@ class BLEComm @Inject internal constructor(
} }
} }
} }
private fun handleNotInitialized() {
aapsLogger.error("BluetoothAdapter not initialized_ERROR")
isConnecting = false
isConnected = false
return
}
} }

View file

@ -135,20 +135,13 @@ class MedtrumService : DaggerService(), BLECommCallback {
} }
}, fabricPrivacy::logException) }, fabricPrivacy::logException)
scope.launch { scope.launch {
medtrumPump.pumpStateFlow.collect { state -> medtrumPump.pumpStateFlow.collect { pumpState ->
handlePumpStateUpdate(state) handlePumpStateUpdate(pumpState)
} }
} }
scope.launch { scope.launch {
medtrumPump.connectionStateFlow.collect { state -> medtrumPump.connectionStateFlow.collect { connectionState ->
if (medtrumPlugin.isInitialized()) { handleConnectionStateChange(connectionState)
when (state) {
ConnectionState.CONNECTED -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED))
ConnectionState.DISCONNECTED -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED))
ConnectionState.CONNECTING -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING))
ConnectionState.DISCONNECTING -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
}
}
} }
} }
@ -163,23 +156,29 @@ 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")
if (currentState is IdleState) { when (currentState) {
medtrumPump.connectionState = ConnectionState.CONNECTING is IdleState -> {
return bleComm.connect(from, medtrumPump.pumpSN)
} else if (currentState is ReadyState) {
aapsLogger.error(LTag.PUMPCOMM, "Connect attempt when in ReadyState from: $from")
if (isConnected) {
aapsLogger.debug(LTag.PUMP, "connect: already connected")
return true
} else {
aapsLogger.debug(LTag.PUMP, "connect: not connected, resetting state and trying to connect")
toState(IdleState())
medtrumPump.connectionState = ConnectionState.CONNECTING medtrumPump.connectionState = ConnectionState.CONNECTING
return bleComm.connect(from, medtrumPump.pumpSN) return bleComm.connect(from, medtrumPump.pumpSN)
} }
} else {
aapsLogger.error(LTag.PUMPCOMM, "Connect attempt when in state: $currentState from: $from") is ReadyState -> {
return false aapsLogger.error(LTag.PUMPCOMM, "Connect attempt when in ReadyState from: $from")
return if (isConnected) {
aapsLogger.debug(LTag.PUMP, "connect: already connected")
true
} else {
aapsLogger.debug(LTag.PUMP, "connect: not connected, resetting state and trying to connect")
toState(IdleState())
medtrumPump.connectionState = ConnectionState.CONNECTING
bleComm.connect(from, medtrumPump.pumpSN)
}
}
else -> {
aapsLogger.error(LTag.PUMPCOMM, "Connect attempt when in state: $currentState from: $from")
return false
}
} }
} }
@ -247,8 +246,8 @@ class MedtrumService : DaggerService(), BLECommCallback {
timeUpdateNotification(result) timeUpdateNotification(result)
} }
// Do this here, because TBR can be cancelled due to time change by connect flow // Do this here, because TBR can be cancelled due to time change by connect flow
if (needLoadHistory) { if (needLoadHistory && result) {
if (result) result = loadEvents() result = loadEvents()
} }
if (result) medtrumPump.needCheckTimeUpdate = false if (result) medtrumPump.needCheckTimeUpdate = false
return result return result
@ -606,6 +605,17 @@ class MedtrumService : DaggerService(), BLECommCallback {
} }
} }
private fun handleConnectionStateChange(connectionState: ConnectionState) {
if (medtrumPlugin.isInitialized()) {
when (connectionState) {
ConnectionState.CONNECTED -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTED))
ConnectionState.DISCONNECTED -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTED))
ConnectionState.CONNECTING -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.CONNECTING))
ConnectionState.DISCONNECTING -> rxBus.send(EventPumpStatusChanged(EventPumpStatusChanged.Status.DISCONNECTING))
}
}
}
/** BLECommCallbacks */ /** BLECommCallbacks */
override fun onBLEConnected() { override fun onBLEConnected() {
aapsLogger.debug(LTag.PUMPCOMM, "<<<<< onBLEConnected") aapsLogger.debug(LTag.PUMPCOMM, "<<<<< onBLEConnected")
@ -676,7 +686,10 @@ class MedtrumService : DaggerService(), BLECommCallback {
protected var responseSuccess = false protected var responseSuccess = false
protected var sendRetryCounter = 0 protected var sendRetryCounter = 0
open fun onEnter() {} open fun onEnter() {
// Used when a state is entered
}
open fun onIndication(data: ByteArray) { open fun onIndication(data: ByteArray) {
aapsLogger.warn(LTag.PUMPCOMM, "onIndication: " + this.toString() + "Should not be called here!") aapsLogger.warn(LTag.PUMPCOMM, "onIndication: " + this.toString() + "Should not be called here!")
} }

View file

@ -80,6 +80,7 @@ class MedtrumViewModel @Inject constructor(
} }
ConnectionState.CONNECTING, ConnectionState.DISCONNECTING -> { ConnectionState.CONNECTING, ConnectionState.DISCONNECTING -> {
// Do nothing
} }
} }
} }

View file

@ -16,6 +16,7 @@ internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
@Singleton @Singleton
class ViewModelFactory @Inject constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory { class ViewModelFactory @Inject constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T { override fun <T : ViewModel> create(modelClass: Class<T>): T {
var creator: Provider<out ViewModel>? = creators[modelClass] var creator: Provider<out ViewModel>? = creators[modelClass]
if (creator == null) { if (creator == null) {
@ -26,9 +27,7 @@ class ViewModelFactory @Inject constructor(private val creators: Map<Class<out V
} }
} }
} }
if (creator == null) { requireNotNull(creator) { "unknown model class $modelClass" }
throw IllegalArgumentException("unknown model class $modelClass")
}
try { try {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return creator.get() as T return creator.get() as T