bugfix: bolusPulsesRemaining

This commit is contained in:
Andrei Vereha 2021-10-09 12:56:43 +02:00
parent 2b5a1020af
commit 3a2ac68a6f
7 changed files with 124 additions and 34 deletions

View file

@ -4,5 +4,5 @@ import info.nightscout.androidaps.extensions.toHex
class IncorrectPacketException(
val payload: ByteArray,
val expectedIndex: Byte? = null
private val expectedIndex: Byte? = null
) : Exception("Invalid payload: ${payload.toHex()}. Expected index: $expectedIndex")

View file

@ -29,7 +29,7 @@ class MessageIO(
private val dataBleIO: DataBleIO,
) {
val receivedOutOfOrder = LinkedHashMap<Byte, ByteArray>()
private val receivedOutOfOrder = LinkedHashMap<Byte, ByteArray>()
var maxMessageReadTries = 3
var messageReadTries = 0

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.message
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.Id
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.comm.exceptions.CouldNotParseMessageException
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Flag
import java.nio.ByteBuffer
/***
@ -80,13 +81,13 @@ data class MessagePacket(
if (payload.copyOfRange(0, 2).decodeToString() != MAGIC_PATTERN) {
throw CouldNotParseMessageException(payload)
}
val f1 = Flag(payload[2].toInt())
val f1 = Flag(payload[2].toInt() and 0xff)
val sas = f1.get(3) != 0
val tfs = f1.get(4) != 0
val version = ((f1.get(0) shl 2) or (f1.get(1) shl 1) or (f1.get(2) shl 0)).toShort()
val eqos = (f1.get(7) or (f1.get(6) shl 1) or (f1.get(5) shl 2)).toShort()
val f2 = Flag(payload[3].toInt())
val f2 = Flag(payload[3].toInt() and 0xff)
val ack = f2.get(0) != 0
val priority = f2.get(1) != 0
val lastMessage = f2.get(2) != 0
@ -125,24 +126,6 @@ data class MessagePacket(
}
}
private class Flag(var value: Int = 0) {
fun set(idx: Byte, set: Boolean) {
val mask = 1 shl (7 - idx)
if (!set)
return
value = value or mask
}
fun get(idx: Byte): Int {
val mask = 1 shl (7 - idx)
if (value and mask == 0) {
return 0
}
return 1
}
}
internal fun Byte.toUnsignedInt() = this.toInt() and 0xff
private fun ByteArray.assertSizeAtLeast(size: Int) {

View file

@ -5,6 +5,8 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.AlertUtil
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
import info.nightscout.androidaps.plugins.pump.omnipod.dash.util.Flag
import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and
@ -13,18 +15,21 @@ class DefaultStatusResponse(
) : ResponseBase(ResponseType.DEFAULT_STATUS_RESPONSE, encoded) {
val messageType: Byte = encoded[0]
val deliveryStatus: DeliveryStatus = byValue((encoded[1].toInt() shr 4 and 0x0f).toByte(), DeliveryStatus.UNKNOWN)
val podStatus: PodStatus = byValue((encoded[1] and 0x0f), PodStatus.UNKNOWN)
val totalPulsesDelivered: Short =
(encoded[2] and 0x0f shl 9 or (encoded[3].toInt() and 0xff shl 1) or (encoded[4].toInt() and 0xff ushr 7)).toShort()
val sequenceNumberOfLastProgrammingCommand: Short = (encoded[4] ushr 3 and 0x0f).toShort()
val bolusPulsesRemaining: Short = ((encoded[4] and 0x07 shl 10 or (encoded[5].toInt() and 0xff) and 2047).toShort())
private var first4bytes = ByteBuffer.wrap(byteArrayOf(encoded[2], encoded[3], encoded[4], encoded[5])).int
private var last4bytes = ByteBuffer.wrap(byteArrayOf(encoded[6], encoded[7], encoded[8], encoded[9])).int
val podStatus: PodStatus = byValue((encoded[1] and 0x0f), PodStatus.UNKNOWN)
val deliveryStatus: DeliveryStatus = byValue(( (encoded[1].toInt() and 0xff) shr 4 and 0x0f).toByte(), DeliveryStatus.UNKNOWN)
val totalPulsesDelivered: Short = (first4bytes ushr 11 ushr 4 and 0x1FFF).toShort()
val sequenceNumberOfLastProgrammingCommand: Short = (first4bytes ushr 11 and 0X0F).toShort()
val bolusPulsesRemaining: Short = (first4bytes and 0X7FF).toShort()
val activeAlerts: EnumSet<AlertType> =
AlertUtil.decodeAlertSet((encoded[6].toInt() and 0xff shl 1 or (encoded[7] ushr 7)).toByte())
val minutesSinceActivation: Short =
(encoded[7] and 0x7f shl 6 or (encoded[8].toInt() and 0xff ushr 2 and 0x3f)).toShort()
val reservoirPulsesRemaining: Short = (encoded[8] shl 8 or (encoded[9].toInt() and 0xff) and 0x3ff).toShort()
AlertUtil.decodeAlertSet((last4bytes ushr 10 ushr 13 and 0xFF).toByte())
val minutesSinceActivation: Short = ((last4bytes ushr 10 and 0x1FFF)).toShort()
val reservoirPulsesRemaining: Short = (last4bytes and 0X3FF).toShort()
override fun toString(): String {
return "DefaultStatusResponse(" +

View file

@ -2,6 +2,6 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.util
class Constants {
companion object {
val PUMP_SERIAL_FOR_FAKE_TBR = "4241"
const val PUMP_SERIAL_FOR_FAKE_TBR = "4241"
}
}

View file

@ -0,0 +1,19 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.util
class Flag(var value: Int = 0) {
fun set(idx: Byte, set: Boolean) {
val mask = 1 shl (7 - idx)
if (!set)
return
value = value or mask
}
fun get(idx: Byte): Int {
val mask = 1 shl (7 - idx)
if (value and mask == 0) {
return 0
}
return 1
}
}

View file

@ -1,5 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlertType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import org.apache.commons.codec.DecoderException
@ -117,7 +118,7 @@ class DefaultStatusResponseTest {
Full reservoir pulses remaining: 392
Time since activation: 4283
*/
@Test @Throws(DecoderException::class) fun testValidResponseBolusPulsesRemaining2() {
@Test @Throws(DecoderException::class) fun testValidResponseReservoirPulsesRemaining() {
val encoded = Hex.decodeHex("1D990714201F0042ED8801DE")
val response = DefaultStatusResponse(encoded)
Assert.assertArrayEquals(encoded, response.encoded)
@ -133,4 +134,86 @@ class DefaultStatusResponseTest {
Assert.assertEquals(392.toShort(), response.reservoirPulsesRemaining)
Assert.assertEquals(3624.toShort(), response.totalPulsesDelivered)
}
/** response (hex) 1d68002601f400002bff0368
Status response: 29
Pod status: RUNNING_BELOW_MIN_VOLUME
Basal active: true
Temp Basal active: false
Immediate bolus active: false
Extended bolus active: true
Bolus pulses remaining: 31
sequence number of last programing command: 4
Total full pulses delivered: 3624
Full reservoir pulses remaining: 392
Time since activation: 4283
*/
@Test @Throws(DecoderException::class) fun testValidResponseBolusPulsesRemaining3() {
val encoded = Hex.decodeHex("1d68002601f400002bff0368")
val response = DefaultStatusResponse(encoded)
Assert.assertArrayEquals(encoded, response.encoded)
Assert.assertNotSame(encoded, response.encoded)
Assert.assertEquals(500.toShort(), response.bolusPulsesRemaining)
Assert.assertEquals(0, response.activeAlerts.size)
}
/** response (hex) 1d28002e91e400002fff8256
Status response: 29
Pod status: RUNNING_BELOW_MIN_VOLUME
Basal active: true
Temp Basal active: false
Immediate bolus active: false
Extended bolus active: true
Bolus pulses remaining: 31
sequence number of last programing command: 4
Total full pulses delivered: 3624
Full reservoir pulses remaining: 392
Time since activation: 4283
*/
@Test @Throws(DecoderException::class) fun testValidResponseBolusPulsesRemaining4() {
val encoded = Hex.decodeHex("1d28002e91e400002fff8256")
val response = DefaultStatusResponse(encoded)
Assert.assertArrayEquals(encoded, response.encoded)
Assert.assertNotSame(encoded, response.encoded)
Assert.assertEquals(484.toShort(), response.bolusPulsesRemaining)
Assert.assertEquals(0, response.activeAlerts.size)
}
/*
1D980559C820404393FF83AA
Pod status: RUNNING_ABOVE_MIN_VOLUME
Basal active: true
Temp Basal active: false
Immediate bolus active: false
Extended bolus active: true
Bolus pulses remaining: 32
sequence number of last programing command: 9
Total full pulses delivered: 2739
Full reservoir pulses remaining: 1023
Time since activation: 4324
Alert 1 is InActive
Alert 2 is InActive
Alert 3 is InActive
Alert 4 is InActive
Alert 5 is InActive
Alert 6 is InActive
Alert 7 is Active
Occlusion alert active false
*/
@Test @Throws(DecoderException::class) fun testValidResponseActiveAlert1() {
val encoded = Hex.decodeHex("1D980559C820404393FF83AA")
val response = DefaultStatusResponse(encoded)
Assert.assertArrayEquals(encoded, response.encoded)
Assert.assertNotSame(encoded, response.encoded)
Assert.assertEquals(ResponseType.DEFAULT_STATUS_RESPONSE, response.responseType)
Assert.assertEquals(ResponseType.DEFAULT_STATUS_RESPONSE.value, response.messageType)
Assert.assertEquals(DeliveryStatus.UNKNOWN, response.deliveryStatus)
Assert.assertEquals(PodStatus.RUNNING_ABOVE_MIN_VOLUME, response.podStatus)
Assert.assertEquals(9.toShort(), response.sequenceNumberOfLastProgrammingCommand)
Assert.assertEquals(32.toShort(), response.bolusPulsesRemaining)
Assert.assertEquals(1, response.activeAlerts.size)
Assert.assertEquals(4324.toShort(), response.minutesSinceActivation)
Assert.assertEquals(1023.toShort(), response.reservoirPulsesRemaining)
Assert.assertEquals(2739.toShort(), response.totalPulsesDelivered)
Assert.assertEquals(true, response.activeAlerts.contains(AlertType.EXPIRATION))
}
}