Bugfix in setting Dash basal

This commit is contained in:
Bart Sopers 2021-03-30 01:21:35 +02:00
parent 653deff0b6
commit 76c4d01ee7
6 changed files with 50 additions and 9 deletions

View file

@ -135,7 +135,8 @@ class OmnipodDashManagerImpl @Inject constructor(
private fun observeProgramBasalCommand(basalProgram: BasalProgram): Observable<PodEvent> { private fun observeProgramBasalCommand(basalProgram: BasalProgram): Observable<PodEvent> {
return Observable.defer { return Observable.defer {
logger.debug(LTag.PUMPCOMM, "Programming basal. basalProgram={}", basalProgram) val currentTime = Date()
logger.debug(LTag.PUMPCOMM, "Programming basal. currentTime={}, basalProgram={}", currentTime, basalProgram)
bleManager.sendCommand( bleManager.sendCommand(
ProgramBasalCommand.Builder() ProgramBasalCommand.Builder()
.setUniqueId(podStateManager.uniqueId!!.toInt()) .setUniqueId(podStateManager.uniqueId!!.toInt())
@ -143,7 +144,7 @@ class OmnipodDashManagerImpl @Inject constructor(
.setNonce(1229869870) // TODO .setNonce(1229869870) // TODO
.setProgramReminder(ProgramReminder(atStart = false, atEnd = false, atInterval = 0)) .setProgramReminder(ProgramReminder(atStart = false, atEnd = false, atInterval = 0))
.setBasalProgram(basalProgram) .setBasalProgram(basalProgram)
.setCurrentTime(Date()) .setCurrentTime(currentTime)
.build(), .build(),
DefaultStatusResponse::class DefaultStatusResponse::class
) )

View file

@ -38,7 +38,10 @@ class Session(
@Throws(CouldNotParseResponseException::class, UnsupportedOperationException::class) @Throws(CouldNotParseResponseException::class, UnsupportedOperationException::class)
fun sendCommand(cmd: Command, responseType: KClass<out Response>): Response { fun sendCommand(cmd: Command, responseType: KClass<out Response>): Response {
sessionKeys.msgSequenceNumber++ sessionKeys.msgSequenceNumber++
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command: ${cmd.encoded.toHex()} in packet $cmd") aapsLogger.debug(
LTag.PUMPBTCOMM,
"Sending command: ${cmd.javaClass.simpleName}: ${cmd.encoded.toHex()} in packet $cmd"
)
val msg = getCmdMessage(cmd) val msg = getCmdMessage(cmd)
aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command(wrapped): ${msg.payload.toHex()}") aapsLogger.debug(LTag.PUMPBTCOMM, "Sending command(wrapped): ${msg.payload.toHex()}")

View file

@ -56,6 +56,7 @@ object ProgramBasalUtil {
fun mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot: ShortArray?): List<ShortInsulinProgramElement> { fun mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot: ShortArray?): List<ShortInsulinProgramElement> {
require(pulsesPerSlot!!.size <= NUMBER_OF_BASAL_SLOTS) { "Basal program must contain at most 48 slots" } require(pulsesPerSlot!!.size <= NUMBER_OF_BASAL_SLOTS) { "Basal program must contain at most 48 slots" }
val elements: MutableList<ShortInsulinProgramElement> = ArrayList() val elements: MutableList<ShortInsulinProgramElement> = ArrayList()
var extraAlternatePulse = false var extraAlternatePulse = false
var previousPulsesPerSlot: Short = 0 var previousPulsesPerSlot: Short = 0
@ -84,7 +85,7 @@ object ProgramBasalUtil {
extraAlternatePulse = false extraAlternatePulse = false
} }
currentTotalNumberOfSlots++ currentTotalNumberOfSlots++
} else if (numberOfSlotsInCurrentElement.toInt() == 1 && pulsesPerSlot[currentTotalNumberOfSlots.toInt()].toInt() == previousPulsesPerSlot + 1) { } else if (numberOfSlotsInCurrentElement.toInt() == 1 && !extraAlternatePulse && pulsesPerSlot[currentTotalNumberOfSlots.toInt()].toInt() == previousPulsesPerSlot + 1) {
// Second slot of segment with extra alternate pulse // Second slot of segment with extra alternate pulse
var expectAlternatePulseForNextSegment = false var expectAlternatePulseForNextSegment = false
currentTotalNumberOfSlots++ currentTotalNumberOfSlots++
@ -94,10 +95,10 @@ object ProgramBasalUtil {
// Loop rest alternate pulse segment // Loop rest alternate pulse segment
if (pulsesPerSlot[currentTotalNumberOfSlots.toInt()].toInt() == previousPulsesPerSlot + (if (expectAlternatePulseForNextSegment) 1 else 0)) { if (pulsesPerSlot[currentTotalNumberOfSlots.toInt()].toInt() == previousPulsesPerSlot + (if (expectAlternatePulseForNextSegment) 1 else 0)) {
// Still in alternate pulse segment // Still in alternate pulse segment
currentTotalNumberOfSlots++
expectAlternatePulseForNextSegment = !expectAlternatePulseForNextSegment expectAlternatePulseForNextSegment = !expectAlternatePulseForNextSegment
if (numberOfSlotsInCurrentElement < MAX_NUMBER_OF_SLOTS_IN_INSULIN_PROGRAM_ELEMENT) { if (numberOfSlotsInCurrentElement < MAX_NUMBER_OF_SLOTS_IN_INSULIN_PROGRAM_ELEMENT) {
numberOfSlotsInCurrentElement++ numberOfSlotsInCurrentElement++
currentTotalNumberOfSlots++
} else { } else {
// End of alternate pulse segment (no slots left in element) // End of alternate pulse segment (no slots left in element)
elements.add( elements.add(
@ -110,6 +111,7 @@ object ProgramBasalUtil {
previousPulsesPerSlot = pulsesPerSlot[currentTotalNumberOfSlots.toInt()] previousPulsesPerSlot = pulsesPerSlot[currentTotalNumberOfSlots.toInt()]
numberOfSlotsInCurrentElement = 1 numberOfSlotsInCurrentElement = 1
extraAlternatePulse = false extraAlternatePulse = false
currentTotalNumberOfSlots++
break break
} }
} else { } else {
@ -193,6 +195,7 @@ object ProgramBasalUtil {
val hourOfDay = instance[Calendar.HOUR_OF_DAY] val hourOfDay = instance[Calendar.HOUR_OF_DAY]
val minuteOfHour = instance[Calendar.MINUTE] val minuteOfHour = instance[Calendar.MINUTE]
val secondOfMinute = instance[Calendar.SECOND] val secondOfMinute = instance[Calendar.SECOND]
val index = ((hourOfDay * 60 + minuteOfHour) / 30).toByte() val index = ((hourOfDay * 60 + minuteOfHour) / 30).toByte()
val secondOfDay = secondOfMinute + hourOfDay * 3600 + minuteOfHour * 60 val secondOfDay = secondOfMinute + hourOfDay * 3600 + minuteOfHour * 60
val secondsRemaining = ((index + 1) * 1800 - secondOfDay).toShort() val secondsRemaining = ((index + 1) * 1800 - secondOfDay).toShort()

View file

@ -17,4 +17,8 @@ class ProgramReminder(
or ((atInterval and 0x3f).toInt()) or ((atInterval and 0x3f).toInt())
).toByte() ).toByte()
) )
override fun toString(): String {
return "ProgramReminder(atStart=$atStart, atEnd=$atEnd, atInterval=$atInterval)"
}
} }

View file

@ -295,7 +295,10 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
// total delivered // total delivered
podInfoBinding.totalDelivered.text = podInfoBinding.totalDelivered.text =
if (podStateManager.isActivationCompleted && podStateManager.pulsesDelivered != null) { if (podStateManager.isActivationCompleted && podStateManager.pulsesDelivered != null) {
resourceHelper.gs(R.string.omnipod_common_overview_total_delivered_value, podStateManager.pulseRate) resourceHelper.gs(
R.string.omnipod_common_overview_total_delivered_value,
podStateManager.pulsesDelivered!! * 0.05
)
} else { } else {
PLACEHOLDER PLACEHOLDER
} }
@ -313,7 +316,7 @@ class OmnipodDashOverviewFragment : DaggerFragment() {
podInfoBinding.reservoir.text = resourceHelper.gs( podInfoBinding.reservoir.text = resourceHelper.gs(
R.string.omnipod_common_overview_reservoir_value, R.string.omnipod_common_overview_reservoir_value,
(podStateManager.pulsesRemaining!! / 20.0) (podStateManager.pulsesRemaining!! * 0.05)
) )
podInfoBinding.reservoir.setTextColor( podInfoBinding.reservoir.setTextColor(
if (podStateManager.pulsesRemaining!! < lowReservoirThreshold) { if (podStateManager.pulsesRemaining!! < lowReservoirThreshold) {

View file

@ -15,7 +15,7 @@ class ProgramBasalCommandTest {
BasalProgram.Segment(0.toShort(), 48.toShort(), 300) BasalProgram.Segment(0.toShort(), 48.toShort(), 300)
) )
val basalProgram = BasalProgram(segments) val basalProgram = BasalProgram(segments)
val date = Date(2021, 1, 17, 14, 47, 43) val date = Date(121, 1, 17, 14, 47, 43)
val encoded = ProgramBasalCommand.Builder() // val encoded = ProgramBasalCommand.Builder() //
.setUniqueId(37879809) // .setUniqueId(37879809) //
@ -27,6 +27,33 @@ class ProgramBasalCommandTest {
.build() // .build() //
.encoded .encoded
Assert.assertArrayEquals(Hex.decodeHex("0242000128241A12494E532E0005E81D1708000CF01EF01EF01E130E40001593004C4B403840005B8D80827C"), encoded) Assert.assertArrayEquals(
Hex.decodeHex("0242000128241A12494E532E0005E81D1708000CF01EF01EF01E130E40001593004C4B403840005B8D80827C"),
encoded
)
} }
@Test @Throws(DecoderException::class) fun testProgramBasalCommandWithExtraAlternateSegmentPulse() {
val segments = listOf(
BasalProgram.Segment(0.toShort(), 48.toShort(), 5)
)
val basalProgram = BasalProgram(segments)
val date = Date(121, 0, 30, 23, 21, 46)
val encoded = ProgramBasalCommand.Builder() //
.setUniqueId(4241) //
.setNonce(1229869870) //
.setSequenceNumber(12.toShort()) //
.setBasalProgram(basalProgram) //
.setCurrentTime(date) //
.setProgramReminder(ProgramReminder(atStart = false, atEnd = false, atInterval = 0.toByte())) //
.build() //
.encoded
Assert.assertArrayEquals(
Hex.decodeHex("0000109130241a12494e532e0000c52e0f700000f800f800f800130e0000000707fcad8000f015752a00033b"),
encoded
)
}
} }