commit
00de96cba3
|
@ -731,6 +731,8 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
requestedBolusAmount: Double,
|
||||
bolusType: DetailedBolusInfo.BolusType
|
||||
): Boolean {
|
||||
require(requestedBolusAmount > 0) {"requestedBolusAmount has to be positive"}
|
||||
|
||||
val activeCommand = podStateManager.activeCommand
|
||||
if (activeCommand == null) {
|
||||
throw IllegalArgumentException(
|
||||
|
@ -1356,6 +1358,10 @@ class OmnipodDashPumpPlugin @Inject constructor(
|
|||
if (confirmation.success) {
|
||||
podStateManager.lastBolus?.run {
|
||||
val deliveredUnits = markComplete()
|
||||
if (deliveredUnits < 0){
|
||||
aapsLogger.error(LTag.PUMP, "Negative delivered units!!! $deliveredUnits")
|
||||
return
|
||||
}
|
||||
val bolusHistoryEntry = history.getById(historyId)
|
||||
val sync = pumpSync.syncBolusWithPumpId(
|
||||
timestamp = bolusHistoryEntry.createdAt,
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(" +
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue