This commit is contained in:
AdrianLxM 2021-02-26 21:45:17 +01:00
parent dbff1c6e50
commit ae30387a25
36 changed files with 223 additions and 535 deletions

View file

@ -109,7 +109,7 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
when (confirmed) { when (confirmed) {
is DescriptorWriteConfirmationError -> throw CouldNotConfirmWriteException(confirmed.status) is DescriptorWriteConfirmationError -> throw CouldNotConfirmWriteException(confirmed.status)
is DescriptorWriteConfirmationUUID -> if (confirmed.uuid != descriptorUUID) { is DescriptorWriteConfirmationUUID -> if (confirmed.uuid != descriptorUUID) {
aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got ${confirmed.uuid}. Expected: ${descriptorUUID}") aapsLogger.warn(LTag.PUMPBTCOMM, "Could not confirm descriptor write. Got ${confirmed.uuid}. Expected: $descriptorUUID")
throw CouldNotConfirmDescriptorWriteException(descriptorUUID, confirmed.uuid) throw CouldNotConfirmDescriptorWriteException(descriptorUUID, confirmed.uuid)
} else { } else {
aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed descriptor write : " + confirmed.uuid) aapsLogger.debug(LTag.PUMPBTCOMM, "Confirmed descriptor write : " + confirmed.uuid)
@ -127,7 +127,7 @@ class BleCommCallbacks(private val aapsLogger: AAPSLogger, private val incomingP
} }
try { try {
if (descriptorWriteQueue.size > 0) { if (descriptorWriteQueue.size > 0) {
aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: " + descriptorWriteQueue.size) aapsLogger.warn(LTag.PUMPBTCOMM, "Descriptor write queue should be empty, found: ${descriptorWriteQueue.size}")
descriptorWriteQueue.clear() descriptorWriteQueue.clear()
} }
val offered = descriptorWriteQueue.offer(writeConfirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS) val offered = descriptorWriteQueue.offer(writeConfirmation, WRITE_CONFIRM_TIMEOUT_MS.toLong(), TimeUnit.MILLISECONDS)

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.b
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.builder.NonceEnabledCommandBuilder
import java.nio.ByteBuffer import java.nio.ByteBuffer
class DeactivateCommand internal constructor( class DeactivateCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,

View file

@ -6,7 +6,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.b
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType
import java.nio.ByteBuffer import java.nio.ByteBuffer
class GetStatusCommand( class GetStatusCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,

View file

@ -5,7 +5,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.b
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.builder.HeaderEnabledCommandBuilder import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.builder.HeaderEnabledCommandBuilder
import java.nio.ByteBuffer import java.nio.ByteBuffer
class GetVersionCommand internal constructor( class GetVersionCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean multiCommandFlag: Boolean

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.*
class ProgramAlertsCommand internal constructor( class ProgramAlertsCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,

View file

@ -12,7 +12,7 @@ import java.nio.ByteBuffer
import java.util.* import java.util.*
// Always preceded by 0x1a ProgramInsulinCommand // Always preceded by 0x1a ProgramInsulinCommand
class ProgramBasalCommand internal constructor( class ProgramBasalCommand private constructor(
private val interlockCommand: ProgramInsulinCommand, private val interlockCommand: ProgramInsulinCommand,
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ProgramReminder import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.ProgramReminder
import java.nio.ByteBuffer import java.nio.ByteBuffer
class ProgramBeepsCommand internal constructor( class ProgramBeepsCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,

View file

@ -9,7 +9,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.Mess
import java.nio.ByteBuffer import java.nio.ByteBuffer
// NOT SUPPORTED: extended bolus // NOT SUPPORTED: extended bolus
class ProgramBolusCommand internal constructor( class ProgramBolusCommand private constructor(
private val interlockCommand: ProgramInsulinCommand, private val interlockCommand: ProgramInsulinCommand,
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,

View file

@ -7,7 +7,7 @@ import java.nio.ByteBuffer
import java.util.* import java.util.*
// Always followed by one of: 0x13, 0x16, 0x17 // Always followed by one of: 0x13, 0x16, 0x17
class ProgramInsulinCommand( class ProgramInsulinCommand internal constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,
@ -37,7 +37,7 @@ class ProgramInsulinCommand(
fun calculateChecksum(bytes: ByteArray): Short { fun calculateChecksum(bytes: ByteArray): Short {
var sum: Short = 0 var sum: Short = 0
for (b in bytes) { for (b in bytes) {
sum = ((b.toInt() and 0xff) + sum).toShort() // TODO Adrian: int conversion ok? sum = ((b.toInt() and 0xff) + sum).toShort()
} }
return sum return sum
} }

View file

@ -11,7 +11,7 @@ import java.nio.ByteBuffer
import java.util.* import java.util.*
// NOT SUPPORTED: percentage temp basal // NOT SUPPORTED: percentage temp basal
class ProgramTempBasalCommand protected constructor( class ProgramTempBasalCommand private constructor(
private val interlockCommand: ProgramInsulinCommand, private val interlockCommand: ProgramInsulinCommand,
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
@ -20,10 +20,11 @@ class ProgramTempBasalCommand protected constructor(
insulinProgramElements: List<BasalInsulinProgramElement> insulinProgramElements: List<BasalInsulinProgramElement>
) : HeaderEnabledCommand(CommandType.PROGRAM_TEMP_BASAL, uniqueId, sequenceNumber, multiCommandFlag) { ) : HeaderEnabledCommand(CommandType.PROGRAM_TEMP_BASAL, uniqueId, sequenceNumber, multiCommandFlag) {
private val insulinProgramElements: List<BasalInsulinProgramElement> private val insulinProgramElements: List<BasalInsulinProgramElement> = ArrayList(insulinProgramElements)
fun getBodyLength(): Byte = (insulinProgramElements.size * 6 + 8).toByte()
fun getLength(): Short = (getBodyLength() + 2).toShort() private fun getBodyLength(): Byte = (insulinProgramElements.size * 6 + 8).toByte()
private fun getLength(): Short = (getBodyLength() + 2).toShort()
class Builder : NonceEnabledCommandBuilder<Builder, ProgramTempBasalCommand>() { class Builder : NonceEnabledCommandBuilder<Builder, ProgramTempBasalCommand>() {
@ -56,16 +57,12 @@ class ProgramTempBasalCommand protected constructor(
val shortInsulinProgramElements = ProgramTempBasalUtil.mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot) val shortInsulinProgramElements = ProgramTempBasalUtil.mapPulsesPerSlotToShortInsulinProgramElements(pulsesPerSlot)
val insulinProgramElements = ProgramTempBasalUtil.mapTenthPulsesPerSlotToLongInsulinProgramElements(tenthPulsesPerSlot) val insulinProgramElements = ProgramTempBasalUtil.mapTenthPulsesPerSlotToLongInsulinProgramElements(tenthPulsesPerSlot)
val interlockCommand = ProgramInsulinCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!, shortInsulinProgramElements, val interlockCommand = ProgramInsulinCommand(uniqueId!!, sequenceNumber!!, multiCommandFlag, nonce!!, shortInsulinProgramElements,
ProgramTempBasalUtil.calculateChecksum(durationInSlots, pulsesPerSlot!![0], pulsesPerSlot), durationInSlots, ProgramTempBasalUtil.calculateChecksum(durationInSlots, pulsesPerSlot[0], pulsesPerSlot), durationInSlots,
0x3840.toShort(), pulsesPerSlot[0], ProgramInsulinCommand.DeliveryType.TEMP_BASAL) 0x3840.toShort(), pulsesPerSlot[0], ProgramInsulinCommand.DeliveryType.TEMP_BASAL)
return ProgramTempBasalCommand(interlockCommand, uniqueId!!, sequenceNumber!!, multiCommandFlag, programReminder!!, insulinProgramElements) return ProgramTempBasalCommand(interlockCommand, uniqueId!!, sequenceNumber!!, multiCommandFlag, programReminder!!, insulinProgramElements)
} }
} }
init {
this.insulinProgramElements = ArrayList(insulinProgramElements)
}
override val encoded: ByteArray override val encoded: ByteArray
get() { get() {
val firstProgramElement = insulinProgramElements[0] val firstProgramElement = insulinProgramElements[0]
@ -90,7 +87,7 @@ class ProgramTempBasalCommand protected constructor(
} }
val tempBasalCommand = buffer.array() val tempBasalCommand = buffer.array()
val interlockCommand = interlockCommand.encoded val interlockCommand = interlockCommand.encoded
val header: ByteArray = encodeHeader(uniqueId, sequenceNumber, (tempBasalCommand.size + interlockCommand!!.size).toShort(), multiCommandFlag) val header: ByteArray = encodeHeader(uniqueId, sequenceNumber, (tempBasalCommand.size + interlockCommand.size).toShort(), multiCommandFlag)
return appendCrc(ByteBuffer.allocate(header.size + interlockCommand.size + tempBasalCommand.size) // return appendCrc(ByteBuffer.allocate(header.size + interlockCommand.size + tempBasalCommand.size) //
.put(header) // .put(header) //
.put(interlockCommand) // .put(interlockCommand) //

View file

@ -6,7 +6,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.b
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.*
class SetUniqueIdCommand internal constructor( class SetUniqueIdCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,

View file

@ -7,7 +7,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.*
class SilenceAlertsCommand internal constructor( class SilenceAlertsCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,

View file

@ -8,7 +8,7 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.*
class StopDeliveryCommand internal constructor( class StopDeliveryCommand private constructor(
uniqueId: Int, uniqueId: Int,
sequenceNumber: Short, sequenceNumber: Short,
multiCommandFlag: Boolean, multiCommandFlag: Boolean,
@ -24,7 +24,7 @@ class StopDeliveryCommand internal constructor(
.put(commandType.value) // .put(commandType.value) //
.put(BODY_LENGTH) // .put(BODY_LENGTH) //
.putInt(nonce) // .putInt(nonce) //
.put((beepType.value.toInt() shl 4 or deliveryType.encoded[0].toInt()).toByte()) // TODO bitstuff .put((beepType.value.toInt() shl 4 or deliveryType.encoded[0].toInt()).toByte()) //
.array()) .array())
} }

View file

@ -1,8 +1,6 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base
enum class CommandType( enum class CommandType(val value: Byte) {
val value: Byte
) {
SET_UNIQUE_ID(0x03.toByte()), SET_UNIQUE_ID(0x03.toByte()),
GET_VERSION(0x07.toByte()), GET_VERSION(0x07.toByte()),

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command
@Suppress("UNCHECKED_CAST")
abstract class HeaderEnabledCommandBuilder<T : HeaderEnabledCommandBuilder<T, R>, R : Command> : CommandBuilder<R> { abstract class HeaderEnabledCommandBuilder<T : HeaderEnabledCommandBuilder<T, R>, R : Command> : CommandBuilder<R> {
protected var uniqueId: Int? = null protected var uniqueId: Int? = null

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.command.base.Command
@Suppress("UNCHECKED_CAST")
abstract class NonceEnabledCommandBuilder<T : NonceEnabledCommandBuilder<T, R>, R : Command> : HeaderEnabledCommandBuilder<T, R>() { abstract class NonceEnabledCommandBuilder<T : NonceEnabledCommandBuilder<T, R>, R : Command> : HeaderEnabledCommandBuilder<T, R>() {
protected var nonce: Int? = null protected var nonce: Int? = null

View file

@ -17,10 +17,10 @@ object ProgramBasalUtil {
private const val MAX_NUMBER_OF_SLOTS_IN_INSULIN_PROGRAM_ELEMENT: Byte = 16 private const val MAX_NUMBER_OF_SLOTS_IN_INSULIN_PROGRAM_ELEMENT: Byte = 16
fun mapTenthPulsesPerSlotToLongInsulinProgramElements( fun mapTenthPulsesPerSlotToLongInsulinProgramElements(
tenthPulsesPerSlot: ShortArray?, tenthPulsesPerSlot: ShortArray,
insulinProgramElementFactory: (Byte, Byte, Short) -> BasalInsulinProgramElement = ::BasalInsulinProgramElement insulinProgramElementFactory: (Byte, Byte, Short) -> BasalInsulinProgramElement = ::BasalInsulinProgramElement
): List<BasalInsulinProgramElement> { ): List<BasalInsulinProgramElement> {
require(tenthPulsesPerSlot!!.size <= NUMBER_OF_BASAL_SLOTS) { "Basal program must contain at most 48 slots" } require(tenthPulsesPerSlot.size <= NUMBER_OF_BASAL_SLOTS) { "Basal program must contain at most 48 slots" }
val elements: MutableList<BasalInsulinProgramElement> = ArrayList() val elements: MutableList<BasalInsulinProgramElement> = ArrayList()
var previousTenthPulsesPerSlot: Short = 0 var previousTenthPulsesPerSlot: Short = 0
var numberOfSlotsInCurrentElement: Byte = 0 var numberOfSlotsInCurrentElement: Byte = 0

View file

@ -9,7 +9,7 @@ import kotlin.math.roundToInt
object ProgramTempBasalUtil { object ProgramTempBasalUtil {
fun mapTenthPulsesPerSlotToLongInsulinProgramElements(tenthPulsesPerSlot: ShortArray?): List<BasalInsulinProgramElement> { fun mapTenthPulsesPerSlotToLongInsulinProgramElements(tenthPulsesPerSlot: ShortArray): List<BasalInsulinProgramElement> {
return ProgramBasalUtil.mapTenthPulsesPerSlotToLongInsulinProgramElements(tenthPulsesPerSlot) { startSlotIndex: Byte, numberOfSlots: Byte, totalTenthPulses: Short -> TempBasalInsulinProgramElement(startSlotIndex, numberOfSlots, totalTenthPulses) } return ProgramBasalUtil.mapTenthPulsesPerSlotToLongInsulinProgramElements(tenthPulsesPerSlot) { startSlotIndex: Byte, numberOfSlots: Byte, totalTenthPulses: Short -> TempBasalInsulinProgramElement(startSlotIndex, numberOfSlots, totalTenthPulses) }
} }

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
enum class AlarmType( import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue
private val value: Byte
) { enum class AlarmType(override val value: Byte) : HasValue {
NONE(0x00.toByte()), NONE(0x00.toByte()),
ALARM_PW_FLASH_ERASE(0x01.toByte()), ALARM_PW_FLASH_ERASE(0x01.toByte()),
@ -160,15 +160,4 @@ enum class AlarmType(
ALARM_BLE_QN_CRIT_VAR_FAIL(0xc2.toByte()), ALARM_BLE_QN_CRIT_VAR_FAIL(0xc2.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
fun byValue(value: Byte): AlarmType {
for (type in values()) {
if (type.value == value) {
return type
}
}
return UNKNOWN
}
}
} }

View file

@ -26,7 +26,7 @@ class AlertConfiguration(
if (autoOff) { if (autoOff) {
firstByte = firstByte or (1 shl 1) firstByte = firstByte or (1 shl 1)
} }
firstByte = firstByte or ((durationInMinutes.toInt() shr 8 and 0x01).toByte()) //Todo bitstuff firstByte = firstByte or ((durationInMinutes.toInt() shr 8 and 0x01).toByte())
return ByteBuffer.allocate(6) // return ByteBuffer.allocate(6) //
.put(firstByte) .put(firstByte)
.put(durationInMinutes.toByte()) // .put(durationInMinutes.toByte()) //

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
enum class AlertSlot( import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue
val value: Byte
) { enum class AlertSlot(override val value: Byte) : HasValue {
AUTO_OFF(0x00.toByte()), AUTO_OFF(0x00.toByte()),
MULTI_COMMAND(0x01.toByte()), MULTI_COMMAND(0x01.toByte()),
@ -13,16 +13,4 @@ enum class AlertSlot(
SUSPEND_ENDED(0x06.toByte()), SUSPEND_ENDED(0x06.toByte()),
EXPIRATION(0x07.toByte()), EXPIRATION(0x07.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
fun byValue(value: Byte): AlertSlot {
for (slot in values()) {
if (slot.value == value) {
return slot
}
}
return UNKNOWN
}
}
} }

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
enum class DeliveryStatus( import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue
private val value: Byte
) { enum class DeliveryStatus(override val value: Byte) : HasValue {
SUSPENDED(0x00.toByte()), SUSPENDED(0x00.toByte()),
BASAL_ACTIVE(0x01.toByte()), BASAL_ACTIVE(0x01.toByte()),
@ -11,16 +11,4 @@ enum class DeliveryStatus(
BOLUS_AND_BASAL_ACTIVE(0x05.toByte()), BOLUS_AND_BASAL_ACTIVE(0x05.toByte()),
BOLUS_AND_TEMP_BASAL_ACTIVE(0x06.toByte()), BOLUS_AND_TEMP_BASAL_ACTIVE(0x06.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
fun byValue(value: Byte): DeliveryStatus {
for (status in values()) {
if (status.value == value) {
return status
}
}
return UNKNOWN
}
}
} }

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
enum class NakErrorType( import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue
private val value: Byte
) { enum class NakErrorType(override val value: Byte) : HasValue {
FLASH_WRITE(0x01.toByte()), FLASH_WRITE(0x01.toByte()),
FLASH_ERASE(0x02.toByte()), FLASH_ERASE(0x02.toByte()),
@ -34,16 +34,4 @@ enum class NakErrorType(
IGNORE_COMMAND(0x1c.toByte()), IGNORE_COMMAND(0x1c.toByte()),
INVALID_CRC(0x1d.toByte()), INVALID_CRC(0x1d.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
fun byValue(value: Byte): NakErrorType {
for (type in values()) {
if (type.value == value) {
return type
}
}
return UNKNOWN
}
}
} }

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition
enum class PodStatus( import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue
private val value: Byte
) { enum class PodStatus(override val value: Byte) : HasValue {
UNINITIALIZED(0x00.toByte()), UNINITIALIZED(0x00.toByte()),
MFG_TEST(0x01.toByte()), MFG_TEST(0x01.toByte()),
@ -22,17 +22,5 @@ enum class PodStatus(
DEACTIVATED(0x0f.toByte()), DEACTIVATED(0x0f.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
fun byValue(value: Byte): PodStatus {
for (status in values()) {
if (status.value == value) {
return status
}
}
return UNKNOWN
}
}
fun isRunning(): Boolean = this == RUNNING_ABOVE_MIN_VOLUME || this == RUNNING_BELOW_MIN_VOLUME fun isRunning(): Boolean = this == RUNNING_ABOVE_MIN_VOLUME || this == RUNNING_BELOW_MIN_VOLUME
} }

View file

@ -4,163 +4,68 @@ import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definitio
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus 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 info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.StatusResponseType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.StatusResponseType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.*
import kotlin.experimental.and import kotlin.experimental.and
class AlarmStatusResponse( class AlarmStatusResponse(
encoded: ByteArray encoded: ByteArray
) : AdditionalStatusResponseBase(StatusResponseType.ALARM_STATUS, encoded) { ) : AdditionalStatusResponseBase(StatusResponseType.ALARM_STATUS, encoded) {
private val messageType: Byte val messageType: Byte = encoded[0]
private val messageLength: Short val messageLength: Short = (encoded[1].toInt() and 0xff).toShort()
private val additionalStatusResponseType: Byte val additionalStatusResponseType: Byte = encoded[2]
private val podStatus: PodStatus val podStatus: PodStatus = byValue((encoded[3] and 0x0f), PodStatus.UNKNOWN)
private val deliveryStatus: DeliveryStatus val deliveryStatus: DeliveryStatus = byValue((encoded[4] and 0x0f), DeliveryStatus.UNKNOWN)
private val bolusPulsesRemaining: Short val bolusPulsesRemaining: Short = (ByteBuffer.wrap(byteArrayOf(encoded[5], encoded[6])).short and 2047)
private val sequenceNumberOfLastProgrammingCommand: Short val sequenceNumberOfLastProgrammingCommand: Short = (encoded[7] and 0x0f).toShort()
private val totalPulsesDelivered: Short val totalPulsesDelivered: Short = ByteBuffer.wrap(byteArrayOf(encoded[8], encoded[9])).short
private val alarmType: AlarmType val alarmType: AlarmType = byValue(encoded[10], AlarmType.UNKNOWN)
private val alarmTime: Short val alarmTime: Short = ByteBuffer.wrap(byteArrayOf(encoded[11], encoded[12])).short
private val reservoirPulsesRemaining: Short val reservoirPulsesRemaining: Short = ByteBuffer.wrap(byteArrayOf(encoded[13], encoded[14])).short
private val minutesSinceActivation: Short val minutesSinceActivation: Short = ByteBuffer.wrap(byteArrayOf(encoded[15], encoded[16])).short
private val alert0Active: Boolean val alert0Active: Boolean
private val alert1Active: Boolean val alert1Active: Boolean
private val alert2Active: Boolean val alert2Active: Boolean
private val alert3Active: Boolean val alert3Active: Boolean
private val alert4Active: Boolean val alert4Active: Boolean
private val alert5Active: Boolean val alert5Active: Boolean
private val alert6Active: Boolean val alert6Active: Boolean
private val alert7Active: Boolean val alert7Active: Boolean
private val occlusionAlarm: Boolean val occlusionAlarm: Boolean
private val pulseInfoInvalid: Boolean val pulseInfoInvalid: Boolean
private val podStatusWhenAlarmOccurred: PodStatus val podStatusWhenAlarmOccurred: PodStatus
private val immediateBolusWhenAlarmOccurred: Boolean val immediateBolusWhenAlarmOccurred: Boolean
private val occlusionType: Byte val occlusionType: Byte
private val occurredWhenFetchingImmediateBolusActiveInformation: Boolean val occurredWhenFetchingImmediateBolusActiveInformation: Boolean
private val rssi: Short val rssi: Short
private val receiverLowerGain: Short val receiverLowerGain: Short
private val podStatusWhenAlarmOccurred2: PodStatus val podStatusWhenAlarmOccurred2: PodStatus
private val returnAddressOfPodAlarmHandlerCaller: Short val returnAddressOfPodAlarmHandlerCaller: Short
fun getMessageType(): Byte { init {
return messageType val activeAlerts = encoded[17].toInt()
} alert0Active = activeAlerts and 1 == 1
alert1Active = activeAlerts ushr 1 and 1 == 1
fun getMessageLength(): Short { alert2Active = activeAlerts ushr 2 and 1 == 1
return messageLength alert3Active = activeAlerts ushr 3 and 1 == 1
} alert4Active = activeAlerts ushr 4 and 1 == 1
alert5Active = activeAlerts ushr 5 and 1 == 1
fun getAdditionalStatusResponseType(): Byte { alert6Active = activeAlerts ushr 6 and 1 == 1
return additionalStatusResponseType alert7Active = activeAlerts ushr 7 and 1 == 1
} val alarmFlags = encoded[18]
occlusionAlarm = (alarmFlags.toInt() and 1) == 1
fun getPodStatus(): PodStatus { pulseInfoInvalid = alarmFlags shr 1 and 1 == 1
return podStatus val byte19 = encoded[19]
} val byte20 = encoded[20]
podStatusWhenAlarmOccurred = byValue((byte19 and 0x0f), PodStatus.UNKNOWN)
fun getDeliveryStatus(): DeliveryStatus { immediateBolusWhenAlarmOccurred = byte19 shr 4 and 1 == 1
return deliveryStatus occlusionType = ((byte19 shr 5 and 3).toByte())
} occurredWhenFetchingImmediateBolusActiveInformation = byte19 shr 7 and 1 == 1
rssi = (byte20 and 0x3f).toShort()
fun getBolusPulsesRemaining(): Short { receiverLowerGain = ((byte20 shr 6 and 0x03).toShort())
return bolusPulsesRemaining podStatusWhenAlarmOccurred2 = byValue((encoded[21] and 0x0f), PodStatus.UNKNOWN)
} returnAddressOfPodAlarmHandlerCaller = ByteBuffer.wrap(byteArrayOf(encoded[22], encoded[23])).short
fun getSequenceNumberOfLastProgrammingCommand(): Short {
return sequenceNumberOfLastProgrammingCommand
}
fun getTotalPulsesDelivered(): Short {
return totalPulsesDelivered
}
fun getAlarmType(): AlarmType {
return alarmType
}
fun getAlarmTime(): Short {
return alarmTime
}
fun getReservoirPulsesRemaining(): Short {
return reservoirPulsesRemaining
}
fun getMinutesSinceActivation(): Short {
return minutesSinceActivation
}
fun isAlert0Active(): Boolean {
return alert0Active
}
fun isAlert1Active(): Boolean {
return alert1Active
}
fun isAlert2Active(): Boolean {
return alert2Active
}
fun isAlert3Active(): Boolean {
return alert3Active
}
fun isAlert4Active(): Boolean {
return alert4Active
}
fun isAlert5Active(): Boolean {
return alert5Active
}
fun isAlert6Active(): Boolean {
return alert6Active
}
fun isAlert7Active(): Boolean {
return alert7Active
}
fun isOcclusionAlarm(): Boolean {
return occlusionAlarm
}
fun isPulseInfoInvalid(): Boolean {
return pulseInfoInvalid
}
fun getPodStatusWhenAlarmOccurred(): PodStatus {
return podStatusWhenAlarmOccurred
}
fun isImmediateBolusWhenAlarmOccurred(): Boolean {
return immediateBolusWhenAlarmOccurred
}
fun getOcclusionType(): Byte {
return occlusionType
}
fun isOccurredWhenFetchingImmediateBolusActiveInformation(): Boolean {
return occurredWhenFetchingImmediateBolusActiveInformation
}
fun getRssi(): Short {
return rssi
}
fun getReceiverLowerGain(): Short {
return receiverLowerGain
}
fun getPodStatusWhenAlarmOccurred2(): PodStatus {
return podStatusWhenAlarmOccurred2
}
fun getReturnAddressOfPodAlarmHandlerCaller(): Short {
return returnAddressOfPodAlarmHandlerCaller
} }
override fun toString(): String { override fun toString(): String {
@ -197,52 +102,11 @@ class AlarmStatusResponse(
", returnAddressOfPodAlarmHandlerCaller=" + returnAddressOfPodAlarmHandlerCaller + ", returnAddressOfPodAlarmHandlerCaller=" + returnAddressOfPodAlarmHandlerCaller +
", statusResponseType=" + statusResponseType + ", statusResponseType=" + statusResponseType +
", responseType=" + responseType + ", responseType=" + responseType +
", encoded=" + Arrays.toString(encoded) + ", encoded=" + encoded.contentToString() +
'}' '}'
} }
init { infix fun Byte.shr(i: Int): Int = toInt() shr i
messageType = encoded[0]
messageLength = (encoded[1].toInt() and 0xff).toShort()
additionalStatusResponseType = encoded[2]
podStatus = PodStatus.byValue((encoded[3] and 0x0f))
deliveryStatus = DeliveryStatus.byValue((encoded[4] and 0x0f))
bolusPulsesRemaining = (ByteBuffer.wrap(byteArrayOf(encoded[5], encoded[6])).short and 2047)
sequenceNumberOfLastProgrammingCommand = (encoded[7] and 0x0f).toShort()
totalPulsesDelivered = ByteBuffer.wrap(byteArrayOf(encoded[8], encoded[9])).short
alarmType = AlarmType.byValue(encoded[10])
alarmTime = ByteBuffer.wrap(byteArrayOf(encoded[11], encoded[12])).short
reservoirPulsesRemaining = ByteBuffer.wrap(byteArrayOf(encoded[13], encoded[14])).short
minutesSinceActivation = ByteBuffer.wrap(byteArrayOf(encoded[15], encoded[16])).short
val activeAlerts = encoded[17].toInt() // TODO: toInt()?
alert0Active = activeAlerts and 1 == 1
alert1Active = activeAlerts ushr 1 and 1 == 1
alert2Active = activeAlerts ushr 2 and 1 == 1
alert3Active = activeAlerts ushr 3 and 1 == 1
alert4Active = activeAlerts ushr 4 and 1 == 1
alert5Active = activeAlerts ushr 5 and 1 == 1
alert6Active = activeAlerts ushr 6 and 1 == 1
alert7Active = activeAlerts ushr 7 and 1 == 1
val alarmFlags = encoded[18]
occlusionAlarm = (alarmFlags.toInt() and 1) == 1
pulseInfoInvalid = alarmFlags shr 1 and 1 == 1
val byte19 = encoded[19]
val byte20 = encoded[20]
podStatusWhenAlarmOccurred = PodStatus.byValue((byte19 and 0x0f))
immediateBolusWhenAlarmOccurred = byte19 shr 4 and 1 == 1
occlusionType = ((byte19 shr 5 and 3).toByte())
occurredWhenFetchingImmediateBolusActiveInformation = byte19 shr 7 and 1 == 1
rssi = (byte20 and 0x3f).toShort()
receiverLowerGain = ((byte20 shr 6 and 0x03).toShort())
podStatusWhenAlarmOccurred2 = PodStatus.byValue((encoded[21] and 0x0f))
returnAddressOfPodAlarmHandlerCaller = ByteBuffer.wrap(byteArrayOf(encoded[22], encoded[23])).short
}
//TODO autoconvert to Int ok?
private infix fun Byte.ushr(i: Int) = toInt() ushr i
private infix fun Short.shr(i: Int): Int = toInt() shr i
private infix fun Byte.shl(i: Int): Int = toInt() shl i
private infix fun Byte.shr(i: Int): Int = toInt() shr i
} }

View file

@ -2,93 +2,30 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.DeliveryStatus 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 info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
import kotlin.experimental.and import kotlin.experimental.and
class DefaultStatusResponse( class DefaultStatusResponse(
encoded: ByteArray encoded: ByteArray
) : ResponseBase(ResponseType.DEFAULT_STATUS_RESPONSE, encoded) { ) : ResponseBase(ResponseType.DEFAULT_STATUS_RESPONSE, encoded) {
// TODO: Here is a lot of bitshifting that had to be changed. we should go over it. val messageType: Byte = encoded[0]
private val messageType: Byte = encoded[0] val deliveryStatus: DeliveryStatus = byValue((encoded[1].toInt() shr 4 and 0x0f).toByte(), DeliveryStatus.UNKNOWN)
private val deliveryStatus: DeliveryStatus = DeliveryStatus.byValue((encoded[1].toInt() shr 4 and 0x0f).toByte()) val podStatus: PodStatus = byValue((encoded[1] and 0x0f), PodStatus.UNKNOWN)
private val podStatus: PodStatus = PodStatus.byValue((encoded[1] and 0x0f) as Byte) val totalPulsesDelivered: Short = ((encoded[2] and 0x0f shl 12 or (encoded[3].toInt() and 0xff shl 1) or (encoded[4].toInt() and 0xff ushr 7)).toShort())
private val totalPulsesDelivered: Short = ((encoded[2] and 0x0f shl 12 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()
private 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 val bolusPulsesRemaining: Short = ((encoded[4] and 0x07 shl 10 or (encoded[5].toInt() and 0xff) and 2047).toShort()) val activeAlerts = (encoded[6].toInt() and 0xff shl 1 or (encoded[7] ushr 7)).toShort()
private val activeAlerts = (encoded[6].toInt() and 0xff shl 1 or (encoded[7] ushr 7)).toShort() val occlusionAlertActive: Boolean = (activeAlerts and 1).toInt() == 1
private val occlusionAlertActive: Boolean = (activeAlerts and 1).toInt() == 1 val alert1Active: Boolean = activeAlerts shr 1 and 1 == 1
private val alert1Active: Boolean = activeAlerts shr 1 and 1 == 1 val alert2Active: Boolean = activeAlerts shr 2 and 1 == 1
private val alert2Active: Boolean = activeAlerts shr 2 and 1 == 1 val alert3Active: Boolean = activeAlerts shr 3 and 1 == 1
private val alert3Active: Boolean = activeAlerts shr 3 and 1 == 1 val alert4Active: Boolean = activeAlerts shr 4 and 1 == 1
private val alert4Active: Boolean = activeAlerts shr 4 and 1 == 1 val alert5Active: Boolean = activeAlerts shr 5 and 1 == 1
private val alert5Active: Boolean = activeAlerts shr 5 and 1 == 1 val alert6Active: Boolean = activeAlerts shr 6 and 1 == 1
private val alert6Active: Boolean = activeAlerts shr 6 and 1 == 1 val alert7Active: Boolean = activeAlerts shr 7 and 1 == 1
private val alert7Active: Boolean = activeAlerts shr 7 and 1 == 1 val minutesSinceActivation: Short = (encoded[7] and 0x7f shl 6 or (encoded[8].toInt() and 0xff ushr 2 and 0x3f)).toShort()
private 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 0x3ff).toShort()
private val reservoirPulsesRemaining: Short = (encoded[8] shl 8 or encoded[9].toInt() and 0x3ff).toShort()
fun getMessageType(): Byte {
return messageType
}
fun getDeliveryStatus(): DeliveryStatus {
return deliveryStatus
}
fun getPodStatus(): PodStatus {
return podStatus
}
fun getTotalPulsesDelivered(): Short {
return totalPulsesDelivered
}
fun getSequenceNumberOfLastProgrammingCommand(): Short {
return sequenceNumberOfLastProgrammingCommand
}
fun getBolusPulsesRemaining(): Short {
return bolusPulsesRemaining
}
fun isOcclusionAlertActive(): Boolean {
return occlusionAlertActive
}
fun isAlert1Active(): Boolean {
return alert1Active
}
fun isAlert2Active(): Boolean {
return alert2Active
}
fun isAlert3Active(): Boolean {
return alert3Active
}
fun isAlert4Active(): Boolean {
return alert4Active
}
fun isAlert5Active(): Boolean {
return alert5Active
}
fun isAlert6Active(): Boolean {
return alert6Active
}
fun isAlert7Active(): Boolean {
return alert7Active
}
fun getMinutesSinceActivation(): Short {
return minutesSinceActivation
}
fun getReservoirPulsesRemaining(): Short {
return reservoirPulsesRemaining
}
override fun toString(): String { override fun toString(): String {
return "DefaultStatusResponse{" + return "DefaultStatusResponse{" +
@ -114,7 +51,6 @@ class DefaultStatusResponse(
} }
} }
//TODO autoconvert to Int ok? infix fun Byte.ushr(i: Int) = toInt() ushr i
private infix fun Byte.ushr(i: Int) = toInt() ushr i infix fun Short.shr(i: Int): Int = toInt() shr i
private infix fun Short.shr(i: Int): Int = toInt() shr i infix fun Byte.shl(i: Int): Int = toInt() shl i
private infix fun Byte.shl(i: Int): Int = toInt() shl i

View file

@ -3,39 +3,35 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlarmType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.AlarmType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.NakErrorType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.NakErrorType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
class NakResponse( class NakResponse(
encoded: ByteArray encoded: ByteArray
) : ResponseBase(ResponseType.NAK_RESPONSE, encoded) { ) : ResponseBase(ResponseType.NAK_RESPONSE, encoded) {
private val messageType: Byte // TODO directly assign here val messageType: Byte = encoded[0]
private val messageLength: Short val messageLength: Short = encoded[1].toShort()
private val nakErrorType: NakErrorType val nakErrorType: NakErrorType = byValue(encoded[2], NakErrorType.UNKNOWN)
private var alarmType: AlarmType? = null var alarmType: AlarmType? = null
private var podStatus: PodStatus? = null private set
private var securityNakSyncCount: Short = 0 var podStatus: PodStatus? = null
fun getMessageType(): Byte { private set
return messageType
}
fun getMessageLength(): Short { var securityNakSyncCount: Short = 0
return messageLength private set
}
fun getNakErrorType(): NakErrorType { // TODO make public, a val cannot be reassigned, same for other Responses init {
return nakErrorType val byte3 = encoded[3]
val byte4 = encoded[4]
if (nakErrorType == NakErrorType.ILLEGAL_SECURITY_CODE) {
securityNakSyncCount = ((byte3.toInt() shl 8 or byte4.toInt()).toShort())
alarmType = null
podStatus = null
} else {
securityNakSyncCount = 0
alarmType = byValue(byte3, AlarmType.UNKNOWN)
podStatus = byValue(byte4, PodStatus.UNKNOWN)
} }
fun getAlarmType(): AlarmType? {
return alarmType
}
fun getPodStatus(): PodStatus? {
return podStatus
}
fun getSecurityNakSyncCount(): Short {
return securityNakSyncCount
} }
override fun toString(): String { override fun toString(): String {
@ -50,21 +46,4 @@ class NakResponse(
", encoded=" + encoded.contentToString() + ", encoded=" + encoded.contentToString() +
'}' '}'
} }
init {
messageType = encoded[0]
messageLength = encoded[1].toShort()
nakErrorType = NakErrorType.byValue(encoded[2])
val byte3 = encoded[3]
val byte4 = encoded[4]
if (nakErrorType == NakErrorType.ILLEGAL_SECURITY_CODE) {
securityNakSyncCount = ((byte3.toInt() shl 8 or byte4.toInt()).toShort()) // TODO: toInt()
alarmType = null
podStatus = null
} else {
securityNakSyncCount = 0
alarmType = AlarmType.byValue(byte3)
podStatus = PodStatus.byValue(byte4)
}
}
} }

View file

@ -1,8 +1,8 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
enum class ResponseType( import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.HasValue
val value: Byte
) { enum class ResponseType(override val value: Byte) : HasValue {
ACTIVATION_RESPONSE(0x01.toByte()), ACTIVATION_RESPONSE(0x01.toByte()),
DEFAULT_STATUS_RESPONSE(0x1d.toByte()), DEFAULT_STATUS_RESPONSE(0x1d.toByte()),
@ -10,9 +10,7 @@ enum class ResponseType(
NAK_RESPONSE(0x06.toByte()), NAK_RESPONSE(0x06.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
enum class StatusResponseType( enum class StatusResponseType(override val value: Byte) : HasValue {
val value: Byte
) {
DEFAULT_STATUS_RESPONSE(0x00.toByte()), DEFAULT_STATUS_RESPONSE(0x00.toByte()),
STATUS_RESPONSE_PAGE_1(0x01.toByte()), STATUS_RESPONSE_PAGE_1(0x01.toByte()),
@ -24,53 +22,12 @@ enum class ResponseType(
STATUS_RESPONSE_PAGE_80(0x50.toByte()), STATUS_RESPONSE_PAGE_80(0x50.toByte()),
STATUS_RESPONSE_PAGE_81(0x51.toByte()), STATUS_RESPONSE_PAGE_81(0x51.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
@JvmStatic
fun byValue(value: Byte): StatusResponseType {
for (type in values()) {
if (type.value == value) {
return type
}
}
return UNKNOWN
}
}
} }
enum class ActivationResponseType( enum class ActivationResponseType(override val value: Byte) : HasValue {
val length: Byte
) {
GET_VERSION_RESPONSE(0x15.toByte()), GET_VERSION_RESPONSE(0x15.toByte()),
SET_UNIQUE_ID_RESPONSE(0x1b.toByte()), SET_UNIQUE_ID_RESPONSE(0x1b.toByte()),
UNKNOWN(0xff.toByte()); UNKNOWN(0xff.toByte());
companion object {
@JvmStatic
fun byLength(length: Byte): ActivationResponseType {
for (type in values()) {
if (type.length == length) {
return type
}
}
return UNKNOWN
}
}
}
companion object {
@JvmStatic
fun byValue(value: Byte): ResponseType {
for (type in values()) {
if (type.value == value) {
return type
}
}
return UNKNOWN
}
} }
} }

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
import java.nio.ByteBuffer import java.nio.ByteBuffer
class SetUniqueIdResponse( class SetUniqueIdResponse(
@ -147,7 +148,7 @@ class SetUniqueIdResponse(
bleVersionMinor = (encoded[13].toInt() and 0xff).toShort() bleVersionMinor = (encoded[13].toInt() and 0xff).toShort()
bleVersionInterim = (encoded[14].toInt() and 0xff).toShort() bleVersionInterim = (encoded[14].toInt() and 0xff).toShort()
productId = (encoded[15].toInt() and 0xff).toShort() productId = (encoded[15].toInt() and 0xff).toShort()
podStatus = PodStatus.byValue(encoded[16]) podStatus = byValue(encoded[16], PodStatus.UNKNOWN)
lotNumber = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[17], encoded[18], encoded[19], encoded[20])).long lotNumber = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[17], encoded[18], encoded[19], encoded[20])).long
podSequenceNumber = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[21], encoded[22], encoded[23], encoded[24])).long podSequenceNumber = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[21], encoded[22], encoded[23], encoded[24])).long
uniqueIdReceivedInCommand = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[25], encoded[26], encoded[27], encoded[28])).long uniqueIdReceivedInCommand = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[25], encoded[26], encoded[27], encoded[28])).long

View file

@ -2,6 +2,7 @@ package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.definition.PodStatus
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.response.ResponseType.ActivationResponseType
import info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util.byValue
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.util.* import java.util.*
import kotlin.experimental.and import kotlin.experimental.and
@ -19,7 +20,7 @@ class VersionResponse(
private val bleVersionMinor: Short = (encoded[6].toInt() and 0xff).toShort() private val bleVersionMinor: Short = (encoded[6].toInt() and 0xff).toShort()
private val bleVersionInterim: Short = (encoded[7].toInt() and 0xff).toShort() private val bleVersionInterim: Short = (encoded[7].toInt() and 0xff).toShort()
private val productId: Short = (encoded[8].toInt() and 0xff).toShort() private val productId: Short = (encoded[8].toInt() and 0xff).toShort()
private val podStatus: PodStatus = PodStatus.byValue((encoded[9] and 0xf)) private val podStatus: PodStatus = byValue((encoded[9] and 0xf), PodStatus.UNKNOWN)
private val lotNumber: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[10], encoded[11], encoded[12], encoded[13])).long private val lotNumber: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[10], encoded[11], encoded[12], encoded[13])).long
private val podSequenceNumber: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[14], encoded[15], encoded[16], encoded[17])).long private val podSequenceNumber: Long = ByteBuffer.wrap(byteArrayOf(0, 0, 0, 0, encoded[14], encoded[15], encoded[16], encoded[17])).long
private val rssi: Byte = (encoded[18] and 0x3f) private val rssi: Byte = (encoded[18] and 0x3f)

View file

@ -34,6 +34,8 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
store() store()
} }
// TODO: dynamic get() fun instead of assignment
override val isUniqueIdSet: Boolean = activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID) override val isUniqueIdSet: Boolean = activationProgress.isAtLeast(ActivationProgress.SET_UNIQUE_ID)
override val isActivationCompleted: Boolean = activationProgress == ActivationProgress.COMPLETED override val isActivationCompleted: Boolean = activationProgress == ActivationProgress.COMPLETED
@ -105,17 +107,17 @@ class OmnipodDashPodStateManagerImpl @Inject constructor(
} }
override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) { override fun updateFromDefaultStatusResponse(response: DefaultStatusResponse) {
podState.deliveryStatus = response.getDeliveryStatus() podState.deliveryStatus = response.deliveryStatus
podState.podStatus = response.getPodStatus() podState.podStatus = response.podStatus
podState.pulsesDelivered = response.getTotalPulsesDelivered() podState.pulsesDelivered = response.totalPulsesDelivered
podState.pulsesRemaining = response.getReservoirPulsesRemaining() podState.pulsesRemaining = response.reservoirPulsesRemaining
podState.sequenceNumberOfLastProgrammingCommand = response.getSequenceNumberOfLastProgrammingCommand() podState.sequenceNumberOfLastProgrammingCommand = response.sequenceNumberOfLastProgrammingCommand
podState.minutesSinceActivation = response.getMinutesSinceActivation() podState.minutesSinceActivation = response.minutesSinceActivation
// TODO active alerts // TODO active alerts
podState.lastUpdated = System.currentTimeMillis() podState.lastUpdated = System.currentTimeMillis()
store(); store()
} }
override fun updateFromVersionResponse(response: VersionResponse) { override fun updateFromVersionResponse(response: VersionResponse) {

View file

@ -0,0 +1,10 @@
package info.nightscout.androidaps.plugins.pump.omnipod.dash.driver.pod.util
interface HasValue {
val value: Byte
}
inline fun <reified T> byValue(value: Byte, default: T): T where T : Enum<T>, T : HasValue {
return enumValues<T>().firstOrNull { it.value == value } ?: default
}

View file

@ -14,7 +14,7 @@ object MessageUtil {
val b = sArr[s.toInt()].toByte() val b = sArr[s.toInt()].toByte()
var s2 = b.toShort() var s2 = b.toShort()
if (b < 0) { if (b < 0) {
s2 = ((b and Byte.MAX_VALUE) as Byte + 128).toShort() s2 = ((b and Byte.MAX_VALUE) + 128).toShort()
} }
i += s2.toInt() i += s2.toInt()
s = (s + 1).toShort() s = (s + 1).toShort()
@ -28,7 +28,7 @@ object MessageUtil {
val b2 = (b xor (s and 255).toByte()) // TODO byte conversion ok? val b2 = (b xor (s and 255).toByte()) // TODO byte conversion ok?
var s2 = b2.toShort() var s2 = b2.toShort()
if (b2 < 0) { if (b2 < 0) {
s2 = ((b2 and Byte.MAX_VALUE) as Byte + 128).toShort() s2 = ((b2 and Byte.MAX_VALUE) + 128).toShort()
} }
s = (((s.toInt() shr 8).toShort() and 255) xor crc16table[s2.toInt()]) s = (((s.toInt() shr 8).toShort() and 255) xor crc16table[s2.toInt()])
} }

View file

@ -17,35 +17,35 @@ class AlarmStatusResponseTest {
Assert.assertArrayEquals(encoded, response.encoded) Assert.assertArrayEquals(encoded, response.encoded)
Assert.assertNotSame(encoded, response.encoded) Assert.assertNotSame(encoded, response.encoded)
Assert.assertEquals(ResponseType.ADDITIONAL_STATUS_RESPONSE, response.responseType) Assert.assertEquals(ResponseType.ADDITIONAL_STATUS_RESPONSE, response.responseType)
Assert.assertEquals(ResponseType.ADDITIONAL_STATUS_RESPONSE.value, response.getMessageType()) Assert.assertEquals(ResponseType.ADDITIONAL_STATUS_RESPONSE.value, response.messageType)
Assert.assertEquals(ResponseType.StatusResponseType.ALARM_STATUS, response.statusResponseType) Assert.assertEquals(ResponseType.StatusResponseType.ALARM_STATUS, response.statusResponseType)
Assert.assertEquals(ResponseType.StatusResponseType.ALARM_STATUS.value, response.getAdditionalStatusResponseType()) Assert.assertEquals(ResponseType.StatusResponseType.ALARM_STATUS.value, response.additionalStatusResponseType)
Assert.assertEquals(PodStatus.RUNNING_ABOVE_MIN_VOLUME, response.getPodStatus()) Assert.assertEquals(PodStatus.RUNNING_ABOVE_MIN_VOLUME, response.podStatus)
Assert.assertEquals(DeliveryStatus.BASAL_ACTIVE, response.getDeliveryStatus()) Assert.assertEquals(DeliveryStatus.BASAL_ACTIVE, response.deliveryStatus)
Assert.assertEquals(0.toShort(), response.getBolusPulsesRemaining()) Assert.assertEquals(0.toShort(), response.bolusPulsesRemaining)
Assert.assertEquals(5.toShort(), response.getSequenceNumberOfLastProgrammingCommand()) Assert.assertEquals(5.toShort(), response.sequenceNumberOfLastProgrammingCommand)
Assert.assertEquals(445.toShort(), response.getTotalPulsesDelivered()) Assert.assertEquals(445.toShort(), response.totalPulsesDelivered)
Assert.assertEquals(AlarmType.NONE, response.getAlarmType()) Assert.assertEquals(AlarmType.NONE, response.alarmType)
Assert.assertEquals(0.toShort(), response.getAlarmTime()) Assert.assertEquals(0.toShort(), response.alarmTime)
Assert.assertEquals(1023.toShort(), response.getReservoirPulsesRemaining()) Assert.assertEquals(1023.toShort(), response.reservoirPulsesRemaining)
Assert.assertEquals(405.toShort(), response.getMinutesSinceActivation()) Assert.assertEquals(405.toShort(), response.minutesSinceActivation)
Assert.assertFalse(response.isAlert0Active()) Assert.assertFalse(response.alert0Active)
Assert.assertFalse(response.isAlert1Active()) Assert.assertFalse(response.alert1Active)
Assert.assertFalse(response.isAlert2Active()) Assert.assertFalse(response.alert2Active)
Assert.assertFalse(response.isAlert3Active()) Assert.assertFalse(response.alert3Active)
Assert.assertFalse(response.isAlert4Active()) Assert.assertFalse(response.alert4Active)
Assert.assertFalse(response.isAlert5Active()) Assert.assertFalse(response.alert5Active)
Assert.assertFalse(response.isAlert6Active()) Assert.assertFalse(response.alert6Active)
Assert.assertFalse(response.isAlert7Active()) Assert.assertFalse(response.alert7Active)
Assert.assertFalse(response.isOcclusionAlarm()) Assert.assertFalse(response.occlusionAlarm)
Assert.assertFalse(response.isPulseInfoInvalid()) Assert.assertFalse(response.pulseInfoInvalid)
Assert.assertEquals(PodStatus.UNINITIALIZED, response.getPodStatusWhenAlarmOccurred()) Assert.assertEquals(PodStatus.UNINITIALIZED, response.podStatusWhenAlarmOccurred)
Assert.assertFalse(response.isImmediateBolusWhenAlarmOccurred()) Assert.assertFalse(response.immediateBolusWhenAlarmOccurred)
Assert.assertEquals(0x00.toByte(), response.getOcclusionType()) Assert.assertEquals(0x00.toByte(), response.occlusionType)
Assert.assertFalse(response.isOccurredWhenFetchingImmediateBolusActiveInformation()) Assert.assertFalse(response.occurredWhenFetchingImmediateBolusActiveInformation)
Assert.assertEquals(0.toShort(), response.getRssi()) Assert.assertEquals(0.toShort(), response.rssi)
Assert.assertEquals(0.toShort(), response.getReceiverLowerGain()) Assert.assertEquals(0.toShort(), response.receiverLowerGain)
Assert.assertEquals(PodStatus.UNINITIALIZED, response.getPodStatusWhenAlarmOccurred2()) Assert.assertEquals(PodStatus.UNINITIALIZED, response.podStatusWhenAlarmOccurred2)
Assert.assertEquals(26378.toShort(), response.getReturnAddressOfPodAlarmHandlerCaller()) Assert.assertEquals(26378.toShort(), response.returnAddressOfPodAlarmHandlerCaller)
} }
} }

View file

@ -16,21 +16,21 @@ class DefaultStatusResponseTest {
Assert.assertArrayEquals(encoded, response.encoded) Assert.assertArrayEquals(encoded, response.encoded)
Assert.assertNotSame(encoded, response.encoded) Assert.assertNotSame(encoded, response.encoded)
Assert.assertEquals(ResponseType.DEFAULT_STATUS_RESPONSE, response.responseType) Assert.assertEquals(ResponseType.DEFAULT_STATUS_RESPONSE, response.responseType)
Assert.assertEquals(ResponseType.DEFAULT_STATUS_RESPONSE.value, response.getMessageType()) Assert.assertEquals(ResponseType.DEFAULT_STATUS_RESPONSE.value, response.messageType)
Assert.assertEquals(DeliveryStatus.BASAL_ACTIVE, response.getDeliveryStatus()) Assert.assertEquals(DeliveryStatus.BASAL_ACTIVE, response.deliveryStatus)
Assert.assertEquals(PodStatus.RUNNING_ABOVE_MIN_VOLUME, response.getPodStatus()) Assert.assertEquals(PodStatus.RUNNING_ABOVE_MIN_VOLUME, response.podStatus)
Assert.assertEquals(320.toShort(), response.getTotalPulsesDelivered()) Assert.assertEquals(320.toShort(), response.totalPulsesDelivered)
Assert.assertEquals(5.toShort(), response.getSequenceNumberOfLastProgrammingCommand()) Assert.assertEquals(5.toShort(), response.sequenceNumberOfLastProgrammingCommand)
Assert.assertEquals(0.toShort(), response.getBolusPulsesRemaining()) Assert.assertEquals(0.toShort(), response.bolusPulsesRemaining)
Assert.assertFalse(response.isOcclusionAlertActive()) Assert.assertFalse(response.occlusionAlertActive)
Assert.assertFalse(response.isAlert1Active()) Assert.assertFalse(response.alert1Active)
Assert.assertFalse(response.isAlert2Active()) Assert.assertFalse(response.alert2Active)
Assert.assertFalse(response.isAlert3Active()) Assert.assertFalse(response.alert3Active)
Assert.assertFalse(response.isAlert4Active()) Assert.assertFalse(response.alert4Active)
Assert.assertFalse(response.isAlert5Active()) Assert.assertFalse(response.alert5Active)
Assert.assertFalse(response.isAlert6Active()) Assert.assertFalse(response.alert6Active)
Assert.assertFalse(response.isAlert7Active()) Assert.assertFalse(response.alert7Active)
Assert.assertEquals(280.toShort(), response.getMinutesSinceActivation()) Assert.assertEquals(280.toShort(), response.minutesSinceActivation)
Assert.assertEquals(1023.toShort(), response.getReservoirPulsesRemaining()) Assert.assertEquals(1023.toShort(), response.reservoirPulsesRemaining)
} }
} }

View file

@ -18,10 +18,10 @@ class NakResponseTest {
Assert.assertArrayEquals(encoded, response.encoded) Assert.assertArrayEquals(encoded, response.encoded)
Assert.assertNotSame(encoded, response.encoded) Assert.assertNotSame(encoded, response.encoded)
Assert.assertEquals(ResponseType.NAK_RESPONSE, response.responseType) Assert.assertEquals(ResponseType.NAK_RESPONSE, response.responseType)
Assert.assertEquals(ResponseType.NAK_RESPONSE.value, response.getMessageType()) Assert.assertEquals(ResponseType.NAK_RESPONSE.value, response.messageType)
Assert.assertEquals(NakErrorType.ILLEGAL_PARAM, response.getNakErrorType()) Assert.assertEquals(NakErrorType.ILLEGAL_PARAM, response.nakErrorType)
Assert.assertEquals(AlarmType.NONE, response.getAlarmType()) Assert.assertEquals(AlarmType.NONE, response.alarmType)
Assert.assertEquals(PodStatus.RUNNING_BELOW_MIN_VOLUME, response.getPodStatus()) Assert.assertEquals(PodStatus.RUNNING_BELOW_MIN_VOLUME, response.podStatus)
Assert.assertEquals(0x00.toShort(), response.getSecurityNakSyncCount()) Assert.assertEquals(0x00.toShort(), response.securityNakSyncCount)
} }
} }